Merge "Fix View padding resolution"
diff --git a/api/16.txt b/api/16.txt
index 357d618..6543ab0 100644
--- a/api/16.txt
+++ b/api/16.txt
@@ -7144,7 +7144,7 @@
     method public abstract void setBindArguments(java.lang.String[]);
   }
 
-  public class SQLiteDatabase extends android.database.sqlite.SQLiteClosable {
+  public final class SQLiteDatabase extends android.database.sqlite.SQLiteClosable {
     method public void beginTransaction();
     method public void beginTransactionNonExclusive();
     method public void beginTransactionWithListener(android.database.sqlite.SQLiteTransactionListener);
diff --git a/api/current.txt b/api/current.txt
index d683da1..dbe57d1 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -247,7 +247,7 @@
     field public static final int animationCache = 16842989; // 0x10100ed
     field public static final int animationDuration = 16843026; // 0x1010112
     field public static final int animationOrder = 16843214; // 0x10101ce
-    field public static final int animationResolution = 16843546; // 0x101031a
+    field public static final deprecated int animationResolution = 16843546; // 0x101031a
     field public static final int antialias = 16843034; // 0x101011a
     field public static final int anyDensity = 16843372; // 0x101026c
     field public static final int apiKey = 16843281; // 0x1010211
@@ -414,7 +414,7 @@
     field public static final int ems = 16843096; // 0x1010158
     field public static final deprecated int enabled = 16842766; // 0x101000e
     field public static final int endColor = 16843166; // 0x101019e
-    field public static final int endYear = 16843133; // 0x101017d
+    field public static final deprecated int endYear = 16843133; // 0x101017d
     field public static final int enterFadeDuration = 16843532; // 0x101030c
     field public static final int entries = 16842930; // 0x10100b2
     field public static final int entryValues = 16843256; // 0x10101f8
@@ -888,7 +888,7 @@
     field public static final int starStyle = 16842882; // 0x1010082
     field public static final int startColor = 16843165; // 0x101019d
     field public static final int startOffset = 16843198; // 0x10101be
-    field public static final int startYear = 16843132; // 0x101017c
+    field public static final deprecated int startYear = 16843132; // 0x101017c
     field public static final int stateNotNeeded = 16842774; // 0x1010016
     field public static final int state_above_anchor = 16842922; // 0x10100aa
     field public static final int state_accelerated = 16843547; // 0x101031b
@@ -2722,6 +2722,7 @@
     method public int getLauncherLargeIconSize();
     method public int getMemoryClass();
     method public void getMemoryInfo(android.app.ActivityManager.MemoryInfo);
+    method public static void getMyMemoryState(android.app.ActivityManager.RunningAppProcessInfo);
     method public android.os.Debug.MemoryInfo[] getProcessMemoryInfo(int[]);
     method public java.util.List<android.app.ActivityManager.ProcessErrorStateInfo> getProcessesInErrorState();
     method public java.util.List<android.app.ActivityManager.RecentTaskInfo> getRecentTasks(int, int) throws java.lang.SecurityException;
@@ -2804,6 +2805,7 @@
     field public int importanceReasonCode;
     field public android.content.ComponentName importanceReasonComponent;
     field public int importanceReasonPid;
+    field public int lastTrimLevel;
     field public int lru;
     field public int pid;
     field public java.lang.String[] pkgList;
@@ -4826,6 +4828,9 @@
     field public static final int TRIM_MEMORY_BACKGROUND = 40; // 0x28
     field public static final int TRIM_MEMORY_COMPLETE = 80; // 0x50
     field public static final int TRIM_MEMORY_MODERATE = 60; // 0x3c
+    field public static final int TRIM_MEMORY_RUNNING_CRITICAL = 15; // 0xf
+    field public static final int TRIM_MEMORY_RUNNING_LOW = 10; // 0xa
+    field public static final int TRIM_MEMORY_RUNNING_MODERATE = 5; // 0x5
     field public static final int TRIM_MEMORY_UI_HIDDEN = 20; // 0x14
   }
 
@@ -6904,7 +6909,7 @@
     method public boolean onMove(int, int);
   }
 
-  public abstract interface Cursor {
+  public abstract interface Cursor implements java.io.Closeable {
     method public abstract void close();
     method public abstract void copyStringToBuffer(int, android.database.CharArrayBuffer);
     method public abstract deprecated void deactivate();
@@ -6977,7 +6982,6 @@
     ctor public deprecated CursorWindow(boolean);
     method public boolean allocRow();
     method public void clear();
-    method public void close();
     method public void copyStringToBuffer(int, int, android.database.CharArrayBuffer);
     method public int describeContents();
     method public void freeLastRow();
@@ -7236,13 +7240,14 @@
     ctor public SQLiteCantOpenDatabaseException(java.lang.String);
   }
 
-  public abstract class SQLiteClosable {
+  public abstract class SQLiteClosable implements java.io.Closeable {
     ctor public SQLiteClosable();
     method public void acquireReference();
+    method public void close();
     method protected abstract void onAllReferencesReleased();
-    method protected void onAllReferencesReleasedFromContainer();
+    method protected deprecated void onAllReferencesReleasedFromContainer();
     method public void releaseReference();
-    method public void releaseReferenceFromContainer();
+    method public deprecated void releaseReferenceFromContainer();
   }
 
   public class SQLiteConstraintException extends android.database.sqlite.SQLiteException {
@@ -7267,15 +7272,15 @@
     method public abstract void setBindArguments(java.lang.String[]);
   }
 
-  public class SQLiteDatabase extends android.database.sqlite.SQLiteClosable {
+  public final class SQLiteDatabase extends android.database.sqlite.SQLiteClosable {
     method public void beginTransaction();
     method public void beginTransactionNonExclusive();
     method public void beginTransactionWithListener(android.database.sqlite.SQLiteTransactionListener);
     method public void beginTransactionWithListenerNonExclusive(android.database.sqlite.SQLiteTransactionListener);
-    method public void close();
     method public android.database.sqlite.SQLiteStatement compileStatement(java.lang.String) throws android.database.SQLException;
     method public static android.database.sqlite.SQLiteDatabase create(android.database.sqlite.SQLiteDatabase.CursorFactory);
     method public int delete(java.lang.String, java.lang.String, java.lang.String[]);
+    method public static boolean deleteDatabase(java.io.File);
     method public boolean enableWriteAheadLogging();
     method public void endTransaction();
     method public void execSQL(java.lang.String) throws android.database.SQLException;
@@ -7414,7 +7419,6 @@
     method public void bindNull(int);
     method public void bindString(int, java.lang.String);
     method public void clearBindings();
-    method public void close();
     method public final deprecated int getUniqueId();
     method protected void onAllReferencesReleased();
   }
@@ -10776,6 +10780,17 @@
     method public abstract void onJetUserIdUpdate(android.media.JetPlayer, int, int);
   }
 
+  public class MediaActionSound {
+    ctor public MediaActionSound();
+    method public void load(int);
+    method public void play(int);
+    method public void release();
+    field public static final int FOCUS_COMPLETE = 1; // 0x1
+    field public static final int SHUTTER_CLICK = 0; // 0x0
+    field public static final int START_VIDEO_RECORDING = 2; // 0x2
+    field public static final int STOP_VIDEO_RECORDING = 3; // 0x3
+  }
+
   public class MediaMetadataRetriever {
     ctor public MediaMetadataRetriever();
     method public java.lang.String extractMetadata(int);
@@ -15091,7 +15106,7 @@
     field public static final android.os.Parcelable.Creator STRING_CREATOR;
   }
 
-  public class ParcelFileDescriptor implements android.os.Parcelable {
+  public class ParcelFileDescriptor implements java.io.Closeable android.os.Parcelable {
     ctor public ParcelFileDescriptor(android.os.ParcelFileDescriptor);
     method public static android.os.ParcelFileDescriptor adoptFd(int);
     method public void close() throws java.io.IOException;
@@ -15325,6 +15340,7 @@
     method public android.os.StrictMode.VmPolicy.Builder detectActivityLeaks();
     method public android.os.StrictMode.VmPolicy.Builder detectAll();
     method public android.os.StrictMode.VmPolicy.Builder detectLeakedClosableObjects();
+    method public android.os.StrictMode.VmPolicy.Builder detectLeakedRegistrationObjects();
     method public android.os.StrictMode.VmPolicy.Builder detectLeakedSqlLiteObjects();
     method public android.os.StrictMode.VmPolicy.Builder penaltyDeath();
     method public android.os.StrictMode.VmPolicy.Builder penaltyDropBox();
@@ -16002,6 +16018,7 @@
     field public static final java.lang.String CALENDAR_ID = "calendar_id";
     field public static final java.lang.String CAN_INVITE_OTHERS = "canInviteOthers";
     field public static final java.lang.String DESCRIPTION = "description";
+    field public static final java.lang.String DISPLAY_COLOR = "displayColor";
     field public static final java.lang.String DTEND = "dtend";
     field public static final java.lang.String DTSTART = "dtstart";
     field public static final java.lang.String DURATION = "duration";
@@ -23267,6 +23284,7 @@
     method public boolean hasFocus();
     method public boolean hasFocusable();
     method public boolean hasOnClickListeners();
+    method public boolean hasTransientState();
     method public boolean hasWindowFocus();
     method public static android.view.View inflate(android.content.Context, int, android.view.ViewGroup);
     method protected void initializeFadingEdge(android.content.res.TypedArray);
@@ -23419,6 +23437,7 @@
     method public void setFocusable(boolean);
     method public void setFocusableInTouchMode(boolean);
     method public void setHapticFeedbackEnabled(boolean);
+    method public void setHasTransientState(boolean);
     method public void setHorizontalFadingEdgeEnabled(boolean);
     method public void setHorizontalScrollBarEnabled(boolean);
     method public void setHovered(boolean);
@@ -26109,17 +26128,36 @@
     ctor public CalendarView(android.content.Context, android.util.AttributeSet);
     ctor public CalendarView(android.content.Context, android.util.AttributeSet, int);
     method public long getDate();
+    method public int getDateTextAppearance();
     method public int getFirstDayOfWeek();
+    method public int getFocusedMonthDateColor();
     method public long getMaxDate();
     method public long getMinDate();
+    method public android.graphics.drawable.Drawable getSelectedDateVerticalBar();
+    method public int getSelectedWeekBackgroundColor();
     method public boolean getShowWeekNumber();
+    method public int getShownWeekCount();
+    method public int getUnfocusedMonthDateColor();
+    method public int getWeekDayTextAppearance();
+    method public int getWeekNumberColor();
+    method public int getWeekSeparatorLineColor();
     method public void setDate(long);
     method public void setDate(long, boolean, boolean);
+    method public void setDateTextAppearance(int);
     method public void setFirstDayOfWeek(int);
+    method public void setFocusedMonthDateColor(int);
     method public void setMaxDate(long);
     method public void setMinDate(long);
     method public void setOnDateChangeListener(android.widget.CalendarView.OnDateChangeListener);
+    method public void setSelectedDateVerticalBar(int);
+    method public void setSelectedDateVerticalBar(android.graphics.drawable.Drawable);
+    method public void setSelectedWeekBackgroundColor(int);
     method public void setShowWeekNumber(boolean);
+    method public void setShownWeekCount(int);
+    method public void setUnfocusedMonthDateColor(int);
+    method public void setWeekDayTextAppearance(int);
+    method public void setWeekNumberColor(int);
+    method public void setWeekSeparatorLineColor(int);
   }
 
   public static abstract interface CalendarView.OnDateChangeListener {
@@ -27607,9 +27645,12 @@
     method public final int getAutoLinkMask();
     method public int getCompoundDrawablePadding();
     method public android.graphics.drawable.Drawable[] getCompoundDrawables();
+    method public android.graphics.drawable.Drawable[] getCompoundDrawablesRelative();
     method public int getCompoundPaddingBottom();
+    method public int getCompoundPaddingEnd();
     method public int getCompoundPaddingLeft();
     method public int getCompoundPaddingRight();
+    method public int getCompoundPaddingStart();
     method public int getCompoundPaddingTop();
     method public final int getCurrentHintTextColor();
     method public final int getCurrentTextColor();
@@ -27652,8 +27693,10 @@
     method public float getTextScaleX();
     method public float getTextSize();
     method public int getTotalPaddingBottom();
+    method public int getTotalPaddingEnd();
     method public int getTotalPaddingLeft();
     method public int getTotalPaddingRight();
+    method public int getTotalPaddingStart();
     method public int getTotalPaddingTop();
     method public final android.text.method.TransformationMethod getTransformationMethod();
     method public android.graphics.Typeface getTypeface();
@@ -27683,6 +27726,9 @@
     method public final void setAutoLinkMask(int);
     method public void setCompoundDrawablePadding(int);
     method public void setCompoundDrawables(android.graphics.drawable.Drawable, android.graphics.drawable.Drawable, android.graphics.drawable.Drawable, android.graphics.drawable.Drawable);
+    method public void setCompoundDrawablesRelative(android.graphics.drawable.Drawable, android.graphics.drawable.Drawable, android.graphics.drawable.Drawable, android.graphics.drawable.Drawable);
+    method public void setCompoundDrawablesRelativeWithIntrinsicBounds(int, int, int, int);
+    method public void setCompoundDrawablesRelativeWithIntrinsicBounds(android.graphics.drawable.Drawable, android.graphics.drawable.Drawable, android.graphics.drawable.Drawable, android.graphics.drawable.Drawable);
     method public void setCompoundDrawablesWithIntrinsicBounds(int, int, int, int);
     method public void setCompoundDrawablesWithIntrinsicBounds(android.graphics.drawable.Drawable, android.graphics.drawable.Drawable, android.graphics.drawable.Drawable, android.graphics.drawable.Drawable);
     method public void setCursorVisible(boolean);
diff --git a/cmds/dumpstate/dumpstate.c b/cmds/dumpstate/dumpstate.c
index 13b63dc..ba79c9f 100644
--- a/cmds/dumpstate/dumpstate.c
+++ b/cmds/dumpstate/dumpstate.c
@@ -86,11 +86,6 @@
     dump_file("PAGETYPEINFO", "/proc/pagetypeinfo");
     dump_file("BUDDYINFO", "/proc/buddyinfo");
 
-    print_properties();
-
-    /* TODO: Make last_kmsg CAP_SYSLOG protected. b/5555691 */
-    dump_file("LAST KMSG", "/proc/last_kmsg");
-    do_dmesg();
 
     dump_file("KERNEL WAKELOCKS", "/proc/wakelocks");
     dump_file("KERNEL CPUFREQ", "/sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state");
@@ -99,6 +94,19 @@
     run_command("PROCESSES AND THREADS", 10, "ps", "-t", "-p", "-P", NULL);
     run_command("LIBRANK", 10, "librank", NULL);
 
+    do_dmesg();
+
+    run_command("LIST OF OPEN FILES", 10, SU_PATH, "root", "lsof", NULL);
+
+    for_each_pid(do_showmap, "SMAPS OF ALL PROCESSES");
+    for_each_pid(show_wchan, "BLOCKED PROCESS WAIT-CHANNELS");
+
+    // dump_file("EVENT LOG TAGS", "/etc/event-log-tags");
+    run_command("SYSTEM LOG", 20, "logcat", "-v", "threadtime", "-d", "*:v", NULL);
+    run_command("EVENT LOG", 20, "logcat", "-b", "events", "-v", "threadtime", "-d", "*:v", NULL);
+    run_command("RADIO LOG", 20, "logcat", "-b", "radio", "-v", "threadtime", "-d", "*:v", NULL);
+
+
     /* show the traces we collected in main(), if that was done */
     if (dump_traces_path != NULL) {
         dump_file("VM TRACES JUST NOW", dump_traces_path);
@@ -124,6 +132,11 @@
     dump_file("NETWORK ROUTES", "/proc/net/route");
     dump_file("NETWORK ROUTES IPV6", "/proc/net/ipv6_route");
 
+    /* TODO: Make last_kmsg CAP_SYSLOG protected. b/5555691 */
+    dump_file("LAST KMSG", "/proc/last_kmsg");
+    dump_file("LAST PANIC CONSOLE", "/data/dontpanic/apanic_console");
+    dump_file("LAST PANIC THREADS", "/data/dontpanic/apanic_threads");
+
     if (screenshot_path[0]) {
         ALOGI("taking screenshot\n");
         run_command(NULL, 5, SU_PATH, "root", "screenshot", screenshot_path, NULL);
@@ -134,11 +147,7 @@
             "/data/data/com.android.providers.settings/databases/settings.db",
             "pragma user_version; select * from system; select * from secure;", NULL);
 
-    // dump_file("EVENT LOG TAGS", "/etc/event-log-tags");
-    run_command("SYSTEM LOG", 20, "logcat", "-v", "threadtime", "-d", "*:v", NULL);
-    run_command("EVENT LOG", 20, "logcat", "-b", "events", "-v", "threadtime", "-d", "*:v", NULL);
-    run_command("RADIO LOG", 20, "logcat", "-b", "radio", "-v", "threadtime", "-d", "*:v", NULL);
-
+    /* The following have a tendency to get wedged when wifi drivers/fw goes belly-up. */
     run_command("NETWORK INTERFACES", 10, SU_PATH, "root", "netcfg", NULL);
     run_command("IP RULES", 10, "ip", "rule", "show", NULL);
     run_command("IP RULES v6", 10, "ip", "-6", "rule", "show", NULL);
@@ -171,40 +180,17 @@
             SU_PATH, "root", "wlutil", "counters", NULL);
 #endif
 
-    char ril_dumpstate_timeout[PROPERTY_VALUE_MAX] = {0};
-    property_get("ril.dumpstate.timeout", ril_dumpstate_timeout, "30");
-    if (strnlen(ril_dumpstate_timeout, PROPERTY_VALUE_MAX - 1) > 0) {
-        if (0 == strncmp(build_type, "user", PROPERTY_VALUE_MAX - 1)) {
-            // su does not exist on user builds, so try running without it.
-            // This way any implementations of vril-dump that do not require
-            // root can run on user builds.
-            run_command("DUMP VENDOR RIL LOGS", atoi(ril_dumpstate_timeout),
-                    "vril-dump", NULL);
-        } else {
-            run_command("DUMP VENDOR RIL LOGS", atoi(ril_dumpstate_timeout),
-                    SU_PATH, "root", "vril-dump", NULL);
-        }
-    }
+    print_properties();
 
     run_command("VOLD DUMP", 10, "vdc", "dump", NULL);
     run_command("SECURE CONTAINERS", 10, "vdc", "asec", "list", NULL);
 
-    dump_file("BINDER FAILED TRANSACTION LOG", "/sys/kernel/debug/binder/failed_transaction_log");
-    dump_file("BINDER TRANSACTION LOG", "/sys/kernel/debug/binder/transaction_log");
-    dump_file("BINDER TRANSACTIONS", "/sys/kernel/debug/binder/transactions");
-    dump_file("BINDER STATS", "/sys/kernel/debug/binder/stats");
-    dump_file("BINDER STATE", "/sys/kernel/debug/binder/state");
-
     run_command("FILESYSTEMS & FREE SPACE", 10, SU_PATH, "root", "df", NULL);
 
     dump_file("PACKAGE SETTINGS", "/data/system/packages.xml");
     dump_file("PACKAGE UID ERRORS", "/data/system/uiderrors.txt");
 
     run_command("LAST RADIO LOG", 10, "parse_radio_log", "/proc/last_radio_log", NULL);
-    dump_file("LAST PANIC CONSOLE", "/data/dontpanic/apanic_console");
-    dump_file("LAST PANIC THREADS", "/data/dontpanic/apanic_threads");
-
-    for_each_pid(show_wchan, "BLOCKED PROCESS WAIT-CHANNELS");
 
     printf("------ BACKLIGHTS ------\n");
     printf("LCD brightness=");
@@ -219,9 +205,12 @@
     dump_file(NULL, "/sys/class/leds/lcd-backlight/registers");
     printf("\n");
 
-    run_command("LIST OF OPEN FILES", 10, SU_PATH, "root", "lsof", NULL);
-
-    for_each_pid(do_showmap, "SMAPS OF ALL PROCESSES");
+    /* Binder state is expensive to look at as it uses a lot of memory. */
+    dump_file("BINDER FAILED TRANSACTION LOG", "/sys/kernel/debug/binder/failed_transaction_log");
+    dump_file("BINDER TRANSACTION LOG", "/sys/kernel/debug/binder/transaction_log");
+    dump_file("BINDER TRANSACTIONS", "/sys/kernel/debug/binder/transactions");
+    dump_file("BINDER STATS", "/sys/kernel/debug/binder/stats");
+    dump_file("BINDER STATE", "/sys/kernel/debug/binder/state");
 
 #ifdef BOARD_HAS_DUMPSTATE
     printf("========================================================\n");
@@ -232,6 +221,22 @@
     printf("\n");
 #endif
 
+    /* Migrate the ril_dumpstate to a dumpstate_board()? */
+    char ril_dumpstate_timeout[PROPERTY_VALUE_MAX] = {0};
+    property_get("ril.dumpstate.timeout", ril_dumpstate_timeout, "30");
+    if (strnlen(ril_dumpstate_timeout, PROPERTY_VALUE_MAX - 1) > 0) {
+        if (0 == strncmp(build_type, "user", PROPERTY_VALUE_MAX - 1)) {
+            // su does not exist on user builds, so try running without it.
+            // This way any implementations of vril-dump that do not require
+            // root can run on user builds.
+            run_command("DUMP VENDOR RIL LOGS", atoi(ril_dumpstate_timeout),
+                    "vril-dump", NULL);
+        } else {
+            run_command("DUMP VENDOR RIL LOGS", atoi(ril_dumpstate_timeout),
+                    SU_PATH, "root", "vril-dump", NULL);
+        }
+    }
+
     printf("========================================================\n");
     printf("== Android Framework Services\n");
     printf("========================================================\n");
diff --git a/cmds/stagefright/codec.cpp b/cmds/stagefright/codec.cpp
index fbf800c..0414b98 100644
--- a/cmds/stagefright/codec.cpp
+++ b/cmds/stagefright/codec.cpp
@@ -35,7 +35,8 @@
 static void usage(const char *me) {
     fprintf(stderr, "usage: %s [-a] use audio\n"
                     "\t\t[-v] use video\n"
-                    "\t\t[-p] playback\n", me);
+                    "\t\t[-p] playback\n"
+                    "\t\t[-S] allocate buffers from a surface\n", me);
 
     exit(1);
 }
@@ -49,6 +50,9 @@
     Vector<sp<ABuffer> > mInBuffers;
     Vector<sp<ABuffer> > mOutBuffers;
     bool mSawOutputEOS;
+    int64_t mNumBuffersDecoded;
+    int64_t mNumBytesDecoded;
+    bool mIsAudio;
 };
 
 }  // namespace android
@@ -57,9 +61,12 @@
         const android::sp<android::ALooper> &looper,
         const char *path,
         bool useAudio,
-        bool useVideo) {
+        bool useVideo,
+        const android::sp<android::Surface> &surface) {
     using namespace android;
 
+    static int64_t kTimeout = 500ll;
+
     sp<NuMediaExtractor> extractor = new NuMediaExtractor;
     if (extractor->setDataSource(path) != OK) {
         fprintf(stderr, "unable to instantiate extractor.\n");
@@ -78,11 +85,12 @@
         AString mime;
         CHECK(format->findString("mime", &mime));
 
-        if (useAudio && !haveAudio
-                && !strncasecmp(mime.c_str(), "audio/", 6)) {
+        bool isAudio = !strncasecmp(mime.c_str(), "audio/", 6);
+        bool isVideo = !strncasecmp(mime.c_str(), "video/", 6);
+
+        if (useAudio && !haveAudio && isAudio) {
             haveAudio = true;
-        } else if (useVideo && !haveVideo
-                && !strncasecmp(mime.c_str(), "video/", 6)) {
+        } else if (useVideo && !haveVideo && isVideo) {
             haveVideo = true;
         } else {
             continue;
@@ -96,13 +104,17 @@
         CodecState *state =
             &stateByTrack.editValueAt(stateByTrack.add(i, CodecState()));
 
+        state->mNumBytesDecoded = 0;
+        state->mNumBuffersDecoded = 0;
+        state->mIsAudio = isAudio;
+
         state->mCodec = MediaCodec::CreateByType(
                 looper, mime.c_str(), false /* encoder */);
 
         CHECK(state->mCodec != NULL);
 
         err = state->mCodec->configure(
-                format, NULL /* surfaceTexture */, 0 /* flags */);
+                format, isVideo ? surface : NULL, 0 /* flags */);
 
         CHECK_EQ(err, (status_t)OK);
 
@@ -122,6 +134,8 @@
 
     CHECK(!stateByTrack.isEmpty());
 
+    int64_t startTimeUs = ALooper::GetNowUs();
+
     for (size_t i = 0; i < stateByTrack.size(); ++i) {
         CodecState *state = &stateByTrack.editValueAt(i);
 
@@ -137,13 +151,7 @@
 
         while (state->mCSDIndex < state->mCSD.size()) {
             size_t index;
-            status_t err = codec->dequeueInputBuffer(&index);
-
-            if (err == -EAGAIN) {
-                usleep(10000);
-                continue;
-            }
-
+            status_t err = codec->dequeueInputBuffer(&index, -1ll);
             CHECK_EQ(err, (status_t)OK);
 
             const sp<ABuffer> &srcBuffer =
@@ -179,7 +187,7 @@
 
                     for (;;) {
                         size_t index;
-                        err = state->mCodec->dequeueInputBuffer(&index);
+                        err = state->mCodec->dequeueInputBuffer(&index, kTimeout);
 
                         if (err == -EAGAIN) {
                             continue;
@@ -204,7 +212,7 @@
                 CodecState *state = &stateByTrack.editValueFor(trackIndex);
 
                 size_t index;
-                err = state->mCodec->dequeueInputBuffer(&index);
+                err = state->mCodec->dequeueInputBuffer(&index, kTimeout);
 
                 if (err == OK) {
                     ALOGV("filling input buffer %d", index);
@@ -261,12 +269,15 @@
             uint32_t flags;
             status_t err = state->mCodec->dequeueOutputBuffer(
                     &index, &offset, &size, &presentationTimeUs, &flags,
-                    10000ll);
+                    kTimeout);
 
             if (err == OK) {
                 ALOGV("draining output buffer %d, time = %lld us",
                       index, presentationTimeUs);
 
+                ++state->mNumBuffersDecoded;
+                state->mNumBytesDecoded += size;
+
                 err = state->mCodec->releaseOutputBuffer(index);
                 CHECK_EQ(err, (status_t)OK);
 
@@ -292,10 +303,27 @@
         }
     }
 
+    int64_t elapsedTimeUs = ALooper::GetNowUs() - startTimeUs;
+
     for (size_t i = 0; i < stateByTrack.size(); ++i) {
         CodecState *state = &stateByTrack.editValueAt(i);
 
         CHECK_EQ((status_t)OK, state->mCodec->release());
+
+        if (state->mIsAudio) {
+            printf("track %d: %lld bytes received. %.2f KB/sec\n",
+                   i,
+                   state->mNumBytesDecoded,
+                   state->mNumBytesDecoded * 1E6 / 1024 / elapsedTimeUs);
+        } else {
+            printf("track %d: %lld frames decoded, %.2f fps. %lld bytes "
+                   "received. %.2f KB/sec\n",
+                   i,
+                   state->mNumBuffersDecoded,
+                   state->mNumBuffersDecoded * 1E6 / elapsedTimeUs,
+                   state->mNumBytesDecoded,
+                   state->mNumBytesDecoded * 1E6 / 1024 / elapsedTimeUs);
+        }
     }
 
     return 0;
@@ -309,9 +337,10 @@
     bool useAudio = false;
     bool useVideo = false;
     bool playback = false;
+    bool useSurface = false;
 
     int res;
-    while ((res = getopt(argc, argv, "havp")) >= 0) {
+    while ((res = getopt(argc, argv, "havpS")) >= 0) {
         switch (res) {
             case 'a':
             {
@@ -331,6 +360,12 @@
                 break;
             }
 
+            case 'S':
+            {
+                useSurface = true;
+                break;
+            }
+
             case '?':
             case 'h':
             default:
@@ -358,8 +393,12 @@
     sp<ALooper> looper = new ALooper;
     looper->start();
 
-    if (playback) {
-        sp<SurfaceComposerClient> composerClient = new SurfaceComposerClient;
+    sp<SurfaceComposerClient> composerClient;
+    sp<SurfaceControl> control;
+    sp<Surface> surface;
+
+    if (playback || (useSurface && useVideo)) {
+        composerClient = new SurfaceComposerClient;
         CHECK_EQ(composerClient->initCheck(), (status_t)OK);
 
         ssize_t displayWidth = composerClient->getDisplayWidth(0);
@@ -367,14 +406,13 @@
 
         ALOGV("display is %ld x %ld\n", displayWidth, displayHeight);
 
-        sp<SurfaceControl> control =
-            composerClient->createSurface(
-                    String8("A Surface"),
-                    0,
-                    displayWidth,
-                    displayHeight,
-                    PIXEL_FORMAT_RGB_565,
-                    0);
+        control = composerClient->createSurface(
+                String8("A Surface"),
+                0,
+                displayWidth,
+                displayHeight,
+                PIXEL_FORMAT_RGB_565,
+                0);
 
         CHECK(control != NULL);
         CHECK(control->isValid());
@@ -384,9 +422,11 @@
         CHECK_EQ(control->show(), (status_t)OK);
         SurfaceComposerClient::closeGlobalTransaction();
 
-        sp<Surface> surface = control->getSurface();
+        surface = control->getSurface();
         CHECK(surface != NULL);
+    }
 
+    if (playback) {
         sp<SimplePlayer> player = new SimplePlayer;
         looper->registerHandler(player);
 
@@ -396,10 +436,12 @@
         sleep(60);
         player->stop();
         player->reset();
-
-        composerClient->dispose();
     } else {
-        decode(looper, argv[0], useAudio, useVideo);
+        decode(looper, argv[0], useAudio, useVideo, surface);
+    }
+
+    if (playback || (useSurface && useVideo)) {
+        composerClient->dispose();
     }
 
     looper->stop();
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index d98d87b..59c803e 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -1145,7 +1145,14 @@
          * @hide
          */
         public int flags;
-        
+
+        /**
+         * Last memory trim level reported to the process: corresponds to
+         * the values supplied to {@link android.content.ComponentCallbacks2#onTrimMemory(int)
+         * ComponentCallbacks2.onTrimMemory(int)}.
+         */
+        public int lastTrimLevel;
+
         /**
          * Constant for {@link #importance}: this process is running the
          * foreground UI.
@@ -1212,7 +1219,7 @@
          * be maintained in the future.
          */
         public int lru;
-        
+
         /**
          * Constant for {@link #importanceReasonCode}: nothing special has
          * been specified for the reason for this level.
@@ -1282,6 +1289,7 @@
             dest.writeInt(uid);
             dest.writeStringArray(pkgList);
             dest.writeInt(this.flags);
+            dest.writeInt(lastTrimLevel);
             dest.writeInt(importance);
             dest.writeInt(lru);
             dest.writeInt(importanceReasonCode);
@@ -1296,6 +1304,7 @@
             uid = source.readInt();
             pkgList = source.readStringArray();
             flags = source.readInt();
+            lastTrimLevel = source.readInt();
             importance = source.readInt();
             lru = source.readInt();
             importanceReasonCode = source.readInt();
@@ -1349,7 +1358,25 @@
             return null;
         }
     }
-    
+
+    /**
+     * Return global memory state information for the calling process.  This
+     * does not fill in all fields of the {@link RunningAppProcessInfo}.  The
+     * only fields that will be filled in are
+     * {@link RunningAppProcessInfo#pid},
+     * {@link RunningAppProcessInfo#uid},
+     * {@link RunningAppProcessInfo#lastTrimLevel},
+     * {@link RunningAppProcessInfo#importance},
+     * {@link RunningAppProcessInfo#lru}, and
+     * {@link RunningAppProcessInfo#importanceReasonCode}.
+     */
+    static public void getMyMemoryState(RunningAppProcessInfo outState) {
+        try {
+            ActivityManagerNative.getDefault().getMyMemoryState(outState);
+        } catch (RemoteException e) {
+        }
+    }
+
     /**
      * Return information about the memory usage of one or more processes.
      * 
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index 24079a5d..b952649 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -1126,7 +1126,17 @@
             reply.writeNoException();
             return true;
         }
-        
+
+        case GET_MY_MEMORY_STATE_TRANSACTION: {
+            data.enforceInterface(IActivityManager.descriptor);
+            ActivityManager.RunningAppProcessInfo info =
+                    new ActivityManager.RunningAppProcessInfo();
+            getMyMemoryState(info);
+            reply.writeNoException();
+            info.writeToParcel(reply, 0);
+            return true;
+        }
+
         case GET_DEVICE_CONFIGURATION_TRANSACTION: {
             data.enforceInterface(IActivityManager.descriptor);
             ConfigurationInfo config = getDeviceConfigurationInfo();
@@ -2973,6 +2983,19 @@
         reply.recycle();
     }
     
+    public void getMyMemoryState(ActivityManager.RunningAppProcessInfo outInfo)
+            throws RemoteException
+    {
+        Parcel data = Parcel.obtain();
+        Parcel reply = Parcel.obtain();
+        data.writeInterfaceToken(IActivityManager.descriptor);
+        mRemote.transact(GET_MY_MEMORY_STATE_TRANSACTION, data, reply, 0);
+        reply.readException();
+        outInfo.readFromParcel(reply);
+        reply.recycle();
+        data.recycle();
+    }
+
     public ConfigurationInfo getDeviceConfigurationInfo() throws RemoteException
     {
         Parcel data = Parcel.obtain();
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index f10bf03..aa15f39 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -102,6 +102,8 @@
 import java.util.TimeZone;
 import java.util.regex.Pattern;
 
+import libcore.io.IoUtils;
+
 import dalvik.system.CloseGuard;
 
 final class SuperNotCalledException extends AndroidRuntimeException {
@@ -2357,41 +2359,47 @@
     }
 
     private void handleDumpService(DumpComponentInfo info) {
-        Service s = mServices.get(info.token);
-        if (s != null) {
-            PrintWriter pw = new PrintWriter(new FileOutputStream(info.fd.getFileDescriptor()));
-            s.dump(info.fd.getFileDescriptor(), pw, info.args);
-            pw.flush();
-            try {
-                info.fd.close();
-            } catch (IOException e) {
+        final StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskWrites();
+        try {
+            Service s = mServices.get(info.token);
+            if (s != null) {
+                PrintWriter pw = new PrintWriter(new FileOutputStream(info.fd.getFileDescriptor()));
+                s.dump(info.fd.getFileDescriptor(), pw, info.args);
+                pw.flush();
             }
+        } finally {
+            IoUtils.closeQuietly(info.fd);
+            StrictMode.setThreadPolicy(oldPolicy);
         }
     }
 
     private void handleDumpActivity(DumpComponentInfo info) {
-        ActivityClientRecord r = mActivities.get(info.token);
-        if (r != null && r.activity != null) {
-            PrintWriter pw = new PrintWriter(new FileOutputStream(info.fd.getFileDescriptor()));
-            r.activity.dump(info.prefix, info.fd.getFileDescriptor(), pw, info.args);
-            pw.flush();
-            try {
-                info.fd.close();
-            } catch (IOException e) {
+        final StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskWrites();
+        try {
+            ActivityClientRecord r = mActivities.get(info.token);
+            if (r != null && r.activity != null) {
+                PrintWriter pw = new PrintWriter(new FileOutputStream(info.fd.getFileDescriptor()));
+                r.activity.dump(info.prefix, info.fd.getFileDescriptor(), pw, info.args);
+                pw.flush();
             }
+        } finally {
+            IoUtils.closeQuietly(info.fd);
+            StrictMode.setThreadPolicy(oldPolicy);
         }
     }
 
     private void handleDumpProvider(DumpComponentInfo info) {
-        ProviderClientRecord r = mLocalProviders.get(info.token);
-        if (r != null && r.mLocalProvider != null) {
-            PrintWriter pw = new PrintWriter(new FileOutputStream(info.fd.getFileDescriptor()));
-            r.mLocalProvider.dump(info.fd.getFileDescriptor(), pw, info.args);
-            pw.flush();
-            try {
-                info.fd.close();
-            } catch (IOException e) {
+        final StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskWrites();
+        try {
+            ProviderClientRecord r = mLocalProviders.get(info.token);
+            if (r != null && r.mLocalProvider != null) {
+                PrintWriter pw = new PrintWriter(new FileOutputStream(info.fd.getFileDescriptor()));
+                r.mLocalProvider.dump(info.fd.getFileDescriptor(), pw, info.args);
+                pw.flush();
             }
+        } finally {
+            IoUtils.closeQuietly(info.fd);
+            StrictMode.setThreadPolicy(oldPolicy);
         }
     }
 
diff --git a/core/java/android/app/ApplicationErrorReport.java b/core/java/android/app/ApplicationErrorReport.java
index 588125d..ebf42619 100644
--- a/core/java/android/app/ApplicationErrorReport.java
+++ b/core/java/android/app/ApplicationErrorReport.java
@@ -98,7 +98,7 @@
     /**
      * Package name of the application which installed the application this
      * report pertains to.
-     * This identifies which Market the application came from.
+     * This identifies which market the application came from.
      */
     public String installerPackageName;
 
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 6d5cce5..e348b87 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -785,7 +785,7 @@
     public boolean deleteDatabase(String name) {
         try {
             File f = validateFilePath(name, false);
-            return f.delete();
+            return SQLiteDatabase.deleteDatabase(f);
         } catch (Exception e) {
         }
         return false;
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index 53a71db..ea2545f 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -278,13 +278,16 @@
      * SIGUSR1 is delivered. All others are ignored.
      */
     public void signalPersistentProcesses(int signal) throws RemoteException;
-    // Retrieve info of applications installed on external media that are currently
-    // running.
+    // Retrieve running application processes in the system
     public List<ActivityManager.RunningAppProcessInfo> getRunningAppProcesses()
             throws RemoteException;
- // Retrieve running application processes in the system
+    // Retrieve info of applications installed on external media that are currently
+    // running.
     public List<ApplicationInfo> getRunningExternalApplications()
             throws RemoteException;
+    // Get memory information about the calling process.
+    public void getMyMemoryState(ActivityManager.RunningAppProcessInfo outInfo)
+            throws RemoteException;
     // Get device configuration
     public ConfigurationInfo getDeviceConfigurationInfo() throws RemoteException;
     
@@ -606,4 +609,5 @@
     int KILL_ALL_BACKGROUND_PROCESSES_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+139;
     int GET_CONTENT_PROVIDER_EXTERNAL_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+140;
     int REMOVE_CONTENT_PROVIDER_EXTERNAL_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+141;
+    int GET_MY_MEMORY_STATE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+142;
 }
diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java
index d9bbb4a..de9470e 100644
--- a/core/java/android/app/LoadedApk.java
+++ b/core/java/android/app/LoadedApk.java
@@ -512,6 +512,7 @@
 
     public void removeContextRegistrations(Context context,
             String who, String what) {
+        final boolean reportRegistrationLeaks = StrictMode.vmRegistrationLeaksEnabled();
         HashMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> rmap =
             mReceivers.remove(context);
         if (rmap != null) {
@@ -525,6 +526,9 @@
                         "call to unregisterReceiver()?");
                 leak.setStackTrace(rd.getLocation().getStackTrace());
                 Slog.e(ActivityThread.TAG, leak.getMessage(), leak);
+                if (reportRegistrationLeaks) {
+                    StrictMode.onIntentReceiverLeaked(leak);
+                }
                 try {
                     ActivityManagerNative.getDefault().unregisterReceiver(
                             rd.getIIntentReceiver());
@@ -546,6 +550,9 @@
                         + sd.getServiceConnection() + " that was originally bound here");
                 leak.setStackTrace(sd.getLocation().getStackTrace());
                 Slog.e(ActivityThread.TAG, leak.getMessage(), leak);
+                if (reportRegistrationLeaks) {
+                    StrictMode.onServiceConnectionLeaked(leak);
+                }
                 try {
                     ActivityManagerNative.getDefault().unbindService(
                             sd.getIServiceConnection());
diff --git a/core/java/android/content/BroadcastReceiver.java b/core/java/android/content/BroadcastReceiver.java
index b609c26..9ddb2a6 100644
--- a/core/java/android/content/BroadcastReceiver.java
+++ b/core/java/android/content/BroadcastReceiver.java
@@ -446,13 +446,17 @@
     /**
      * This method is called when the BroadcastReceiver is receiving an Intent
      * broadcast.  During this time you can use the other methods on
-     * BroadcastReceiver to view/modify the current result values.  The function
-     * is normally called within the main thread of its process, so you should
+     * BroadcastReceiver to view/modify the current result values.  This method
+     * is always called within the main thread of its process, unless you
+     * explicitly asked for it to be scheduled on a different thread using
+     * {@link android.content.Context#registerReceiver(BroadcastReceiver,
+     * IntentFilter, String, android.os.Handler)}. When it runs on the main
+     * thread you should
      * never perform long-running operations in it (there is a timeout of
      * 10 seconds that the system allows before considering the receiver to
      * be blocked and a candidate to be killed). You cannot launch a popup dialog
      * in your implementation of onReceive().
-     * 
+     *
      * <p><b>If this BroadcastReceiver was launched through a &lt;receiver&gt; tag,
      * then the object is no longer alive after returning from this
      * function.</b>  This means you should not perform any operations that
diff --git a/core/java/android/content/ComponentCallbacks2.java b/core/java/android/content/ComponentCallbacks2.java
index 8b9f97c..85294dd 100644
--- a/core/java/android/content/ComponentCallbacks2.java
+++ b/core/java/android/content/ComponentCallbacks2.java
@@ -52,15 +52,49 @@
     static final int TRIM_MEMORY_UI_HIDDEN = 20;
 
     /**
+     * Level for {@link #onTrimMemory(int)}: the process is not an expendable
+     * background process, but the device is running extremely low on memory
+     * and is about to not be able to keep any background processes running.
+     * Your running process should free up as many non-critical resources as it
+     * can to allow that memory to be used elsewhere.  The next thing that
+     * will happen after this is {@link #onLowMemory()} called to report that
+     * nothing at all can be kept in the background, a situation that can start
+     * to notably impact the user.
+     */
+    static final int TRIM_MEMORY_RUNNING_CRITICAL = 15;
+
+    /**
+     * Level for {@link #onTrimMemory(int)}: the process is not an expendable
+     * background process, but the device is running low on memory.
+     * Your running process should free up unneeded resources to allow that
+     * memory to be used elsewhere.
+     */
+    static final int TRIM_MEMORY_RUNNING_LOW = 10;
+
+
+    /**
+     * Level for {@link #onTrimMemory(int)}: the process is not an expendable
+     * background process, but the device is running moderately low on memory.
+     * Your running process may want to release some unneeded resources for
+     * use elsewhere.
+     */
+    static final int TRIM_MEMORY_RUNNING_MODERATE = 5;
+
+    /**
      * Called when the operating system has determined that it is a good
      * time for a process to trim unneeded memory from its process.  This will
      * happen for example when it goes in the background and there is not enough
-     * memory to keep as many background processes running as desired.
+     * memory to keep as many background processes running as desired.  You
+     * should never compare to exact values of the level, since new intermediate
+     * values may be added -- you will typically want to compare if the value
+     * is greater or equal to a level you are interested in.
      * 
      * @param level The context of the trim, giving a hint of the amount of
      * trimming the application may like to perform.  May be
      * {@link #TRIM_MEMORY_COMPLETE}, {@link #TRIM_MEMORY_MODERATE},
-     * {@link #TRIM_MEMORY_BACKGROUND}, or {@link #TRIM_MEMORY_UI_HIDDEN}.
+     * {@link #TRIM_MEMORY_BACKGROUND}, {@link #TRIM_MEMORY_UI_HIDDEN},
+     * {@link #TRIM_MEMORY_RUNNING_CRITICAL}, {@link #TRIM_MEMORY_RUNNING_LOW},
+     * or {@link #TRIM_MEMORY_RUNNING_MODERATE}.
      */
     void onTrimMemory(int level);
 }
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index ab62c44..b1b09d5 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -1137,7 +1137,7 @@
     /**
      * Activity Action: The user pressed the "Report" button in the crash/ANR dialog.
      * This intent is delivered to the package which installed the application, usually
-     * the Market.
+     * Google Play.
      * <p>Input: No data is specified. The bug report is passed in using
      * an {@link #EXTRA_BUG_REPORT} field.
      * <p>Output: Nothing.
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 7b4a0ad..e88ee02 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -944,7 +944,7 @@
 
                 if (name != null && !pkg.requestedPermissions.contains(name)) {
                     pkg.requestedPermissions.add(name.intern());
-                    pkg.requestedPermissionsRequired.add(required);
+                    pkg.requestedPermissionsRequired.add(required ? Boolean.TRUE : Boolean.FALSE);
                 }
 
                 XmlUtils.skipCurrentTag(parser);
@@ -1239,6 +1239,7 @@
                 }
                 implicitPerms.append(npi.name);
                 pkg.requestedPermissions.add(npi.name);
+                pkg.requestedPermissionsRequired.add(Boolean.TRUE);
             }
         }
         if (implicitPerms != null) {
@@ -3082,7 +3083,36 @@
                 instrumentation.get(i).setPackageName(newName);
             }
         }
-        
+
+        public boolean hasComponentClassName(String name) {
+            for (int i=activities.size()-1; i>=0; i--) {
+                if (name.equals(activities.get(i).className)) {
+                    return true;
+                }
+            }
+            for (int i=receivers.size()-1; i>=0; i--) {
+                if (name.equals(receivers.get(i).className)) {
+                    return true;
+                }
+            }
+            for (int i=providers.size()-1; i>=0; i--) {
+                if (name.equals(providers.get(i).className)) {
+                    return true;
+                }
+            }
+            for (int i=services.size()-1; i>=0; i--) {
+                if (name.equals(services.get(i).className)) {
+                    return true;
+                }
+            }
+            for (int i=instrumentation.size()-1; i>=0; i--) {
+                if (name.equals(instrumentation.get(i).className)) {
+                    return true;
+                }
+            }
+            return false;
+        }
+
         public String toString() {
             return "Package{"
                 + Integer.toHexString(System.identityHashCode(this))
diff --git a/core/java/android/database/Cursor.java b/core/java/android/database/Cursor.java
index 59ec89d..907833d 100644
--- a/core/java/android/database/Cursor.java
+++ b/core/java/android/database/Cursor.java
@@ -20,6 +20,8 @@
 import android.net.Uri;
 import android.os.Bundle;
 
+import java.io.Closeable;
+
 /**
  * This interface provides random read-write access to the result set returned
  * by a database query.
@@ -27,7 +29,7 @@
  * Cursor implementations are not required to be synchronized so code using a Cursor from multiple
  * threads should perform its own synchronization when using the Cursor.
  */
-public interface Cursor {
+public interface Cursor extends Closeable {
     /*
      * Values returned by {@link #getType(int)}.
      * These should be consistent with the corresponding types defined in CursorWindow.h
diff --git a/core/java/android/database/CursorWindow.java b/core/java/android/database/CursorWindow.java
index 85f570c1..f1f3017 100644
--- a/core/java/android/database/CursorWindow.java
+++ b/core/java/android/database/CursorWindow.java
@@ -169,14 +169,6 @@
     }
 
     /**
-     * Closes the cursor window and frees its underlying resources when all other
-     * remaining references have been released.
-     */
-    public void close() {
-        releaseReference();
-    }
-
-    /**
      * Clears out the existing contents of the window, making it safe to reuse
      * for new data.
      * <p>
@@ -703,8 +695,13 @@
     }
 
     public void writeToParcel(Parcel dest, int flags) {
-        dest.writeInt(mStartPos);
-        nativeWriteToParcel(mWindowPtr, dest);
+        acquireReference();
+        try {
+            dest.writeInt(mStartPos);
+            nativeWriteToParcel(mWindowPtr, dest);
+        } finally {
+            releaseReference();
+        }
 
         if ((flags & Parcelable.PARCELABLE_WRITE_RETURN_VALUE) != 0) {
             releaseReference();
diff --git a/core/java/android/database/DatabaseUtils.java b/core/java/android/database/DatabaseUtils.java
index 0022118..99d260e 100644
--- a/core/java/android/database/DatabaseUtils.java
+++ b/core/java/android/database/DatabaseUtils.java
@@ -269,63 +269,56 @@
         if (position < 0 || position >= cursor.getCount()) {
             return;
         }
-        window.acquireReference();
-        try {
-            final int oldPos = cursor.getPosition();
-            final int numColumns = cursor.getColumnCount();
-            window.clear();
-            window.setStartPosition(position);
-            window.setNumColumns(numColumns);
-            if (cursor.moveToPosition(position)) {
-                do {
-                    if (!window.allocRow()) {
-                        break;
-                    }
-                    for (int i = 0; i < numColumns; i++) {
-                        final int type = cursor.getType(i);
-                        final boolean success;
-                        switch (type) {
-                            case Cursor.FIELD_TYPE_NULL:
-                                success = window.putNull(position, i);
-                                break;
+        final int oldPos = cursor.getPosition();
+        final int numColumns = cursor.getColumnCount();
+        window.clear();
+        window.setStartPosition(position);
+        window.setNumColumns(numColumns);
+        if (cursor.moveToPosition(position)) {
+            do {
+                if (!window.allocRow()) {
+                    break;
+                }
+                for (int i = 0; i < numColumns; i++) {
+                    final int type = cursor.getType(i);
+                    final boolean success;
+                    switch (type) {
+                        case Cursor.FIELD_TYPE_NULL:
+                            success = window.putNull(position, i);
+                            break;
 
-                            case Cursor.FIELD_TYPE_INTEGER:
-                                success = window.putLong(cursor.getLong(i), position, i);
-                                break;
+                        case Cursor.FIELD_TYPE_INTEGER:
+                            success = window.putLong(cursor.getLong(i), position, i);
+                            break;
 
-                            case Cursor.FIELD_TYPE_FLOAT:
-                                success = window.putDouble(cursor.getDouble(i), position, i);
-                                break;
+                        case Cursor.FIELD_TYPE_FLOAT:
+                            success = window.putDouble(cursor.getDouble(i), position, i);
+                            break;
 
-                            case Cursor.FIELD_TYPE_BLOB: {
-                                final byte[] value = cursor.getBlob(i);
-                                success = value != null ? window.putBlob(value, position, i)
-                                        : window.putNull(position, i);
-                                break;
-                            }
-
-                            default: // assume value is convertible to String
-                            case Cursor.FIELD_TYPE_STRING: {
-                                final String value = cursor.getString(i);
-                                success = value != null ? window.putString(value, position, i)
-                                        : window.putNull(position, i);
-                                break;
-                            }
+                        case Cursor.FIELD_TYPE_BLOB: {
+                            final byte[] value = cursor.getBlob(i);
+                            success = value != null ? window.putBlob(value, position, i)
+                                    : window.putNull(position, i);
+                            break;
                         }
-                        if (!success) {
-                            window.freeLastRow();
+
+                        default: // assume value is convertible to String
+                        case Cursor.FIELD_TYPE_STRING: {
+                            final String value = cursor.getString(i);
+                            success = value != null ? window.putString(value, position, i)
+                                    : window.putNull(position, i);
                             break;
                         }
                     }
-                    position += 1;
-                } while (cursor.moveToNext());
-            }
-            cursor.moveToPosition(oldPos);
-        } catch (IllegalStateException e){
-            // simply ignore it
-        } finally {
-            window.releaseReference();
+                    if (!success) {
+                        window.freeLastRow();
+                        break;
+                    }
+                }
+                position += 1;
+            } while (cursor.moveToNext());
         }
+        cursor.moveToPosition(oldPos);
     }
 
     /**
diff --git a/core/java/android/database/sqlite/SQLiteClosable.java b/core/java/android/database/sqlite/SQLiteClosable.java
index 7e91a7b..adfbc6e 100644
--- a/core/java/android/database/sqlite/SQLiteClosable.java
+++ b/core/java/android/database/sqlite/SQLiteClosable.java
@@ -16,15 +16,39 @@
 
 package android.database.sqlite;
 
+import java.io.Closeable;
+
 /**
  * An object created from a SQLiteDatabase that can be closed.
+ *
+ * This class implements a primitive reference counting scheme for database objects.
  */
-public abstract class SQLiteClosable {
+public abstract class SQLiteClosable implements Closeable {
     private int mReferenceCount = 1;
 
+    /**
+     * Called when the last reference to the object was released by
+     * a call to {@link #releaseReference()} or {@link #close()}.
+     */
     protected abstract void onAllReferencesReleased();
-    protected void onAllReferencesReleasedFromContainer() {}
 
+    /**
+     * Called when the last reference to the object was released by
+     * a call to {@link #releaseReferenceFromContainer()}.
+     *
+     * @deprecated Do not use.
+     */
+    @Deprecated
+    protected void onAllReferencesReleasedFromContainer() {
+        onAllReferencesReleased();
+    }
+
+    /**
+     * Acquires a reference to the object.
+     *
+     * @throws IllegalStateException if the last reference to the object has already
+     * been released.
+     */
     public void acquireReference() {
         synchronized(this) {
             if (mReferenceCount <= 0) {
@@ -35,6 +59,12 @@
         }
     }
 
+    /**
+     * Releases a reference to the object, closing the object if the last reference
+     * was released.
+     *
+     * @see #onAllReferencesReleased()
+     */
     public void releaseReference() {
         boolean refCountIsZero = false;
         synchronized(this) {
@@ -45,6 +75,14 @@
         }
     }
 
+    /**
+     * Releases a reference to the object that was owned by the container of the object,
+     * closing the object if the last reference was released.
+     *
+     * @see #onAllReferencesReleasedFromContainer()
+     * @deprecated Do not use.
+     */
+    @Deprecated
     public void releaseReferenceFromContainer() {
         boolean refCountIsZero = false;
         synchronized(this) {
@@ -54,4 +92,17 @@
             onAllReferencesReleasedFromContainer();
         }
     }
+
+    /**
+     * Releases a reference to the object, closing the object if the last reference
+     * was released.
+     *
+     * Calling this method is equivalent to calling {@link #releaseReference}.
+     *
+     * @see #releaseReference()
+     * @see #onAllReferencesReleased()
+     */
+    public void close() {
+        releaseReference();
+    }
 }
diff --git a/core/java/android/database/sqlite/SQLiteConnection.java b/core/java/android/database/sqlite/SQLiteConnection.java
index 1900301..0db3e4f 100644
--- a/core/java/android/database/sqlite/SQLiteConnection.java
+++ b/core/java/android/database/sqlite/SQLiteConnection.java
@@ -208,11 +208,11 @@
                 mConfiguration.label,
                 SQLiteDebug.DEBUG_SQL_STATEMENTS, SQLiteDebug.DEBUG_SQL_TIME);
 
-        setSyncMode();
         setPageSize();
-        setAutoCheckpointInterval();
-        setJournalSizeLimit();
+        setSyncModeFromConfiguration();
         setJournalModeFromConfiguration();
+        setJournalSizeLimit();
+        setAutoCheckpointInterval();
         setLocaleFromConfiguration();
     }
 
@@ -236,12 +236,6 @@
         }
     }
 
-    private void setSyncMode() {
-        if (!mConfiguration.isInMemoryDb()) {
-            execute("PRAGMA synchronous=" + SQLiteGlobal.getSyncMode(), null, null);
-        }
-    }
-
     private void setPageSize() {
         if (!mConfiguration.isInMemoryDb()) {
             execute("PRAGMA page_size=" + SQLiteGlobal.getDefaultPageSize(), null, null);
@@ -262,6 +256,12 @@
         }
     }
 
+    private void setSyncModeFromConfiguration() {
+        if (!mConfiguration.isInMemoryDb()) {
+            execute("PRAGMA synchronous=" + mConfiguration.syncMode, null, null);
+        }
+    }
+
     private void setJournalModeFromConfiguration() {
         if (!mConfiguration.isInMemoryDb()) {
             String result = executeForString("PRAGMA journal_mode=" + mConfiguration.journalMode,
@@ -290,6 +290,8 @@
         }
 
         // Remember what changed.
+        boolean syncModeChanged = !configuration.syncMode.equalsIgnoreCase(
+                mConfiguration.syncMode);
         boolean journalModeChanged = !configuration.journalMode.equalsIgnoreCase(
                 mConfiguration.journalMode);
         boolean localeChanged = !configuration.locale.equals(mConfiguration.locale);
@@ -300,6 +302,11 @@
         // Update prepared statement cache size.
         mPreparedStatementCache.resize(configuration.maxSqlCacheSize);
 
+        // Update sync mode.
+        if (syncModeChanged) {
+            setSyncModeFromConfiguration();
+        }
+
         // Update journal mode.
         if (journalModeChanged) {
             setJournalModeFromConfiguration();
@@ -697,44 +704,49 @@
             throw new IllegalArgumentException("window must not be null.");
         }
 
-        int actualPos = -1;
-        int countedRows = -1;
-        int filledRows = -1;
-        final int cookie = mRecentOperations.beginOperation("executeForCursorWindow",
-                sql, bindArgs);
+        window.acquireReference();
         try {
-            final PreparedStatement statement = acquirePreparedStatement(sql);
+            int actualPos = -1;
+            int countedRows = -1;
+            int filledRows = -1;
+            final int cookie = mRecentOperations.beginOperation("executeForCursorWindow",
+                    sql, bindArgs);
             try {
-                throwIfStatementForbidden(statement);
-                bindArguments(statement, bindArgs);
-                applyBlockGuardPolicy(statement);
-                attachCancellationSignal(cancellationSignal);
+                final PreparedStatement statement = acquirePreparedStatement(sql);
                 try {
-                    final long result = nativeExecuteForCursorWindow(
-                            mConnectionPtr, statement.mStatementPtr, window.mWindowPtr,
-                            startPos, requiredPos, countAllRows);
-                    actualPos = (int)(result >> 32);
-                    countedRows = (int)result;
-                    filledRows = window.getNumRows();
-                    window.setStartPosition(actualPos);
-                    return countedRows;
+                    throwIfStatementForbidden(statement);
+                    bindArguments(statement, bindArgs);
+                    applyBlockGuardPolicy(statement);
+                    attachCancellationSignal(cancellationSignal);
+                    try {
+                        final long result = nativeExecuteForCursorWindow(
+                                mConnectionPtr, statement.mStatementPtr, window.mWindowPtr,
+                                startPos, requiredPos, countAllRows);
+                        actualPos = (int)(result >> 32);
+                        countedRows = (int)result;
+                        filledRows = window.getNumRows();
+                        window.setStartPosition(actualPos);
+                        return countedRows;
+                    } finally {
+                        detachCancellationSignal(cancellationSignal);
+                    }
                 } finally {
-                    detachCancellationSignal(cancellationSignal);
+                    releasePreparedStatement(statement);
                 }
+            } catch (RuntimeException ex) {
+                mRecentOperations.failOperation(cookie, ex);
+                throw ex;
             } finally {
-                releasePreparedStatement(statement);
+                if (mRecentOperations.endOperationDeferLog(cookie)) {
+                    mRecentOperations.logOperation(cookie, "window='" + window
+                            + "', startPos=" + startPos
+                            + ", actualPos=" + actualPos
+                            + ", filledRows=" + filledRows
+                            + ", countedRows=" + countedRows);
+                }
             }
-        } catch (RuntimeException ex) {
-            mRecentOperations.failOperation(cookie, ex);
-            throw ex;
         } finally {
-            if (mRecentOperations.endOperationDeferLog(cookie)) {
-                mRecentOperations.logOperation(cookie, "window='" + window
-                        + "', startPos=" + startPos
-                        + ", actualPos=" + actualPos
-                        + ", filledRows=" + filledRows
-                        + ", countedRows=" + countedRows);
-            }
+            window.releaseReference();
         }
     }
 
diff --git a/core/java/android/database/sqlite/SQLiteDatabase.java b/core/java/android/database/sqlite/SQLiteDatabase.java
index 515658f..d41b484 100644
--- a/core/java/android/database/sqlite/SQLiteDatabase.java
+++ b/core/java/android/database/sqlite/SQLiteDatabase.java
@@ -19,7 +19,6 @@
 import android.content.CancellationSignal;
 import android.content.ContentValues;
 import android.content.OperationCanceledException;
-import android.content.res.Resources;
 import android.database.Cursor;
 import android.database.DatabaseErrorHandler;
 import android.database.DatabaseUtils;
@@ -36,6 +35,7 @@
 import dalvik.system.CloseGuard;
 
 import java.io.File;
+import java.io.FileFilter;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
@@ -64,7 +64,7 @@
  * to the current locale.
  * </p>
  */
-public class SQLiteDatabase extends SQLiteClosable {
+public final class SQLiteDatabase extends SQLiteClosable {
     private static final String TAG = "SQLiteDatabase";
 
     private static final int EVENT_DB_CORRUPT = 75004;
@@ -492,9 +492,16 @@
 
     private void beginTransaction(SQLiteTransactionListener transactionListener,
             boolean exclusive) {
-        getThreadSession().beginTransaction(exclusive ? SQLiteSession.TRANSACTION_MODE_EXCLUSIVE :
-                SQLiteSession.TRANSACTION_MODE_IMMEDIATE, transactionListener,
-                getThreadDefaultConnectionFlags(false /*readOnly*/), null);
+        acquireReference();
+        try {
+            getThreadSession().beginTransaction(
+                    exclusive ? SQLiteSession.TRANSACTION_MODE_EXCLUSIVE :
+                            SQLiteSession.TRANSACTION_MODE_IMMEDIATE,
+                    transactionListener,
+                    getThreadDefaultConnectionFlags(false /*readOnly*/), null);
+        } finally {
+            releaseReference();
+        }
     }
 
     /**
@@ -502,7 +509,12 @@
      * are committed and rolled back.
      */
     public void endTransaction() {
-        getThreadSession().endTransaction(null);
+        acquireReference();
+        try {
+            getThreadSession().endTransaction(null);
+        } finally {
+            releaseReference();
+        }
     }
 
     /**
@@ -515,7 +527,12 @@
      * transaction is already marked as successful.
      */
     public void setTransactionSuccessful() {
-        getThreadSession().setTransactionSuccessful();
+        acquireReference();
+        try {
+            getThreadSession().setTransactionSuccessful();
+        } finally {
+            releaseReference();
+        }
     }
 
     /**
@@ -524,7 +541,12 @@
      * @return True if the current thread is in a transaction.
      */
     public boolean inTransaction() {
-        return getThreadSession().hasTransaction();
+        acquireReference();
+        try {
+            return getThreadSession().hasTransaction();
+        } finally {
+            releaseReference();
+        }
     }
 
     /**
@@ -540,7 +562,12 @@
      * @return True if the current thread is holding an active connection to the database.
      */
     public boolean isDbLockedByCurrentThread() {
-        return getThreadSession().hasConnection();
+        acquireReference();
+        try {
+            return getThreadSession().hasConnection();
+        } finally {
+            releaseReference();
+        }
     }
 
     /**
@@ -599,7 +626,12 @@
     }
 
     private boolean yieldIfContendedHelper(boolean throwIfUnsafe, long sleepAfterYieldDelay) {
-        return getThreadSession().yieldTransaction(sleepAfterYieldDelay, throwIfUnsafe, null);
+        acquireReference();
+        try {
+            return getThreadSession().yieldTransaction(sleepAfterYieldDelay, throwIfUnsafe, null);
+        } finally {
+            releaseReference();
+        }
     }
 
     /**
@@ -678,6 +710,40 @@
     }
 
     /**
+     * Deletes a database including its journal file and other auxiliary files
+     * that may have been created by the database engine.
+     *
+     * @param file The database file path.
+     * @return True if the database was successfully deleted.
+     */
+    public static boolean deleteDatabase(File file) {
+        if (file == null) {
+            throw new IllegalArgumentException("file must not be null");
+        }
+
+        boolean deleted = false;
+        deleted |= file.delete();
+        deleted |= new File(file.getPath() + "-journal").delete();
+        deleted |= new File(file.getPath() + "-shm").delete();
+        deleted |= new File(file.getPath() + "-wal").delete();
+
+        File dir = file.getParentFile();
+        if (dir != null) {
+            final String prefix = file.getName() + "-mj";
+            final FileFilter filter = new FileFilter() {
+                @Override
+                public boolean accept(File candidate) {
+                    return candidate.getName().startsWith(prefix);
+                }
+            };
+            for (File masterJournal : dir.listFiles(filter)) {
+                deleted |= masterJournal.delete();
+            }
+        }
+        return deleted;
+    }
+
+    /**
      * Reopens the database in read-write mode.
      * If the database is already read-write, does nothing.
      *
@@ -754,13 +820,6 @@
     }
 
     /**
-     * Close the database.
-     */
-    public void close() {
-        dispose(false);
-    }
-
-    /**
      * Registers a CustomFunction callback as a function that can be called from
      * SQLite database triggers.
      *
@@ -914,8 +973,12 @@
      * {@link SQLiteStatement}s are not synchronized, see the documentation for more details.
      */
     public SQLiteStatement compileStatement(String sql) throws SQLException {
-        throwIfNotOpen(); // fail fast
-        return new SQLiteStatement(this, sql, null);
+        acquireReference();
+        try {
+            return new SQLiteStatement(this, sql, null);
+        } finally {
+            releaseReference();
+        }
     }
 
     /**
@@ -1076,12 +1139,16 @@
             boolean distinct, String table, String[] columns,
             String selection, String[] selectionArgs, String groupBy,
             String having, String orderBy, String limit, CancellationSignal cancellationSignal) {
-        throwIfNotOpen(); // fail fast
-        String sql = SQLiteQueryBuilder.buildQueryString(
-                distinct, table, columns, selection, groupBy, having, orderBy, limit);
+        acquireReference();
+        try {
+            String sql = SQLiteQueryBuilder.buildQueryString(
+                    distinct, table, columns, selection, groupBy, having, orderBy, limit);
 
-        return rawQueryWithFactory(cursorFactory, sql, selectionArgs,
-                findEditTable(table), cancellationSignal);
+            return rawQueryWithFactory(cursorFactory, sql, selectionArgs,
+                    findEditTable(table), cancellationSignal);
+        } finally {
+            releaseReference();
+        }
     }
 
     /**
@@ -1226,12 +1293,15 @@
     public Cursor rawQueryWithFactory(
             CursorFactory cursorFactory, String sql, String[] selectionArgs,
             String editTable, CancellationSignal cancellationSignal) {
-        throwIfNotOpen(); // fail fast
-
-        SQLiteCursorDriver driver = new SQLiteDirectCursorDriver(this, sql, editTable,
-                cancellationSignal);
-        return driver.query(cursorFactory != null ? cursorFactory : mCursorFactory,
-                selectionArgs);
+        acquireReference();
+        try {
+            SQLiteCursorDriver driver = new SQLiteDirectCursorDriver(this, sql, editTable,
+                    cancellationSignal);
+            return driver.query(cursorFactory != null ? cursorFactory : mCursorFactory,
+                    selectionArgs);
+        } finally {
+            releaseReference();
+        }
     }
 
     /**
@@ -1350,38 +1420,44 @@
      */
     public long insertWithOnConflict(String table, String nullColumnHack,
             ContentValues initialValues, int conflictAlgorithm) {
-        StringBuilder sql = new StringBuilder();
-        sql.append("INSERT");
-        sql.append(CONFLICT_VALUES[conflictAlgorithm]);
-        sql.append(" INTO ");
-        sql.append(table);
-        sql.append('(');
+        acquireReference();
+        try {
+            StringBuilder sql = new StringBuilder();
+            sql.append("INSERT");
+            sql.append(CONFLICT_VALUES[conflictAlgorithm]);
+            sql.append(" INTO ");
+            sql.append(table);
+            sql.append('(');
 
-        Object[] bindArgs = null;
-        int size = (initialValues != null && initialValues.size() > 0) ? initialValues.size() : 0;
-        if (size > 0) {
-            bindArgs = new Object[size];
-            int i = 0;
-            for (String colName : initialValues.keySet()) {
-                sql.append((i > 0) ? "," : "");
-                sql.append(colName);
-                bindArgs[i++] = initialValues.get(colName);
+            Object[] bindArgs = null;
+            int size = (initialValues != null && initialValues.size() > 0)
+                    ? initialValues.size() : 0;
+            if (size > 0) {
+                bindArgs = new Object[size];
+                int i = 0;
+                for (String colName : initialValues.keySet()) {
+                    sql.append((i > 0) ? "," : "");
+                    sql.append(colName);
+                    bindArgs[i++] = initialValues.get(colName);
+                }
+                sql.append(')');
+                sql.append(" VALUES (");
+                for (i = 0; i < size; i++) {
+                    sql.append((i > 0) ? ",?" : "?");
+                }
+            } else {
+                sql.append(nullColumnHack + ") VALUES (NULL");
             }
             sql.append(')');
-            sql.append(" VALUES (");
-            for (i = 0; i < size; i++) {
-                sql.append((i > 0) ? ",?" : "?");
-            }
-        } else {
-            sql.append(nullColumnHack + ") VALUES (NULL");
-        }
-        sql.append(')');
 
-        SQLiteStatement statement = new SQLiteStatement(this, sql.toString(), bindArgs);
-        try {
-            return statement.executeInsert();
+            SQLiteStatement statement = new SQLiteStatement(this, sql.toString(), bindArgs);
+            try {
+                return statement.executeInsert();
+            } finally {
+                statement.close();
+            }
         } finally {
-            statement.close();
+            releaseReference();
         }
     }
 
@@ -1396,12 +1472,17 @@
      *         whereClause.
      */
     public int delete(String table, String whereClause, String[] whereArgs) {
-        SQLiteStatement statement =  new SQLiteStatement(this, "DELETE FROM " + table +
-                (!TextUtils.isEmpty(whereClause) ? " WHERE " + whereClause : ""), whereArgs);
+        acquireReference();
         try {
-            return statement.executeUpdateDelete();
+            SQLiteStatement statement =  new SQLiteStatement(this, "DELETE FROM " + table +
+                    (!TextUtils.isEmpty(whereClause) ? " WHERE " + whereClause : ""), whereArgs);
+            try {
+                return statement.executeUpdateDelete();
+            } finally {
+                statement.close();
+            }
         } finally {
-            statement.close();
+            releaseReference();
         }
     }
 
@@ -1436,38 +1517,43 @@
             throw new IllegalArgumentException("Empty values");
         }
 
-        StringBuilder sql = new StringBuilder(120);
-        sql.append("UPDATE ");
-        sql.append(CONFLICT_VALUES[conflictAlgorithm]);
-        sql.append(table);
-        sql.append(" SET ");
-
-        // move all bind args to one array
-        int setValuesSize = values.size();
-        int bindArgsSize = (whereArgs == null) ? setValuesSize : (setValuesSize + whereArgs.length);
-        Object[] bindArgs = new Object[bindArgsSize];
-        int i = 0;
-        for (String colName : values.keySet()) {
-            sql.append((i > 0) ? "," : "");
-            sql.append(colName);
-            bindArgs[i++] = values.get(colName);
-            sql.append("=?");
-        }
-        if (whereArgs != null) {
-            for (i = setValuesSize; i < bindArgsSize; i++) {
-                bindArgs[i] = whereArgs[i - setValuesSize];
-            }
-        }
-        if (!TextUtils.isEmpty(whereClause)) {
-            sql.append(" WHERE ");
-            sql.append(whereClause);
-        }
-
-        SQLiteStatement statement = new SQLiteStatement(this, sql.toString(), bindArgs);
+        acquireReference();
         try {
-            return statement.executeUpdateDelete();
+            StringBuilder sql = new StringBuilder(120);
+            sql.append("UPDATE ");
+            sql.append(CONFLICT_VALUES[conflictAlgorithm]);
+            sql.append(table);
+            sql.append(" SET ");
+
+            // move all bind args to one array
+            int setValuesSize = values.size();
+            int bindArgsSize = (whereArgs == null) ? setValuesSize : (setValuesSize + whereArgs.length);
+            Object[] bindArgs = new Object[bindArgsSize];
+            int i = 0;
+            for (String colName : values.keySet()) {
+                sql.append((i > 0) ? "," : "");
+                sql.append(colName);
+                bindArgs[i++] = values.get(colName);
+                sql.append("=?");
+            }
+            if (whereArgs != null) {
+                for (i = setValuesSize; i < bindArgsSize; i++) {
+                    bindArgs[i] = whereArgs[i - setValuesSize];
+                }
+            }
+            if (!TextUtils.isEmpty(whereClause)) {
+                sql.append(" WHERE ");
+                sql.append(whereClause);
+            }
+
+            SQLiteStatement statement = new SQLiteStatement(this, sql.toString(), bindArgs);
+            try {
+                return statement.executeUpdateDelete();
+            } finally {
+                statement.close();
+            }
         } finally {
-            statement.close();
+            releaseReference();
         }
     }
 
@@ -1545,24 +1631,29 @@
     }
 
     private int executeSql(String sql, Object[] bindArgs) throws SQLException {
-        if (DatabaseUtils.getSqlStatementType(sql) == DatabaseUtils.STATEMENT_ATTACH) {
-            boolean disableWal = false;
-            synchronized (mLock) {
-                if (!mHasAttachedDbsLocked) {
-                    mHasAttachedDbsLocked = true;
-                    disableWal = true;
+        acquireReference();
+        try {
+            if (DatabaseUtils.getSqlStatementType(sql) == DatabaseUtils.STATEMENT_ATTACH) {
+                boolean disableWal = false;
+                synchronized (mLock) {
+                    if (!mHasAttachedDbsLocked) {
+                        mHasAttachedDbsLocked = true;
+                        disableWal = true;
+                    }
+                }
+                if (disableWal) {
+                    disableWriteAheadLogging();
                 }
             }
-            if (disableWal) {
-                disableWriteAheadLogging();
-            }
-        }
 
-        SQLiteStatement statement = new SQLiteStatement(this, sql, bindArgs);
-        try {
-            return statement.executeUpdateDelete();
+            SQLiteStatement statement = new SQLiteStatement(this, sql, bindArgs);
+            try {
+                return statement.executeUpdateDelete();
+            } finally {
+                statement.close();
+            }
         } finally {
-            statement.close();
+            releaseReference();
         }
     }
 
@@ -1746,6 +1837,7 @@
 
             mIsWALEnabledLocked = true;
             mConfigurationLocked.maxConnectionPoolSize = SQLiteGlobal.getWALConnectionPoolSize();
+            mConfigurationLocked.syncMode = SQLiteGlobal.getWALSyncMode();
             mConfigurationLocked.journalMode = "WAL";
             mConnectionPoolLocked.reconfigure(mConfigurationLocked);
         }
@@ -1766,6 +1858,7 @@
 
             mIsWALEnabledLocked = false;
             mConfigurationLocked.maxConnectionPoolSize = 1;
+            mConfigurationLocked.syncMode = SQLiteGlobal.getDefaultSyncMode();
             mConfigurationLocked.journalMode = SQLiteGlobal.getDefaultJournalMode();
             mConnectionPoolLocked.reconfigure(mConfigurationLocked);
         }
@@ -1845,26 +1938,32 @@
                 attachedDbs.add(new Pair<String, String>("main", mConfigurationLocked.path));
                 return attachedDbs;
             }
+
+            acquireReference();
         }
 
-        // has attached databases. query sqlite to get the list of attached databases.
-        Cursor c = null;
         try {
-            c = rawQuery("pragma database_list;", null);
-            while (c.moveToNext()) {
-                // sqlite returns a row for each database in the returned list of databases.
-                //   in each row,
-                //       1st column is the database name such as main, or the database
-                //                              name specified on the "ATTACH" command
-                //       2nd column is the database file path.
-                attachedDbs.add(new Pair<String, String>(c.getString(1), c.getString(2)));
+            // has attached databases. query sqlite to get the list of attached databases.
+            Cursor c = null;
+            try {
+                c = rawQuery("pragma database_list;", null);
+                while (c.moveToNext()) {
+                    // sqlite returns a row for each database in the returned list of databases.
+                    //   in each row,
+                    //       1st column is the database name such as main, or the database
+                    //                              name specified on the "ATTACH" command
+                    //       2nd column is the database file path.
+                    attachedDbs.add(new Pair<String, String>(c.getString(1), c.getString(2)));
+                }
+            } finally {
+                if (c != null) {
+                    c.close();
+                }
             }
+            return attachedDbs;
         } finally {
-            if (c != null) {
-                c.close();
-            }
+            releaseReference();
         }
-        return attachedDbs;
     }
 
     /**
@@ -1881,35 +1980,38 @@
      * false otherwise.
      */
     public boolean isDatabaseIntegrityOk() {
-        throwIfNotOpen(); // fail fast
-
-        List<Pair<String, String>> attachedDbs = null;
+        acquireReference();
         try {
-            attachedDbs = getAttachedDbs();
-            if (attachedDbs == null) {
-                throw new IllegalStateException("databaselist for: " + getPath() + " couldn't " +
-                        "be retrieved. probably because the database is closed");
-            }
-        } catch (SQLiteException e) {
-            // can't get attachedDb list. do integrity check on the main database
-            attachedDbs = new ArrayList<Pair<String, String>>();
-            attachedDbs.add(new Pair<String, String>("main", getPath()));
-        }
-
-        for (int i = 0; i < attachedDbs.size(); i++) {
-            Pair<String, String> p = attachedDbs.get(i);
-            SQLiteStatement prog = null;
+            List<Pair<String, String>> attachedDbs = null;
             try {
-                prog = compileStatement("PRAGMA " + p.first + ".integrity_check(1);");
-                String rslt = prog.simpleQueryForString();
-                if (!rslt.equalsIgnoreCase("ok")) {
-                    // integrity_checker failed on main or attached databases
-                    Log.e(TAG, "PRAGMA integrity_check on " + p.second + " returned: " + rslt);
-                    return false;
+                attachedDbs = getAttachedDbs();
+                if (attachedDbs == null) {
+                    throw new IllegalStateException("databaselist for: " + getPath() + " couldn't " +
+                            "be retrieved. probably because the database is closed");
                 }
-            } finally {
-                if (prog != null) prog.close();
+            } catch (SQLiteException e) {
+                // can't get attachedDb list. do integrity check on the main database
+                attachedDbs = new ArrayList<Pair<String, String>>();
+                attachedDbs.add(new Pair<String, String>("main", getPath()));
             }
+
+            for (int i = 0; i < attachedDbs.size(); i++) {
+                Pair<String, String> p = attachedDbs.get(i);
+                SQLiteStatement prog = null;
+                try {
+                    prog = compileStatement("PRAGMA " + p.first + ".integrity_check(1);");
+                    String rslt = prog.simpleQueryForString();
+                    if (!rslt.equalsIgnoreCase("ok")) {
+                        // integrity_checker failed on main or attached databases
+                        Log.e(TAG, "PRAGMA integrity_check on " + p.second + " returned: " + rslt);
+                        return false;
+                    }
+                } finally {
+                    if (prog != null) prog.close();
+                }
+            }
+        } finally {
+            releaseReference();
         }
         return true;
     }
@@ -1919,12 +2021,6 @@
         return "SQLiteDatabase: " + getPath();
     }
 
-    private void throwIfNotOpen() {
-        synchronized (mConnectionPoolLocked) {
-            throwIfNotOpenLocked();
-        }
-    }
-
     private void throwIfNotOpenLocked() {
         if (mConnectionPoolLocked == null) {
             throw new IllegalStateException("The database '" + mConfigurationLocked.label
diff --git a/core/java/android/database/sqlite/SQLiteDatabaseConfiguration.java b/core/java/android/database/sqlite/SQLiteDatabaseConfiguration.java
index 32a1bcb..efbcaca 100644
--- a/core/java/android/database/sqlite/SQLiteDatabaseConfiguration.java
+++ b/core/java/android/database/sqlite/SQLiteDatabaseConfiguration.java
@@ -85,6 +85,13 @@
     public Locale locale;
 
     /**
+     * The database synchronization mode.
+     *
+     * Default is {@link SQLiteGlobal#getDefaultSyncMode()}.
+     */
+    public String syncMode;
+
+    /**
      * The database journal mode.
      *
      * Default is {@link SQLiteGlobal#getDefaultJournalMode()}.
@@ -117,6 +124,7 @@
         maxConnectionPoolSize = 1;
         maxSqlCacheSize = 25;
         locale = Locale.getDefault();
+        syncMode = SQLiteGlobal.getDefaultSyncMode();
         journalMode = SQLiteGlobal.getDefaultJournalMode();
     }
 
@@ -154,6 +162,7 @@
         maxConnectionPoolSize = other.maxConnectionPoolSize;
         maxSqlCacheSize = other.maxSqlCacheSize;
         locale = other.locale;
+        syncMode = other.syncMode;
         journalMode = other.journalMode;
         customFunctions.clear();
         customFunctions.addAll(other.customFunctions);
diff --git a/core/java/android/database/sqlite/SQLiteDebug.java b/core/java/android/database/sqlite/SQLiteDebug.java
index 10ce991..1197331 100644
--- a/core/java/android/database/sqlite/SQLiteDebug.java
+++ b/core/java/android/database/sqlite/SQLiteDebug.java
@@ -62,6 +62,9 @@
      */
     public static final boolean DEBUG_LOG_SLOW_QUERIES = Build.IS_DEBUGGABLE;
 
+    private SQLiteDebug() {
+    }
+
     /**
      * Determines whether a query should be logged.
      *
diff --git a/core/java/android/database/sqlite/SQLiteDirectCursorDriver.java b/core/java/android/database/sqlite/SQLiteDirectCursorDriver.java
index 3375e74..294edc4 100644
--- a/core/java/android/database/sqlite/SQLiteDirectCursorDriver.java
+++ b/core/java/android/database/sqlite/SQLiteDirectCursorDriver.java
@@ -25,7 +25,7 @@
  * 
  * @hide
  */
-public class SQLiteDirectCursorDriver implements SQLiteCursorDriver {
+public final class SQLiteDirectCursorDriver implements SQLiteCursorDriver {
     private final SQLiteDatabase mDatabase;
     private final String mEditTable; 
     private final String mSql;
diff --git a/core/java/android/database/sqlite/SQLiteGlobal.java b/core/java/android/database/sqlite/SQLiteGlobal.java
index af0cf45..5d8f80e 100644
--- a/core/java/android/database/sqlite/SQLiteGlobal.java
+++ b/core/java/android/database/sqlite/SQLiteGlobal.java
@@ -83,11 +83,19 @@
     }
 
     /**
-     * Gets the database synchronization mode.
+     * Gets the default database synchronization mode when WAL is not in use.
      */
-    public static String getSyncMode() {
+    public static String getDefaultSyncMode() {
         return Resources.getSystem().getString(
-                com.android.internal.R.string.db_sync_mode);
+                com.android.internal.R.string.db_default_sync_mode);
+    }
+
+    /**
+     * Gets the database synchronization mode when in WAL mode.
+     */
+    public static String getWALSyncMode() {
+        return Resources.getSystem().getString(
+                com.android.internal.R.string.db_wal_sync_mode);
     }
 
     /**
@@ -99,7 +107,7 @@
     }
 
     /**
-     * Gets the default connection pool size when in WAL mode.
+     * Gets the connection pool size when in WAL mode.
      */
     public static int getWALConnectionPoolSize() {
         return Math.max(2, Resources.getSystem().getInteger(
diff --git a/core/java/android/database/sqlite/SQLiteProgram.java b/core/java/android/database/sqlite/SQLiteProgram.java
index 9f0edfb..94a23cb 100644
--- a/core/java/android/database/sqlite/SQLiteProgram.java
+++ b/core/java/android/database/sqlite/SQLiteProgram.java
@@ -190,13 +190,6 @@
     }
 
     /**
-     * Release this program's resources, making it invalid.
-     */
-    public void close() {
-        releaseReference();
-    }
-
-    /**
      * Given an array of String bindArgs, this method binds all of them in one single call.
      *
      * @param bindArgs the String array of bind args, none of which must be null.
diff --git a/core/java/android/hardware/Camera.java b/core/java/android/hardware/Camera.java
index cca208a..573e6ea 100644
--- a/core/java/android/hardware/Camera.java
+++ b/core/java/android/hardware/Camera.java
@@ -36,7 +36,6 @@
 import java.util.List;
 import java.util.StringTokenizer;
 
-
 /**
  * The Camera class is used to set image capture settings, start/stop preview,
  * snap pictures, and retrieve frames for encoding for video.  This class is a
diff --git a/core/java/android/hardware/CameraSound.java b/core/java/android/hardware/CameraSound.java
deleted file mode 100644
index dc97ff09..0000000
--- a/core/java/android/hardware/CameraSound.java
+++ /dev/null
@@ -1,217 +0,0 @@
-/*
- * Copyright (C) 2011 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.hardware;
-
-import android.media.AudioManager;
-import android.media.MediaPlayer;
-import android.os.SystemProperties;
-import android.util.Log;
-
-import java.io.IOException;
-
-/**
- * <p>Use this class to play an appropriate sound when implementing a custom
- * still or video recording mechanism through the preview callbacks.</p>
- *
- * <p>There is no need to play sounds when using {@link #android.hardware.Camera#takePicture}
- * or {@link android.media.MediaRecorder} for still images or video,
- * respectively, as these play their own sounds when needed.</p>
- *
- * @hide
- */
-public class CameraSound {
-    private static final String TAG = "CameraSound";
-    /**
-     * The sound used by {@link android.hardware.Camera#takePicture} to
-     * indicate still image capture.
-     */
-    public static final int SHUTTER_CLICK         = 0;
-
-    /**
-     * A sound to indicate that focusing has completed. Because deciding
-     * when this occurs is application-dependent, this sound is not used by
-     * any methods in the Camera class.
-     */
-    public static final int FOCUS_COMPLETE        = 1;
-
-    /**
-     * The sound used by {@link android.media.MediaRecorder#start} to
-     * indicate the start of video recording.
-     */
-    public static final int START_VIDEO_RECORDING = 2;
-
-    /**
-     * The sound used by {@link android.media.MediaRecorder#stop} to
-     * indicate the end of video recording.
-     */
-    public static final int STOP_VIDEO_RECORDING  = 3;
-
-    private static final int NUM_SOUNDS           = 4;
-    private CameraSoundPlayer[] mCameraSoundPlayers;
-
-    public CameraSound() {
-    }
-
-    /**
-     * <p>Play one of the predefined platform sounds for camera actions.</p>
-     *
-     * <p>Use this method to play a platform-specific sound for various camera
-     * actions. The sound playing is done asynchronously, with the same behavior
-     * and content as the sounds played by {@link #takePicture takePicture},
-     * {@link android.media.MediaRecorder#start MediaRecorder.start}, and
-     * {@link android.media.MediaRecorder#stop MediaRecorder.stop}.</p>
-     *
-     * <p>Using this method makes it easy to match the default device sounds
-     * when recording or capturing data through the preview callbacks.</p>
-     *
-     * @param soundId The type of sound to play, selected from SHUTTER_CLICK,
-     *         FOCUS_COMPLETE, START_VIDEO_RECORDING, or STOP_VIDEO_RECORDING.
-     * @see android.hardware#takePicture
-     * @see android.media.MediaRecorder
-     * @see #SHUTTER_CLICK
-     * @see #FOCUS_COMPLETE
-     * @see #START_VIDEO_RECORDING
-     * @see #STOP_VIDEO_RECORDING
-     */
-    public void playSound(int soundId) {
-        if (mCameraSoundPlayers == null) {
-            mCameraSoundPlayers = new CameraSoundPlayer[NUM_SOUNDS];
-        }
-        if (mCameraSoundPlayers[soundId] == null) {
-            mCameraSoundPlayers[soundId] = new CameraSoundPlayer(soundId);
-        }
-        mCameraSoundPlayers[soundId].play();
-    }
-
-    public void release() {
-        if (mCameraSoundPlayers != null) {
-            for (CameraSoundPlayer csp: mCameraSoundPlayers) {
-                if (csp != null) {
-                    csp.release();
-                }
-            }
-            mCameraSoundPlayers = null;
-        }
-    }
-
-    private static class CameraSoundPlayer implements Runnable {
-        private int mSoundId;
-        private MediaPlayer mPlayer;
-        private Thread mThread;
-        private boolean mExit;
-        private int mPlayCount;
-
-        private static final String mShutterSound    =
-                "/system/media/audio/ui/camera_click.ogg";
-        private static final String mFocusSound      =
-                "/system/media/audio/ui/camera_focus.ogg";
-        private static final String mVideoStartSound =
-                "/system/media/audio/ui/VideoRecord.ogg";
-        private static final String mVideoStopSound  =
-                "/system/media/audio/ui/VideoRecord.ogg";
-
-        @Override
-        public void run() {
-            String soundFilePath;
-            switch (mSoundId) {
-                case SHUTTER_CLICK:
-                    soundFilePath = mShutterSound;
-                    break;
-                case FOCUS_COMPLETE:
-                    soundFilePath = mFocusSound;
-                    break;
-                case START_VIDEO_RECORDING:
-                    soundFilePath = mVideoStartSound;
-                    break;
-                case STOP_VIDEO_RECORDING:
-                    soundFilePath = mVideoStopSound;
-                    break;
-                default:
-                    Log.e(TAG, "Unknown sound " + mSoundId + " requested.");
-                    return;
-            }
-            mPlayer = new MediaPlayer();
-            try {
-                mPlayer.setAudioStreamType(AudioManager.STREAM_SYSTEM_ENFORCED);
-                mPlayer.setDataSource(soundFilePath);
-                mPlayer.setLooping(false);
-                mPlayer.prepare();
-            } catch(IOException e) {
-                Log.e(TAG, "Error setting up sound " + mSoundId, e);
-                return;
-            }
-
-            while(true) {
-                try {
-                    synchronized (this) {
-                        while(true) {
-                            if (mExit) {
-                                return;
-                            } else if (mPlayCount <= 0) {
-                                wait();
-                            } else {
-                                mPlayCount--;
-                                break;
-                            }
-                        }
-                    }
-                    mPlayer.start();
-                } catch (Exception e) {
-                    Log.e(TAG, "Error playing sound " + mSoundId, e);
-                }
-            }
-        }
-
-        public CameraSoundPlayer(int soundId) {
-            mSoundId = soundId;
-        }
-
-        public void play() {
-            if (mThread == null) {
-                mThread = new Thread(this);
-                mThread.start();
-            }
-            synchronized (this) {
-                mPlayCount++;
-                notifyAll();
-            }
-        }
-
-        public void release() {
-            if (mThread != null) {
-                synchronized (this) {
-                    mExit = true;
-                    notifyAll();
-                }
-                try {
-                    mThread.join();
-                } catch (InterruptedException e) {
-                }
-                mThread = null;
-            }
-            if (mPlayer != null) {
-                mPlayer.release();
-                mPlayer = null;
-            }
-        }
-
-        @Override
-        protected void finalize() {
-            release();
-        }
-    }
-}
\ No newline at end of file
diff --git a/core/java/android/nfc/INfcAdapter.aidl b/core/java/android/nfc/INfcAdapter.aidl
index 61bc324..10da9ef 100644
--- a/core/java/android/nfc/INfcAdapter.aidl
+++ b/core/java/android/nfc/INfcAdapter.aidl
@@ -45,4 +45,6 @@
     void setForegroundNdefPush(in NdefMessage msg, in INdefPushCallback callback);
 
     void dispatch(in Tag tag);
+
+    void setP2pModes(int initatorModes, int targetModes);
 }
diff --git a/core/java/android/nfc/NfcAdapter.java b/core/java/android/nfc/NfcAdapter.java
index 5176857..23f96e3 100644
--- a/core/java/android/nfc/NfcAdapter.java
+++ b/core/java/android/nfc/NfcAdapter.java
@@ -903,6 +903,17 @@
     /**
      * @hide
      */
+    public void setP2pModes(int initiatorModes, int targetModes) {
+        try {
+            sService.setP2pModes(initiatorModes, targetModes);
+        } catch (RemoteException e) {
+            attemptDeadServiceRecovery(e);
+        }
+    }
+
+    /**
+     * @hide
+     */
     public INfcAdapterExtras getNfcAdapterExtrasInterface() {
         if (mContext == null) {
             throw new UnsupportedOperationException("You need a context on NfcAdapter to use the "
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index c106092..63275cf 100644
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -371,6 +371,15 @@
 
         /**
          * Next up on Android!
+         *
+         * <p>Applications targeting this or a later release will get these
+         * new changes in behavior:</p>
+         * <ul>
+         * <li> Calls to {@link android.content.pm.PackageManager#setComponentEnabledSetting
+         * PackageManager.setComponentEnabledSetting} will now throw an
+         * IllegalArgumentException if the given component class name does not
+         * exist in the application's manifest.
+         * </ul>
          */
         public static final int JELLY_BEAN = CUR_DEVELOPMENT;
     }
diff --git a/core/java/android/os/ParcelFileDescriptor.java b/core/java/android/os/ParcelFileDescriptor.java
index ac15d9c..3e90dfc 100644
--- a/core/java/android/os/ParcelFileDescriptor.java
+++ b/core/java/android/os/ParcelFileDescriptor.java
@@ -15,6 +15,7 @@
  */
 
 package android.os;
+import java.io.Closeable;
 import java.io.File;
 import java.io.FileDescriptor;
 import java.io.FileInputStream;
@@ -28,7 +29,7 @@
  * The FileDescriptor returned by {@link Parcel#readFileDescriptor}, allowing
  * you to close it when done with it.
  */
-public class ParcelFileDescriptor implements Parcelable {
+public class ParcelFileDescriptor implements Parcelable, Closeable {
     private final FileDescriptor mFileDescriptor;
     private boolean mClosed;
     //this field is to create wrapper for ParcelFileDescriptor using another
diff --git a/core/java/android/os/StrictMode.java b/core/java/android/os/StrictMode.java
index 99f58a0..759be91 100644
--- a/core/java/android/os/StrictMode.java
+++ b/core/java/android/os/StrictMode.java
@@ -20,7 +20,10 @@
 import android.app.ActivityThread;
 import android.app.ApplicationErrorReport;
 import android.app.IActivityManager;
+import android.content.BroadcastReceiver;
+import android.content.Context;
 import android.content.Intent;
+import android.content.ServiceConnection;
 import android.util.Log;
 import android.util.Printer;
 import android.util.Singleton;
@@ -106,7 +109,7 @@
  * effort mechanism.  Notably, disk or network access from JNI calls
  * won't necessarily trigger it.  Future versions of Android may catch
  * more (or fewer) operations, so you should never leave StrictMode
- * enabled in shipping applications on the Android Market.
+ * enabled in applications distributed on Google Play.
  */
 public final class StrictMode {
     private static final String TAG = "StrictMode";
@@ -195,9 +198,15 @@
      */
     private static final int DETECT_VM_INSTANCE_LEAKS = 0x1000;  // for VmPolicy
 
+    /**
+     * @hide
+     */
+    public static final int DETECT_VM_REGISTRATION_LEAKS = 0x2000;  // for VmPolicy
+
     private static final int ALL_VM_DETECT_BITS =
             DETECT_VM_CURSOR_LEAKS | DETECT_VM_CLOSABLE_LEAKS |
-            DETECT_VM_ACTIVITY_LEAKS | DETECT_VM_INSTANCE_LEAKS;
+            DETECT_VM_ACTIVITY_LEAKS | DETECT_VM_INSTANCE_LEAKS |
+            DETECT_VM_REGISTRATION_LEAKS;
 
     /**
      * @hide
@@ -618,8 +627,8 @@
              * but will likely expand in future releases.
              */
             public Builder detectAll() {
-                return enable(DETECT_VM_ACTIVITY_LEAKS |
-                        DETECT_VM_CURSOR_LEAKS | DETECT_VM_CLOSABLE_LEAKS);
+                return enable(DETECT_VM_ACTIVITY_LEAKS | DETECT_VM_CURSOR_LEAKS
+                        | DETECT_VM_CLOSABLE_LEAKS | DETECT_VM_REGISTRATION_LEAKS);
             }
 
             /**
@@ -648,6 +657,15 @@
             }
 
             /**
+             * Detect when a {@link BroadcastReceiver} or
+             * {@link ServiceConnection} is leaked during {@link Context}
+             * teardown.
+             */
+            public Builder detectLeakedRegistrationObjects() {
+                return enable(DETECT_VM_REGISTRATION_LEAKS);
+            }
+
+            /**
              * Crashes the whole process on violation.  This penalty runs at
              * the end of all enabled penalties so yo you'll still get
              * your logging or other violations before the process dies.
@@ -1499,6 +1517,13 @@
     /**
      * @hide
      */
+    public static boolean vmRegistrationLeaksEnabled() {
+        return (sVmPolicyMask & DETECT_VM_REGISTRATION_LEAKS) != 0;
+    }
+
+    /**
+     * @hide
+     */
     public static void onSqliteObjectLeaked(String message, Throwable originStack) {
         onVmPolicyViolation(message, originStack);
     }
@@ -1510,6 +1535,20 @@
         onVmPolicyViolation(null, originStack);
     }
 
+    /**
+     * @hide
+     */
+    public static void onIntentReceiverLeaked(Throwable originStack) {
+        onVmPolicyViolation(null, originStack);
+    }
+
+    /**
+     * @hide
+     */
+    public static void onServiceConnectionLeaked(Throwable originStack) {
+        onVmPolicyViolation(null, originStack);
+    }
+
     // Map from VM violation fingerprint to uptime millis.
     private static final HashMap<Integer, Long> sLastVmViolationTime = new HashMap<Integer, Long>();
 
diff --git a/core/java/android/provider/CalendarContract.java b/core/java/android/provider/CalendarContract.java
index fa59b32f..83799c4 100644
--- a/core/java/android/provider/CalendarContract.java
+++ b/core/java/android/provider/CalendarContract.java
@@ -856,6 +856,17 @@
         public static final String EVENT_COLOR_KEY = "eventColor_index";
 
         /**
+         * This will be {@link #EVENT_COLOR} if it is not null; otherwise, this will be
+         * {@link Calendars#CALENDAR_COLOR}.
+         * Read-only value. To modify, write to {@link #EVENT_COLOR} or
+         * {@link Calendars#CALENDAR_COLOR} directly.
+         *<P>
+         *     Type: INTEGER
+         *</P>
+         */
+        public static final String DISPLAY_COLOR = "displayColor";
+
+        /**
          * The event status. Column name.
          * <P>Type: INTEGER (one of {@link #STATUS_TENTATIVE}...)</P>
          */
diff --git a/core/java/android/provider/MediaStore.java b/core/java/android/provider/MediaStore.java
index d3ad63d..6c6b1184 100644
--- a/core/java/android/provider/MediaStore.java
+++ b/core/java/android/provider/MediaStore.java
@@ -1833,19 +1833,19 @@
             public static final String LANGUAGE = "language";
 
             /**
-             * The latitude where the image was captured.
+             * The latitude where the video was captured.
              * <P>Type: DOUBLE</P>
              */
             public static final String LATITUDE = "latitude";
 
             /**
-             * The longitude where the image was captured.
+             * The longitude where the video was captured.
              * <P>Type: DOUBLE</P>
              */
             public static final String LONGITUDE = "longitude";
 
             /**
-             * The date & time that the image was taken in units
+             * The date & time that the video was taken in units
              * of milliseconds since jan 1, 1970.
              * <P>Type: INTEGER</P>
              */
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index b42417a..bc6594b 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -2644,10 +2644,10 @@
 
         /**
          * Whether the package installer should allow installation of apps downloaded from
-         * sources other than the Android Market (vending machine).
+         * sources other than Google Play.
          *
          * 1 = allow installing from other sources
-         * 0 = only allow installing from the Android Market
+         * 0 = only allow installing from Google Play
          */
         public static final String INSTALL_NON_MARKET_APPS = "install_non_market_apps";
 
diff --git a/core/java/android/text/Layout.java b/core/java/android/text/Layout.java
index bdfe940..516ce2a 100644
--- a/core/java/android/text/Layout.java
+++ b/core/java/android/text/Layout.java
@@ -76,7 +76,6 @@
                                         int start, int end,
                                         TextPaint paint) {
         float need = 0;
-        TextPaint workPaint = new TextPaint();
 
         int next;
         for (int i = start; i <= end; i = next) {
@@ -86,7 +85,7 @@
                 next = end;
 
             // note, omits trailing paragraph char
-            float w = measurePara(paint, workPaint, source, i, next);
+            float w = measurePara(paint, source, i, next);
 
             if (w > need)
                 need = w;
@@ -189,106 +188,34 @@
      * Draw this Layout on the specified canvas, with the highlight path drawn
      * between the background and the text.
      *
-     * @param c the canvas
+     * @param canvas the canvas
      * @param highlight the path of the highlight or cursor; can be null
      * @param highlightPaint the paint for the highlight
      * @param cursorOffsetVertical the amount to temporarily translate the
      *        canvas while rendering the highlight
      */
-    public void draw(Canvas c, Path highlight, Paint highlightPaint,
-                     int cursorOffsetVertical) {
-        int dtop, dbottom;
+    public void draw(Canvas canvas, Path highlight, Paint highlightPaint,
+            int cursorOffsetVertical) {
+        final long lineRange = getLineRangeForDraw(canvas);
+        int firstLine = TextUtils.unpackRangeStartFromLong(lineRange);
+        int lastLine = TextUtils.unpackRangeEndFromLong(lineRange);
+        if (lastLine < 0) return;
 
-        synchronized (sTempRect) {
-            if (!c.getClipBounds(sTempRect)) {
-                return;
-            }
+        drawBackground(canvas, highlight, highlightPaint, cursorOffsetVertical,
+                firstLine, lastLine);
+        drawText(canvas, firstLine, lastLine);
+    }
 
-            dtop = sTempRect.top;
-            dbottom = sTempRect.bottom;
-        }
-
-        int top = 0;
-        int bottom = getLineTop(getLineCount());
-
-        if (dtop > top) {
-            top = dtop;
-        }
-        if (dbottom < bottom) {
-            bottom = dbottom;
-        }
-
-        int first = getLineForVertical(top);
-        int last = getLineForVertical(bottom);
-
-        int previousLineBottom = getLineTop(first);
-        int previousLineEnd = getLineStart(first);
-
-        TextPaint paint = mPaint;
-        CharSequence buf = mText;
-        int width = mWidth;
-        boolean spannedText = mSpannedText;
-
+    /**
+     * @hide
+     */
+    public void drawText(Canvas canvas, int firstLine, int lastLine) {
+        int previousLineBottom = getLineTop(firstLine);
+        int previousLineEnd = getLineStart(firstLine);
         ParagraphStyle[] spans = NO_PARA_SPANS;
         int spanEnd = 0;
-        int textLength = 0;
-
-        // First, draw LineBackgroundSpans.
-        // LineBackgroundSpans know nothing about the alignment, margins, or
-        // direction of the layout or line.  XXX: Should they?
-        // They are evaluated at each line.
-        if (spannedText) {
-            Spanned sp = (Spanned) buf;
-            textLength = buf.length();
-            for (int i = first; i <= last; i++) {
-                int start = previousLineEnd;
-                int end = getLineStart(i+1);
-                previousLineEnd = end;
-
-                int ltop = previousLineBottom;
-                int lbottom = getLineTop(i+1);
-                previousLineBottom = lbottom;
-                int lbaseline = lbottom - getLineDescent(i);
-
-                if (start >= spanEnd) {
-                    // These should be infrequent, so we'll use this so that
-                    // we don't have to check as often.
-                    spanEnd = sp.nextSpanTransition(start, textLength,
-                            LineBackgroundSpan.class);
-                    // All LineBackgroundSpans on a line contribute to its
-                    // background.
-                   spans = getParagraphSpans(sp, start, end, LineBackgroundSpan.class);
-                }
-
-                for (int n = 0; n < spans.length; n++) {
-                    LineBackgroundSpan back = (LineBackgroundSpan) spans[n];
-
-                    back.drawBackground(c, paint, 0, width,
-                                       ltop, lbaseline, lbottom,
-                                       buf, start, end,
-                                       i);
-                }
-            }
-            // reset to their original values
-            spanEnd = 0;
-            previousLineBottom = getLineTop(first);
-            previousLineEnd = getLineStart(first);
-            spans = NO_PARA_SPANS;
-        }
-
-        // There can be a highlight even without spans if we are drawing
-        // a non-spanned transformation of a spanned editing buffer.
-        if (highlight != null) {
-            if (cursorOffsetVertical != 0) {
-                c.translate(0, cursorOffsetVertical);
-            }
-
-            c.drawPath(highlight, highlightPaint);
-
-            if (cursorOffsetVertical != 0) {
-                c.translate(0, -cursorOffsetVertical);
-            }
-        }
+        TextPaint paint = mPaint;
+        CharSequence buf = mText;
 
         Alignment paraAlign = mAlignment;
         TabStops tabStops = null;
@@ -296,13 +223,11 @@
 
         TextLine tl = TextLine.obtain();
 
-        // Next draw the lines, one at a time.
-        // the baseline is the top of the following line minus the current
-        // line's descent.
-        for (int i = first; i <= last; i++) {
+        // Draw the lines, one at a time.
+        // The baseline is the top of the following line minus the current line's descent.
+        for (int i = firstLine; i <= lastLine; i++) {
             int start = previousLineEnd;
-
-            previousLineEnd = getLineStart(i+1);
+            previousLineEnd = getLineStart(i + 1);
             int end = getLineVisibleEnd(i, start, previousLineEnd);
 
             int ltop = previousLineBottom;
@@ -314,10 +239,10 @@
             int left = 0;
             int right = mWidth;
 
-            if (spannedText) {
+            if (mSpannedText) {
                 Spanned sp = (Spanned) buf;
-                boolean isFirstParaLine = (start == 0 ||
-                        buf.charAt(start - 1) == '\n');
+                int textLength = buf.length();
+                boolean isFirstParaLine = (start == 0 || buf.charAt(start - 1) == '\n');
 
                 // New batch of paragraph styles, collect into spans array.
                 // Compute the alignment, last alignment style wins.
@@ -329,13 +254,13 @@
                 // just collect the ones present at the start of the paragraph.
                 // If spanEnd is before the end of the paragraph, that's not
                 // our problem.
-                if (start >= spanEnd && (i == first || isFirstParaLine)) {
+                if (start >= spanEnd && (i == firstLine || isFirstParaLine)) {
                     spanEnd = sp.nextSpanTransition(start, textLength,
                                                     ParagraphStyle.class);
                     spans = getParagraphSpans(sp, start, spanEnd, ParagraphStyle.class);
 
                     paraAlign = mAlignment;
-                    for (int n = spans.length-1; n >= 0; n--) {
+                    for (int n = spans.length - 1; n >= 0; n--) {
                         if (spans[n] instanceof AlignmentSpan) {
                             paraAlign = ((AlignmentSpan) spans[n]).getAlignment();
                             break;
@@ -359,12 +284,12 @@
                         }
 
                         if (dir == DIR_RIGHT_TO_LEFT) {
-                            margin.drawLeadingMargin(c, paint, right, dir, ltop,
+                            margin.drawLeadingMargin(canvas, paint, right, dir, ltop,
                                                      lbaseline, lbottom, buf,
                                                      start, end, isFirstParaLine, this);
                             right -= margin.getLeadingMargin(useFirstLineMargin);
                         } else {
-                            margin.drawLeadingMargin(c, paint, left, dir, ltop,
+                            margin.drawLeadingMargin(canvas, paint, left, dir, ltop,
                                                      lbaseline, lbottom, buf,
                                                      start, end, isFirstParaLine, this);
                             left += margin.getLeadingMargin(useFirstLineMargin);
@@ -416,13 +341,12 @@
             }
 
             Directions directions = getLineDirections(i);
-            if (directions == DIRS_ALL_LEFT_TO_RIGHT &&
-                    !spannedText && !hasTabOrEmoji) {
+            if (directions == DIRS_ALL_LEFT_TO_RIGHT && !mSpannedText && !hasTabOrEmoji) {
                 // XXX: assumes there's nothing additional to be done
-                c.drawText(buf, start, end, x, lbaseline, paint);
+                canvas.drawText(buf, start, end, x, lbaseline, paint);
             } else {
                 tl.set(paint, buf, start, end, dir, directions, hasTabOrEmoji, tabStops);
-                tl.draw(c, x, ltop, lbaseline, lbottom);
+                tl.draw(canvas, x, ltop, lbaseline, lbottom);
             }
         }
 
@@ -430,6 +354,85 @@
     }
 
     /**
+     * @hide
+     */
+    public void drawBackground(Canvas canvas, Path highlight, Paint highlightPaint,
+            int cursorOffsetVertical, int firstLine, int lastLine) {
+        // First, draw LineBackgroundSpans.
+        // LineBackgroundSpans know nothing about the alignment, margins, or
+        // direction of the layout or line.  XXX: Should they?
+        // They are evaluated at each line.
+        if (mSpannedText) {
+            int previousLineBottom = getLineTop(firstLine);
+            int previousLineEnd = getLineStart(firstLine);
+            ParagraphStyle[] spans = NO_PARA_SPANS;
+            TextPaint paint = mPaint;
+            CharSequence buf = mText;
+            int spanEnd = 0;
+            final int width = mWidth;
+            Spanned sp = (Spanned) buf;
+            int textLength = buf.length();
+            for (int i = firstLine; i <= lastLine; i++) {
+                int start = previousLineEnd;
+                int end = getLineStart(i + 1);
+                previousLineEnd = end;
+
+                int ltop = previousLineBottom;
+                int lbottom = getLineTop(i + 1);
+                previousLineBottom = lbottom;
+                int lbaseline = lbottom - getLineDescent(i);
+
+                if (start >= spanEnd) {
+                    // These should be infrequent, so we'll use this so that
+                    // we don't have to check as often.
+                    spanEnd = sp.nextSpanTransition(start, textLength, LineBackgroundSpan.class);
+                    // All LineBackgroundSpans on a line contribute to its background.
+                    spans = getParagraphSpans(sp, start, end, LineBackgroundSpan.class);
+                }
+
+                for (int n = 0; n < spans.length; n++) {
+                    LineBackgroundSpan back = (LineBackgroundSpan) spans[n];
+                    back.drawBackground(canvas, paint, 0, width,
+                            ltop, lbaseline, lbottom,
+                            buf, start, end, i);
+                }
+            }
+        }
+
+        // There can be a highlight even without spans if we are drawing
+        // a non-spanned transformation of a spanned editing buffer.
+        if (highlight != null) {
+            if (cursorOffsetVertical != 0) canvas.translate(0, cursorOffsetVertical);
+            canvas.drawPath(highlight, highlightPaint);
+            if (cursorOffsetVertical != 0) canvas.translate(0, -cursorOffsetVertical);
+        }
+    }
+
+    /**
+     * @param canvas
+     * @return The range of lines that need to be drawn, possibly empty.
+     * @hide
+     */
+    public long getLineRangeForDraw(Canvas canvas) {
+        int dtop, dbottom;
+
+        synchronized (sTempRect) {
+            if (!canvas.getClipBounds(sTempRect)) {
+                // Negative range end used as a special flag
+                return TextUtils.packRangeInLong(0, -1);
+            }
+
+            dtop = sTempRect.top;
+            dbottom = sTempRect.bottom;
+        }
+
+        final int top = Math.max(dtop, 0);
+        final int bottom = Math.min(getLineTop(getLineCount()), dbottom);
+
+        return TextUtils.packRangeInLong(getLineForVertical(top), getLineForVertical(bottom));
+    }
+
+    /**
      * Return the start position of the line, given the left and right bounds
      * of the margins.
      *
@@ -460,7 +463,8 @@
                 int start = getLineStart(line);
                 int spanEnd = spanned.nextSpanTransition(start, spanned.length(),
                         TabStopSpan.class);
-                TabStopSpan[] tabSpans = getParagraphSpans(spanned, start, spanEnd, TabStopSpan.class);
+                TabStopSpan[] tabSpans = getParagraphSpans(spanned, start, spanEnd,
+                        TabStopSpan.class);
                 if (tabSpans.length > 0) {
                     tabStops = new TabStops(TAB_INCREMENT, tabSpans);
                 }
@@ -1481,8 +1485,7 @@
     }
 
     /* package */
-    static float measurePara(TextPaint paint, TextPaint workPaint,
-            CharSequence text, int start, int end) {
+    static float measurePara(TextPaint paint, CharSequence text, int start, int end) {
 
         MeasuredText mt = MeasuredText.obtain();
         TextLine tl = TextLine.obtain();
@@ -1659,7 +1662,7 @@
      */
     /* package */ static <T> T[] getParagraphSpans(Spanned text, int start, int end, Class<T> type) {
         if (start == end && start > 0) {
-            return (T[]) ArrayUtils.emptyArray(type);
+            return ArrayUtils.emptyArray(type);
         }
 
         return text.getSpans(start, end, type);
@@ -1777,8 +1780,7 @@
 
     }
 
-    /* package */ static class SpannedEllipsizer
-                    extends Ellipsizer implements Spanned {
+    /* package */ static class SpannedEllipsizer extends Ellipsizer implements Spanned {
         private Spanned mSpanned;
 
         public SpannedEllipsizer(CharSequence display) {
@@ -1802,6 +1804,7 @@
             return mSpanned.getSpanFlags(tag);
         }
 
+        @SuppressWarnings("rawtypes")
         public int nextSpanTransition(int start, int limit, Class type) {
             return mSpanned.nextSpanTransition(start, limit, type);
         }
diff --git a/core/java/android/text/MeasuredText.java b/core/java/android/text/MeasuredText.java
index a52e2ba..715d1f2 100644
--- a/core/java/android/text/MeasuredText.java
+++ b/core/java/android/text/MeasuredText.java
@@ -222,23 +222,27 @@
         return wid;
     }
 
-    int breakText(int start, int limit, boolean forwards, float width) {
+    int breakText(int limit, boolean forwards, float width) {
         float[] w = mWidths;
         if (forwards) {
-            for (int i = start; i < limit; ++i) {
-                if ((width -= w[i]) < 0) {
-                    return i - start;
-                }
+            int i = 0;
+            while (i < limit) {
+                width -= w[i];
+                if (width < 0.0f) break;
+                i++;
             }
+            while (i > 0 && mChars[i - 1] == ' ') i--;
+            return i;
         } else {
-            for (int i = limit; --i >= start;) {
-                if ((width -= w[i]) < 0) {
-                    return limit - i -1;
-                }
+            int i = limit - 1;
+            while (i >= 0) {
+                width -= w[i];
+                if (width < 0.0f) break;
+                i--;
             }
+            while (i < limit - 1 && mChars[i + 1] == ' ') i++;
+            return limit - i - 1;
         }
-
-        return limit - start;
     }
 
     float measure(int start, int limit) {
diff --git a/core/java/android/text/TextUtils.java b/core/java/android/text/TextUtils.java
index 43dfc81..270624c 100644
--- a/core/java/android/text/TextUtils.java
+++ b/core/java/android/text/TextUtils.java
@@ -1091,13 +1091,13 @@
             if (avail < 0) {
                 // it all goes
             } else if (where == TruncateAt.START) {
-                right = len - mt.breakText(0, len, false, avail);
+                right = len - mt.breakText(len, false, avail);
             } else if (where == TruncateAt.END || where == TruncateAt.END_SMALL) {
-                left = mt.breakText(0, len, true, avail);
+                left = mt.breakText(len, true, avail);
             } else {
-                right = len - mt.breakText(0, len, false, avail / 2);
+                right = len - mt.breakText(len, false, avail / 2);
                 avail -= mt.measure(right, len);
-                left = mt.breakText(0, right, true, avail);
+                left = mt.breakText(right, true, avail);
             }
 
             if (callback != null) {
@@ -1664,6 +1664,36 @@
         }
     }
 
+    /**
+     * Pack 2 int values into a long, useful as a return value for a range
+     * @see #unpackRangeStartFromLong(long)
+     * @see #unpackRangeEndFromLong(long)
+     * @hide
+     */
+    public static long packRangeInLong(int start, int end) {
+        return (((long) start) << 32) | end;
+    }
+
+    /**
+     * Get the start value from a range packed in a long by {@link #packRangeInLong(int, int)}
+     * @see #unpackRangeEndFromLong(long)
+     * @see #packRangeInLong(int, int)
+     * @hide
+     */
+    public static int unpackRangeStartFromLong(long range) {
+        return (int) (range >>> 32);
+    }
+
+    /**
+     * Get the end value from a range packed in a long by {@link #packRangeInLong(int, int)}
+     * @see #unpackRangeStartFromLong(long)
+     * @see #packRangeInLong(int, int)
+     * @hide
+     */
+    public static int unpackRangeEndFromLong(long range) {
+        return (int) (range & 0x00000000FFFFFFFFL);
+    }
+
     private static Object sLock = new Object();
     private static char[] sTemp = null;
 
diff --git a/core/java/android/view/Choreographer.java b/core/java/android/view/Choreographer.java
index 42c3913..f4d7af9 100644
--- a/core/java/android/view/Choreographer.java
+++ b/core/java/android/view/Choreographer.java
@@ -81,6 +81,8 @@
     private static final int MSG_DO_ANIMATION = 0;
     private static final int MSG_DO_DRAW = 1;
     private static final int MSG_DO_SCHEDULE_VSYNC = 2;
+    private static final int MSG_POST_DELAYED_ANIMATION = 3;
+    private static final int MSG_POST_DELAYED_DRAW = 4;
 
     private final Object mLock = new Object();
 
@@ -150,7 +152,7 @@
     }
 
     /**
-     * Posts a callback to run on the next animation cycle and schedules an animation cycle.
+     * Posts a callback to run on the next animation cycle.
      * The callback only runs once and then is automatically removed.
      *
      * @param runnable The callback to run during the next animation cycle.
@@ -161,6 +163,10 @@
         if (runnable == null) {
             throw new IllegalArgumentException("runnable must not be null");
         }
+        postAnimationCallbackUnchecked(runnable);
+    }
+
+    private void postAnimationCallbackUnchecked(Runnable runnable) {
         synchronized (mLock) {
             mAnimationCallbacks = addCallbackLocked(mAnimationCallbacks, runnable);
             scheduleAnimationLocked();
@@ -168,25 +174,49 @@
     }
 
     /**
-     * Removes an animation callback.
+     * Posts a callback to run on the next animation cycle following the specified delay.
+     * The callback only runs once and then is automatically removed.
+     *
+     * @param runnable The callback to run during the next animation cycle following
+     * the specified delay.
+     * @param delayMillis The delay time in milliseconds.
+     *
+     * @see #removeAnimationCallback
+     */
+    public void postAnimationCallbackDelayed(Runnable runnable, long delayMillis) {
+        if (runnable == null) {
+            throw new IllegalArgumentException("runnable must not be null");
+        }
+        if (delayMillis <= 0) {
+            postAnimationCallbackUnchecked(runnable);
+        } else {
+            Message msg = mHandler.obtainMessage(MSG_POST_DELAYED_ANIMATION, runnable);
+            mHandler.sendMessageDelayed(msg, delayMillis);
+        }
+    }
+
+    /**
+     * Removes animation callbacks for the specified runnable.
      * Does nothing if the specified animation callback has not been posted or has already
      * been removed.
      *
      * @param runnable The animation callback to remove.
      *
      * @see #postAnimationCallback
+     * @see #postAnimationCallbackDelayed
      */
-    public void removeAnimationCallback(Runnable runnable) {
+    public void removeAnimationCallbacks(Runnable runnable) {
         if (runnable == null) {
             throw new IllegalArgumentException("runnable must not be null");
         }
         synchronized (mLock) {
-            mAnimationCallbacks = removeCallbackLocked(mAnimationCallbacks, runnable);
+            mAnimationCallbacks = removeCallbacksLocked(mAnimationCallbacks, runnable);
         }
+        mHandler.removeMessages(MSG_POST_DELAYED_ANIMATION, runnable);
     }
 
     /**
-     * Posts a callback to run on the next draw cycle and schedules a draw cycle.
+     * Posts a callback to run on the next draw cycle.
      * The callback only runs once and then is automatically removed.
      *
      * @param runnable The callback to run during the next draw cycle.
@@ -197,6 +227,10 @@
         if (runnable == null) {
             throw new IllegalArgumentException("runnable must not be null");
         }
+        postDrawCallbackUnchecked(runnable);
+    }
+
+    private void postDrawCallbackUnchecked(Runnable runnable) {
         synchronized (mLock) {
             mDrawCallbacks = addCallbackLocked(mDrawCallbacks, runnable);
             scheduleDrawLocked();
@@ -204,21 +238,45 @@
     }
 
     /**
-     * Removes a draw callback.
+     * Posts a callback to run on the next draw cycle following the specified delay.
+     * The callback only runs once and then is automatically removed.
+     *
+     * @param runnable The callback to run during the next draw cycle following
+     * the specified delay.
+     * @param delayMillis The delay time in milliseconds.
+     *
+     * @see #removeDrawCallback
+     */
+    public void postDrawCallbackDelayed(Runnable runnable, long delayMillis) {
+        if (runnable == null) {
+            throw new IllegalArgumentException("runnable must not be null");
+        }
+        if (delayMillis <= 0) {
+            postDrawCallbackUnchecked(runnable);
+        } else {
+            Message msg = mHandler.obtainMessage(MSG_POST_DELAYED_DRAW, runnable);
+            mHandler.sendMessageDelayed(msg, delayMillis);
+        }
+    }
+
+    /**
+     * Removes draw callbacks for the specified runnable.
      * Does nothing if the specified draw callback has not been posted or has already
      * been removed.
      *
      * @param runnable The draw callback to remove.
      *
      * @see #postDrawCallback
+     * @see #postDrawCallbackDelayed
      */
-    public void removeDrawCallback(Runnable runnable) {
+    public void removeDrawCallbacks(Runnable runnable) {
         if (runnable == null) {
             throw new IllegalArgumentException("runnable must not be null");
         }
         synchronized (mLock) {
-            mDrawCallbacks = removeCallbackLocked(mDrawCallbacks, runnable);
+            mDrawCallbacks = removeCallbacksLocked(mDrawCallbacks, runnable);
         }
+        mHandler.removeMessages(MSG_POST_DELAYED_DRAW, runnable);
     }
 
     private void scheduleAnimationLocked() {
@@ -369,7 +427,7 @@
         return head;
     }
 
-    private Callback removeCallbackLocked(Callback head, Runnable runnable) {
+    private Callback removeCallbacksLocked(Callback head, Runnable runnable) {
         Callback predecessor = null;
         for (Callback callback = head; callback != null;) {
             final Callback next = callback.next;
@@ -438,6 +496,12 @@
                 case MSG_DO_SCHEDULE_VSYNC:
                     doScheduleVsync();
                     break;
+                case MSG_POST_DELAYED_ANIMATION:
+                    postAnimationCallbackUnchecked((Runnable)msg.obj);
+                    break;
+                case MSG_POST_DELAYED_DRAW:
+                    postDrawCallbackUnchecked((Runnable)msg.obj);
+                    break;
             }
         }
     }
diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java
index ee0fa86..1f75e70 100644
--- a/core/java/android/view/GLES20Canvas.java
+++ b/core/java/android/view/GLES20Canvas.java
@@ -157,6 +157,8 @@
     static native void nDestroyLayer(int layerId);
     static native void nDestroyLayerDeferred(int layerId);
     static native void nFlushLayer(int layerId);
+    static native void nUpdateRenderLayer(int layerId, int renderer, int displayList,
+            int left, int top, int right, int bottom);
     static native boolean nCopyLayer(int layerId, int bitmap);
 
     ///////////////////////////////////////////////////////////////////////////
@@ -191,6 +193,13 @@
     private static native int nGetMaximumTextureWidth();
     private static native int nGetMaximumTextureHeight();
 
+    /**
+     * Returns the native OpenGLRenderer object.
+     */
+    int getRenderer() {
+        return mRenderer;
+    }
+
     ///////////////////////////////////////////////////////////////////////////
     // Setup
     ///////////////////////////////////////////////////////////////////////////
diff --git a/core/java/android/view/GLES20RenderLayer.java b/core/java/android/view/GLES20RenderLayer.java
index 23a7166..c727a36 100644
--- a/core/java/android/view/GLES20RenderLayer.java
+++ b/core/java/android/view/GLES20RenderLayer.java
@@ -18,6 +18,7 @@
 
 import android.graphics.Canvas;
 import android.graphics.Matrix;
+import android.graphics.Rect;
 
 /**
  * An OpenGL ES 2.0 implementation of {@link HardwareLayer}. This
@@ -95,4 +96,11 @@
     @Override
     void setTransform(Matrix matrix) {
     }
+
+    @Override
+    void redraw(DisplayList displayList, Rect dirtyRect) {
+        GLES20Canvas.nUpdateRenderLayer(mLayer, mCanvas.getRenderer(),
+                ((GLES20DisplayList) displayList).getNativeDisplayList(),
+                dirtyRect.left, dirtyRect.top, dirtyRect.right, dirtyRect.bottom);
+    }
 }
diff --git a/core/java/android/view/GLES20TextureLayer.java b/core/java/android/view/GLES20TextureLayer.java
index 6c41023..cbb908b 100644
--- a/core/java/android/view/GLES20TextureLayer.java
+++ b/core/java/android/view/GLES20TextureLayer.java
@@ -18,6 +18,7 @@
 
 import android.graphics.Canvas;
 import android.graphics.Matrix;
+import android.graphics.Rect;
 import android.graphics.SurfaceTexture;
 
 /**
@@ -81,4 +82,8 @@
     void setTransform(Matrix matrix) {
         GLES20Canvas.nSetTextureLayerTransform(mLayer, matrix.native_instance);
     }
+
+    @Override
+    void redraw(DisplayList displayList, Rect dirtyRect) {
+    }
 }
diff --git a/core/java/android/view/HardwareLayer.java b/core/java/android/view/HardwareLayer.java
index d5666f3..a97167b 100644
--- a/core/java/android/view/HardwareLayer.java
+++ b/core/java/android/view/HardwareLayer.java
@@ -19,6 +19,7 @@
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.Matrix;
+import android.graphics.Rect;
 
 /**
  * A hardware layer can be used to render graphics operations into a hardware
@@ -163,4 +164,13 @@
      * @param matrix The transform to apply to the layer.
      */
     abstract void setTransform(Matrix matrix);
+
+    /**
+     * Specifies the display list to use to refresh the layer.
+     *
+     * @param displayList The display list containing the drawing commands to
+     *                    execute in this layer
+     * @param dirtyRect The dirty region of the layer that needs to be redrawn
+     */
+    abstract void redraw(DisplayList displayList, Rect dirtyRect);
 }
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java
index ec95863..bf91700 100644
--- a/core/java/android/view/HardwareRenderer.java
+++ b/core/java/android/view/HardwareRenderer.java
@@ -1284,15 +1284,10 @@
                 usePbufferSurface(managedContext.getContext());
             }
 
-            switch (level) {
-                case ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN:
-                case ComponentCallbacks2.TRIM_MEMORY_BACKGROUND:
-                case ComponentCallbacks2.TRIM_MEMORY_MODERATE:
-                    GLES20Canvas.flushCaches(GLES20Canvas.FLUSH_CACHES_MODERATE);
-                    break;
-                case ComponentCallbacks2.TRIM_MEMORY_COMPLETE:
-                    GLES20Canvas.flushCaches(GLES20Canvas.FLUSH_CACHES_FULL);
-                    break;
+            if (level >= ComponentCallbacks2.TRIM_MEMORY_COMPLETE) {
+                GLES20Canvas.flushCaches(GLES20Canvas.FLUSH_CACHES_FULL);
+            } else if (level >= ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN) {
+                GLES20Canvas.flushCaches(GLES20Canvas.FLUSH_CACHES_MODERATE);
             }
         }
 
diff --git a/core/java/android/view/IWindow.aidl b/core/java/android/view/IWindow.aidl
index 715fa7b..acb1387 100644
--- a/core/java/android/view/IWindow.aidl
+++ b/core/java/android/view/IWindow.aidl
@@ -49,6 +49,7 @@
             boolean reportDraw, in Configuration newConfig);
     void dispatchAppVisibility(boolean visible);
     void dispatchGetNewSurface();
+    void dispatchScreenStatus(boolean on);
 
     /**
      * Tell the window that it is either gaining or losing focus.  Keep it up
diff --git a/core/java/android/view/LayoutInflater.java b/core/java/android/view/LayoutInflater.java
index 9628d6b..3c0ee12 100644
--- a/core/java/android/view/LayoutInflater.java
+++ b/core/java/android/view/LayoutInflater.java
@@ -34,8 +34,8 @@
 import java.util.HashMap;
 
 /**
- * This class is used to instantiate layout XML file into its corresponding View
- * objects. It is never be used directly -- use
+ * Instantiates a layout XML file into its corresponding {@link android.view.View}
+ * objects. It is never used directly. Instead, use
  * {@link android.app.Activity#getLayoutInflater()} or
  * {@link Context#getSystemService} to retrieve a standard LayoutInflater instance
  * that is already hooked up to the current context and correctly configured
diff --git a/core/java/android/view/TextureView.java b/core/java/android/view/TextureView.java
index 74916f0..fc02cc1 100644
--- a/core/java/android/view/TextureView.java
+++ b/core/java/android/view/TextureView.java
@@ -334,7 +334,7 @@
                     synchronized (mLock) {
                         mUpdateLayer = true;
                     }
-                    postInvalidateDelayed(0);
+                    postInvalidate();
                 }
             };
             mSurface.setOnFrameAvailableListener(mUpdateListener);
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index ec340ec..94531c8 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -4897,8 +4897,6 @@
      * the framework should take special note to preserve when possible.
      *
      * @return true if the view has transient state
-     *
-     * @hide
      */
     @ViewDebug.ExportedProperty(category = "layout")
     public boolean hasTransientState() {
@@ -4910,8 +4908,6 @@
      * framework should attempt to preserve when possible.
      *
      * @param hasTransientState true if this view has transient state
-     *
-     * @hide
      */
     public void setHasTransientState(boolean hasTransientState) {
         if (hasTransientState() == hasTransientState) return;
@@ -5255,6 +5251,7 @@
                 if (mNextFocusForwardId == View.NO_ID) return null;
                 return findViewInsideOutShouldExist(root, mNextFocusForwardId);
             case FOCUS_BACKWARD: {
+                if (mID == View.NO_ID) return null;
                 final int id = mID;
                 return root.findViewByPredicateInsideOut(this, new Predicate<View>() {
                     @Override
@@ -8889,6 +8886,54 @@
     }
 
     /**
+     * <p>Cause an invalidate to happen on the next animation time step, typically the
+     * next display frame.</p>
+     *
+     * <p>This method can be invoked from outside of the UI thread
+     * only when this View is attached to a window.</p>
+     *
+     * @hide
+     */
+    public void postInvalidateOnAnimation() {
+        // We try only with the AttachInfo because there's no point in invalidating
+        // if we are not attached to our window
+        final AttachInfo attachInfo = mAttachInfo;
+        if (attachInfo != null) {
+            attachInfo.mViewRootImpl.dispatchInvalidateOnAnimation(this);
+        }
+    }
+
+    /**
+     * <p>Cause an invalidate of the specified area to happen on the next animation
+     * time step, typically the next display frame.</p>
+     *
+     * <p>This method can be invoked from outside of the UI thread
+     * only when this View is attached to a window.</p>
+     *
+     * @param left The left coordinate of the rectangle to invalidate.
+     * @param top The top coordinate of the rectangle to invalidate.
+     * @param right The right coordinate of the rectangle to invalidate.
+     * @param bottom The bottom coordinate of the rectangle to invalidate.
+     *
+     * @hide
+     */
+    public void postInvalidateOnAnimation(int left, int top, int right, int bottom) {
+        // We try only with the AttachInfo because there's no point in invalidating
+        // if we are not attached to our window
+        final AttachInfo attachInfo = mAttachInfo;
+        if (attachInfo != null) {
+            final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.acquire();
+            info.target = this;
+            info.left = left;
+            info.top = top;
+            info.right = right;
+            info.bottom = bottom;
+
+            attachInfo.mViewRootImpl.dispatchInvalidateRectOnAnimation(info);
+        }
+    }
+
+    /**
      * Post a callback to send a {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} event.
      * This event is sent at most once every
      * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}.
@@ -9674,6 +9719,8 @@
      *
      * @param layoutDirection the direction of the layout
      *
+     * {@link #LAYOUT_DIRECTION_LTR}
+     * {@link #LAYOUT_DIRECTION_RTL}
      */
     public void onPaddingChanged(int layoutDirection) {
     }
@@ -10137,7 +10184,7 @@
      * dynamic.
      */
     boolean hasStaticLayer() {
-        return mLayerType == LAYER_TYPE_NONE;
+        return true;
     }
 
     /**
@@ -10236,42 +10283,8 @@
                 return null;
             }
 
-            HardwareCanvas currentCanvas = mAttachInfo.mHardwareCanvas;
-            final HardwareCanvas canvas = mHardwareLayer.start(currentCanvas);
-
-            // Make sure all the GPU resources have been properly allocated
-            if (canvas == null) {
-                mHardwareLayer.end(currentCanvas);
-                return null;
-            }
-
-            mAttachInfo.mHardwareCanvas = canvas;
-            try {
-                canvas.setViewport(width, height);
-                canvas.onPreDraw(mLocalDirtyRect);
-                mLocalDirtyRect.setEmpty();
-
-                final int restoreCount = canvas.save();
-
-                computeScroll();
-                canvas.translate(-mScrollX, -mScrollY);
-
-                mPrivateFlags |= DRAWN | DRAWING_CACHE_VALID;
-
-                // Fast path for layouts with no backgrounds
-                if ((mPrivateFlags & SKIP_DRAW) == SKIP_DRAW) {
-                    mPrivateFlags &= ~DIRTY_MASK;
-                    dispatchDraw(canvas);
-                } else {
-                    draw(canvas);
-                }
-
-                canvas.restoreToCount(restoreCount);
-            } finally {
-                canvas.onPostDraw();
-                mHardwareLayer.end(currentCanvas);
-                mAttachInfo.mHardwareCanvas = currentCanvas;
-            }
+            mHardwareLayer.redraw(getDisplayList(), mLocalDirtyRect);
+            mLocalDirtyRect.setEmpty();
         }
 
         return mHardwareLayer;
@@ -14872,6 +14885,8 @@
         boolean mHardwareAccelerationRequested;
         HardwareRenderer mHardwareRenderer;
 
+        boolean mScreenOn;
+
         /**
          * Scale factor used by the compatibility mode
          */
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index e0d0763..7fd05c3 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -46,6 +46,7 @@
 import android.os.Looper;
 import android.os.Message;
 import android.os.ParcelFileDescriptor;
+import android.os.PowerManager;
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.SystemClock;
@@ -390,6 +391,9 @@
         mProfileRendering = Boolean.parseBoolean(
                 SystemProperties.get(PROPERTY_PROFILE_RENDERING, "false"));
         mChoreographer = Choreographer.getInstance();
+
+        PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
+        mAttachInfo.mScreenOn = powerManager.isScreenOn();
     }
 
     /**
@@ -757,6 +761,16 @@
         scheduleTraversals();
     }
 
+    void handleScreenStatusChange(boolean on) {
+        if (on != mAttachInfo.mScreenOn) {
+            mAttachInfo.mScreenOn = on;
+            if (on) {
+                mFullRedrawNeeded = true;
+                scheduleTraversals();
+            }
+        }
+    }
+
     /**
      * {@inheritDoc}
      */
@@ -876,7 +890,7 @@
 
         if (mFrameScheduled) {
             mFrameScheduled = false;
-            mChoreographer.removeDrawCallback(mFrameRunnable);
+            mChoreographer.removeDrawCallbacks(mFrameRunnable);
         }
     }
 
@@ -1886,6 +1900,8 @@
     }
 
     private void performDraw() {
+        if (!mAttachInfo.mScreenOn) return;
+
         final long drawStartTime;
         if (ViewDebug.DEBUG_LATENCY) {
             drawStartTime = System.nanoTime();
@@ -2018,8 +2034,7 @@
         }
 
         if (!dirty.isEmpty() || mIsAnimating) {
-            if (mAttachInfo.mHardwareRenderer != null
-                    && mAttachInfo.mHardwareRenderer.isEnabled()) {
+            if (mAttachInfo.mHardwareRenderer != null && mAttachInfo.mHardwareRenderer.isEnabled()) {
                 // Draw with hardware renderer.
                 mIsAnimating = false;
                 mHardwareYOffset = yoff;
@@ -2485,6 +2500,7 @@
     private final static int MSG_FIND_ACCESSIBLITY_NODE_INFO_BY_VIEW_ID = 21;
     private final static int MSG_FIND_ACCESSIBLITY_NODE_INFO_BY_TEXT = 22;
     private final static int MSG_PROCESS_INPUT_EVENTS = 23;
+    private final static int MSG_DISPATCH_SCREEN_STATUS = 24;
 
     final class ViewRootHandler extends Handler {
         @Override
@@ -2741,6 +2757,11 @@
                         .findAccessibilityNodeInfosByTextUiThread(msg);
                 }
             } break;
+            case MSG_DISPATCH_SCREEN_STATUS: {
+                if (mView != null) {
+                    handleScreenStatusChange(msg.arg1 == 1);
+                }
+            } break;
             }
         }
     }
@@ -3992,21 +4013,117 @@
     }
     WindowInputEventReceiver mInputEventReceiver;
 
+    final class InvalidateOnAnimationRunnable implements Runnable {
+        private boolean mPosted;
+        private ArrayList<View> mViews = new ArrayList<View>();
+        private ArrayList<AttachInfo.InvalidateInfo> mViewRects =
+                new ArrayList<AttachInfo.InvalidateInfo>();
+        private View[] mTempViews;
+        private AttachInfo.InvalidateInfo[] mTempViewRects;
+
+        public void addView(View view) {
+            synchronized (this) {
+                mViews.add(view);
+                postIfNeededLocked();
+            }
+        }
+
+        public void addViewRect(AttachInfo.InvalidateInfo info) {
+            synchronized (this) {
+                mViewRects.add(info);
+                postIfNeededLocked();
+            }
+        }
+
+        public void removeView(View view) {
+            synchronized (this) {
+                mViews.remove(view);
+
+                for (int i = mViewRects.size(); i-- > 0; ) {
+                    AttachInfo.InvalidateInfo info = mViewRects.get(i);
+                    if (info.target == view) {
+                        mViewRects.remove(i);
+                        info.release();
+                    }
+                }
+
+                if (mPosted && mViews.isEmpty() && mViewRects.isEmpty()) {
+                    mChoreographer.removeAnimationCallbacks(this);
+                    mPosted = false;
+                }
+            }
+        }
+
+        @Override
+        public void run() {
+            final int viewCount;
+            final int viewRectCount;
+            synchronized (this) {
+                mPosted = false;
+
+                viewCount = mViews.size();
+                if (viewCount != 0) {
+                    mTempViews = mViews.toArray(mTempViews != null
+                            ? mTempViews : new View[viewCount]);
+                    mViews.clear();
+                }
+
+                viewRectCount = mViewRects.size();
+                if (viewRectCount != 0) {
+                    mTempViewRects = mViewRects.toArray(mTempViewRects != null
+                            ? mTempViewRects : new AttachInfo.InvalidateInfo[viewRectCount]);
+                    mViewRects.clear();
+                }
+            }
+
+            for (int i = 0; i < viewCount; i++) {
+                mTempViews[i].invalidate();
+            }
+
+            for (int i = 0; i < viewRectCount; i++) {
+                final View.AttachInfo.InvalidateInfo info = mTempViewRects[i];
+                info.target.invalidate(info.left, info.top, info.right, info.bottom);
+                info.release();
+            }
+        }
+
+        private void postIfNeededLocked() {
+            if (!mPosted) {
+                mChoreographer.postAnimationCallback(this);
+                mPosted = true;
+            }
+        }
+    }
+    final InvalidateOnAnimationRunnable mInvalidateOnAnimationRunnable =
+            new InvalidateOnAnimationRunnable();
+
     public void dispatchInvalidateDelayed(View view, long delayMilliseconds) {
         Message msg = mHandler.obtainMessage(MSG_INVALIDATE, view);
         mHandler.sendMessageDelayed(msg, delayMilliseconds);
     }
 
-    public void cancelInvalidate(View view) {
-        mHandler.removeMessages(MSG_INVALIDATE, view);
-    }
-
     public void dispatchInvalidateRectDelayed(AttachInfo.InvalidateInfo info,
             long delayMilliseconds) {
         final Message msg = mHandler.obtainMessage(MSG_INVALIDATE_RECT, info);
         mHandler.sendMessageDelayed(msg, delayMilliseconds);
     }
 
+    public void dispatchInvalidateOnAnimation(View view) {
+        mInvalidateOnAnimationRunnable.addView(view);
+    }
+
+    public void dispatchInvalidateRectOnAnimation(AttachInfo.InvalidateInfo info) {
+        mInvalidateOnAnimationRunnable.addViewRect(info);
+    }
+
+    public void cancelInvalidate(View view) {
+        mHandler.removeMessages(MSG_INVALIDATE, view);
+        // fixme: might leak the AttachInfo.InvalidateInfo objects instead of returning
+        // them to the pool
+        mHandler.removeMessages(MSG_INVALIDATE_RECT, view);
+        mInvalidateOnAnimationRunnable.removeView(view);
+    }
+
     public void dispatchKey(KeyEvent event) {
         Message msg = mHandler.obtainMessage(MSG_DISPATCH_KEY, event);
         msg.setAsynchronous(true);
@@ -4025,6 +4142,12 @@
         mHandler.sendMessage(msg);
     }
 
+    public void dispatchScreenStatusChange(boolean on) {
+        Message msg = mHandler.obtainMessage(MSG_DISPATCH_SCREEN_STATUS);
+        msg.arg1 = on ? 1 : 0;
+        mHandler.sendMessage(msg);
+    }
+
     public void dispatchGetNewSurface() {
         Message msg = mHandler.obtainMessage(MSG_DISPATCH_GET_NEW_SURFACE);
         mHandler.sendMessage(msg);
@@ -4226,6 +4349,13 @@
             }
         }
 
+        public void dispatchScreenStatus(boolean on) {
+            final ViewRootImpl viewAncestor = mViewAncestor.get();
+            if (viewAncestor != null) {
+                viewAncestor.dispatchScreenStatusChange(on);
+            }
+        }
+        
         public void dispatchGetNewSurface() {
             final ViewRootImpl viewAncestor = mViewAncestor.get();
             if (viewAncestor != null) {
diff --git a/core/java/android/view/WindowManagerImpl.java b/core/java/android/view/WindowManagerImpl.java
index f56dd10..0e4a30f 100644
--- a/core/java/android/view/WindowManagerImpl.java
+++ b/core/java/android/view/WindowManagerImpl.java
@@ -432,29 +432,25 @@
      */
     public void trimMemory(int level) {
         if (HardwareRenderer.isAvailable()) {
-            switch (level) {
-                case ComponentCallbacks2.TRIM_MEMORY_COMPLETE:
-                case ComponentCallbacks2.TRIM_MEMORY_MODERATE:
-                    // On low and medium end gfx devices
-                    if (!ActivityManager.isHighEndGfx(getDefaultDisplay())) {
-                        // Force a full memory flush
-                        HardwareRenderer.trimMemory(ComponentCallbacks2.TRIM_MEMORY_COMPLETE);
-                        // Destroy all hardware surfaces and resources associated to
-                        // known windows
-                        synchronized (this) {
-                            if (mViews == null) return;
-                            int count = mViews.length;
-                            for (int i = 0; i < count; i++) {
-                                mRoots[i].terminateHardwareResources();
-                            }
+            // On low and medium end gfx devices
+            if (!ActivityManager.isHighEndGfx(getDefaultDisplay())) {
+                if (level >= ComponentCallbacks2.TRIM_MEMORY_MODERATE) {
+                    // Destroy all hardware surfaces and resources associated to
+                    // known windows
+                    synchronized (this) {
+                        if (mViews == null) return;
+                        int count = mViews.length;
+                        for (int i = 0; i < count; i++) {
+                            mRoots[i].terminateHardwareResources();
                         }
-                        mNeedsEglTerminate = true;
-                        break;
                     }
-                    // high end gfx devices fall through to next case
-                default:
-                    HardwareRenderer.trimMemory(level);
+                    // Force a full memory flush
+                    HardwareRenderer.trimMemory(ComponentCallbacks2.TRIM_MEMORY_COMPLETE);
+                    mNeedsEglTerminate = true;
+                    return;
+                }
             }
+            HardwareRenderer.trimMemory(level);
         }
     }
 
diff --git a/core/java/android/view/textservice/SpellCheckerSession.java b/core/java/android/view/textservice/SpellCheckerSession.java
index 9105f19..6ff3b9b 100644
--- a/core/java/android/view/textservice/SpellCheckerSession.java
+++ b/core/java/android/view/textservice/SpellCheckerSession.java
@@ -281,9 +281,6 @@
                         if (DBG) {
                             Log.w(TAG, "Get suggestions from the spell checker.");
                         }
-                        if (scp.mTextInfos.length != 1) {
-                            throw new IllegalArgumentException();
-                        }
                         try {
                             session.onGetSentenceSuggestionsMultiple(
                                     scp.mTextInfos, scp.mSuggestionsLimit);
diff --git a/core/java/android/webkit/AccessibilityInjector.java b/core/java/android/webkit/AccessibilityInjector.java
index db66305..11bd815 100644
--- a/core/java/android/webkit/AccessibilityInjector.java
+++ b/core/java/android/webkit/AccessibilityInjector.java
@@ -79,8 +79,8 @@
     private static ArrayList<AccessibilityWebContentKeyBinding> sBindings =
         new ArrayList<AccessibilityWebContentKeyBinding>();
 
-    // handle to the WebView this injector is associated with.
-    private final WebView mWebView;
+    // handle to the WebViewClassic this injector is associated with.
+    private final WebViewClassic mWebView;
 
     // events scheduled for sending as soon as we receive the selected text
     private final Stack<AccessibilityEvent> mScheduledEventStack = new Stack<AccessibilityEvent>();
@@ -98,11 +98,11 @@
     private int mLastDirection;
 
     /**
-     * Creates a new injector associated with a given {@link WebView}.
+     * Creates a new injector associated with a given {@link WebViewClassic}.
      *
-     * @param webView The associated WebView.
+     * @param webView The associated WebViewClassic.
      */
-    public AccessibilityInjector(WebView webView) {
+    public AccessibilityInjector(WebViewClassic webView) {
         mWebView = webView;
         ensureWebContentKeyBindings();
     }
@@ -327,7 +327,7 @@
         AccessibilityEvent event = AccessibilityEvent.obtain(AccessibilityEvent.TYPE_VIEW_SELECTED);
         event.setClassName(mWebView.getClass().getName());
         event.setPackageName(mWebView.getContext().getPackageName());
-        event.setEnabled(mWebView.isEnabled());
+        event.setEnabled(mWebView.getWebView().isEnabled());
         return event;
     }
 
diff --git a/core/java/android/webkit/BrowserFrame.java b/core/java/android/webkit/BrowserFrame.java
index 8ccc59c7..f09e29d 100644
--- a/core/java/android/webkit/BrowserFrame.java
+++ b/core/java/android/webkit/BrowserFrame.java
@@ -70,7 +70,7 @@
     private final static int MAX_OUTSTANDING_REQUESTS = 300;
 
     private final CallbackProxy mCallbackProxy;
-    private final WebSettings mSettings;
+    private final WebSettingsClassic mSettings;
     private final Context mContext;
     private final WebViewDatabase mDatabase;
     private final WebViewCore mWebViewCore;
@@ -200,7 +200,7 @@
      * XXX: Called by WebCore thread.
      */
     public BrowserFrame(Context context, WebViewCore w, CallbackProxy proxy,
-            WebSettings settings, Map<String, Object> javascriptInterfaces) {
+            WebSettingsClassic settings, Map<String, Object> javascriptInterfaces) {
 
         Context appContext = context.getApplicationContext();
 
diff --git a/core/java/android/webkit/CallbackProxy.java b/core/java/android/webkit/CallbackProxy.java
index 3a05bca..2afb841 100644
--- a/core/java/android/webkit/CallbackProxy.java
+++ b/core/java/android/webkit/CallbackProxy.java
@@ -61,8 +61,8 @@
     private volatile WebViewClient mWebViewClient;
     // Instance of WebChromeClient for handling all chrome functions.
     private volatile WebChromeClient mWebChromeClient;
-    // Instance of WebView for handling UI requests.
-    private final WebView mWebView;
+    // Instance of WebViewClassic for handling UI requests.
+    private final WebViewClassic mWebView;
     // Client registered callback listener for download events
     private volatile DownloadListener mDownloadListener;
     // Keep track of multiple progress updates.
@@ -148,13 +148,19 @@
     /**
      * Construct a new CallbackProxy.
      */
-    public CallbackProxy(Context context, WebView w) {
+    public CallbackProxy(Context context, WebViewClassic w) {
         // Used to start a default activity.
         mContext = context;
         mWebView = w;
         mBackForwardList = new WebBackForwardList(this);
     }
 
+    protected void shutdown() {
+        setWebViewClient(null);
+        setWebChromeClient(null);
+        removeCallbacksAndMessages(null);
+    }
+
     /**
      * Set the WebViewClient.
      * @param client An implementation of WebViewClient.
@@ -221,7 +227,7 @@
         }
         boolean override = false;
         if (mWebViewClient != null) {
-            override = mWebViewClient.shouldOverrideUrlLoading(mWebView,
+            override = mWebViewClient.shouldOverrideUrlLoading(mWebView.getWebView(),
                     overrideUrl);
         } else {
             Intent intent = new Intent(Intent.ACTION_VIEW,
@@ -248,7 +254,7 @@
      */
     public boolean uiOverrideKeyEvent(KeyEvent event) {
         if (mWebViewClient != null) {
-            return mWebViewClient.shouldOverrideKeyEvent(mWebView, event);
+            return mWebViewClient.shouldOverrideKeyEvent(mWebView.getWebView(), event);
         }
         return false;
     }
@@ -264,7 +270,8 @@
                 String startedUrl = msg.getData().getString("url");
                 mWebView.onPageStarted(startedUrl);
                 if (mWebViewClient != null) {
-                    mWebViewClient.onPageStarted(mWebView, startedUrl, (Bitmap) msg.obj);
+                    mWebViewClient.onPageStarted(mWebView.getWebView(), startedUrl,
+                            (Bitmap) msg.obj);
                 }
                 break;
 
@@ -272,26 +279,26 @@
                 String finishedUrl = (String) msg.obj;
                 mWebView.onPageFinished(finishedUrl);
                 if (mWebViewClient != null) {
-                    mWebViewClient.onPageFinished(mWebView, finishedUrl);
+                    mWebViewClient.onPageFinished(mWebView.getWebView(), finishedUrl);
                 }
                 break;
 
             case RECEIVED_ICON:
                 if (mWebChromeClient != null) {
-                    mWebChromeClient.onReceivedIcon(mWebView, (Bitmap) msg.obj);
+                    mWebChromeClient.onReceivedIcon(mWebView.getWebView(), (Bitmap) msg.obj);
                 }
                 break;
 
             case RECEIVED_TOUCH_ICON_URL:
                 if (mWebChromeClient != null) {
-                    mWebChromeClient.onReceivedTouchIconUrl(mWebView,
+                    mWebChromeClient.onReceivedTouchIconUrl(mWebView.getWebView(),
                             (String) msg.obj, msg.arg1 == 1);
                 }
                 break;
 
             case RECEIVED_TITLE:
                 if (mWebChromeClient != null) {
-                    mWebChromeClient.onReceivedTitle(mWebView,
+                    mWebChromeClient.onReceivedTitle(mWebView.getWebView(),
                             (String) msg.obj);
                 }
                 break;
@@ -301,7 +308,7 @@
                     int reasonCode = msg.arg1;
                     final String description  = msg.getData().getString("description");
                     final String failUrl  = msg.getData().getString("failingUrl");
-                    mWebViewClient.onReceivedError(mWebView, reasonCode,
+                    mWebViewClient.onReceivedError(mWebView.getWebView(), reasonCode,
                             description, failUrl);
                 }
                 break;
@@ -312,7 +319,7 @@
                 Message dontResend =
                         (Message) msg.getData().getParcelable("dontResend");
                 if (mWebViewClient != null) {
-                    mWebViewClient.onFormResubmission(mWebView, dontResend,
+                    mWebViewClient.onFormResubmission(mWebView.getWebView(), dontResend,
                             resend);
                 } else {
                     dontResend.sendToTarget();
@@ -335,7 +342,7 @@
                     HttpAuthHandler handler = (HttpAuthHandler) msg.obj;
                     String host = msg.getData().getString("host");
                     String realm = msg.getData().getString("realm");
-                    mWebViewClient.onReceivedHttpAuthRequest(mWebView, handler,
+                    mWebViewClient.onReceivedHttpAuthRequest(mWebView.getWebView(), handler,
                             host, realm);
                 }
                 break;
@@ -344,7 +351,7 @@
                 if (mWebViewClient != null) {
                     HashMap<String, Object> map =
                         (HashMap<String, Object>) msg.obj;
-                    mWebViewClient.onReceivedSslError(mWebView,
+                    mWebViewClient.onReceivedSslError(mWebView.getWebView(),
                             (SslErrorHandler) map.get("handler"),
                             (SslError) map.get("error"));
                 }
@@ -352,7 +359,7 @@
 
             case PROCEEDED_AFTER_SSL_ERROR:
                 if (mWebViewClient != null) {
-                    mWebViewClient.onProceededAfterSslError(mWebView,
+                    mWebViewClient.onProceededAfterSslError(mWebView.getWebView(),
                             (SslError) msg.obj);
                 }
                 break;
@@ -361,7 +368,7 @@
                 if (mWebViewClient != null) {
                     HashMap<String, Object> map =
                         (HashMap<String, Object>) msg.obj;
-                    mWebViewClient.onReceivedClientCertRequest(mWebView,
+                    mWebViewClient.onReceivedClientCertRequest(mWebView.getWebView(),
                             (ClientCertRequestHandler) map.get("handler"),
                             (String) map.get("host_and_port"));
                 }
@@ -373,7 +380,7 @@
                 // changed.
                 synchronized (this) {
                     if (mWebChromeClient != null) {
-                        mWebChromeClient.onProgressChanged(mWebView,
+                        mWebChromeClient.onProgressChanged(mWebView.getWebView(),
                                 mLatestProgress);
                     }
                     mProgressUpdatePending = false;
@@ -382,14 +389,14 @@
 
             case UPDATE_VISITED:
                 if (mWebViewClient != null) {
-                    mWebViewClient.doUpdateVisitedHistory(mWebView,
+                    mWebViewClient.doUpdateVisitedHistory(mWebView.getWebView(),
                             (String) msg.obj, msg.arg1 != 0);
                 }
                 break;
 
             case LOAD_RESOURCE:
                 if (mWebViewClient != null) {
-                    mWebViewClient.onLoadResource(mWebView, (String) msg.obj);
+                    mWebViewClient.onLoadResource(mWebView.getWebView(), (String) msg.obj);
                 }
                 break;
 
@@ -409,7 +416,7 @@
 
             case CREATE_WINDOW:
                 if (mWebChromeClient != null) {
-                    if (!mWebChromeClient.onCreateWindow(mWebView,
+                    if (!mWebChromeClient.onCreateWindow(mWebView.getWebView(),
                                 msg.arg1 == 1, msg.arg2 == 1,
                                 (Message) msg.obj)) {
                         synchronized (this) {
@@ -422,13 +429,13 @@
 
             case REQUEST_FOCUS:
                 if (mWebChromeClient != null) {
-                    mWebChromeClient.onRequestFocus(mWebView);
+                    mWebChromeClient.onRequestFocus(mWebView.getWebView());
                 }
                 break;
 
             case CLOSE_WINDOW:
                 if (mWebChromeClient != null) {
-                    mWebChromeClient.onCloseWindow((WebView) msg.obj);
+                    mWebChromeClient.onCloseWindow(((WebViewClassic) msg.obj).getWebView());
                 }
                 break;
 
@@ -449,7 +456,7 @@
 
             case ASYNC_KEYEVENTS:
                 if (mWebViewClient != null) {
-                    mWebViewClient.onUnhandledKeyEvent(mWebView,
+                    mWebViewClient.onUnhandledKeyEvent(mWebView.getWebView(),
                             (KeyEvent) msg.obj);
                 }
                 break;
@@ -516,7 +523,7 @@
                     final JsResult res = (JsResult) msg.obj;
                     String message = msg.getData().getString("message");
                     String url = msg.getData().getString("url");
-                    if (!mWebChromeClient.onJsAlert(mWebView, url, message,
+                    if (!mWebChromeClient.onJsAlert(mWebView.getWebView(), url, message,
                             res)) {
                         if (!canShowAlertDialog()) {
                             res.cancel();
@@ -552,7 +559,7 @@
                     final JsResult res = (JsResult) msg.obj;
                     String message = msg.getData().getString("message");
                     String url = msg.getData().getString("url");
-                    if (!mWebChromeClient.onJsConfirm(mWebView, url, message,
+                    if (!mWebChromeClient.onJsConfirm(mWebView.getWebView(), url, message,
                             res)) {
                         if (!canShowAlertDialog()) {
                             res.cancel();
@@ -597,7 +604,7 @@
                     String message = msg.getData().getString("message");
                     String defaultVal = msg.getData().getString("default");
                     String url = msg.getData().getString("url");
-                    if (!mWebChromeClient.onJsPrompt(mWebView, url, message,
+                    if (!mWebChromeClient.onJsPrompt(mWebView.getWebView(), url, message,
                                 defaultVal, res)) {
                         if (!canShowAlertDialog()) {
                             res.cancel();
@@ -653,7 +660,7 @@
                     final JsResult res = (JsResult) msg.obj;
                     String message = msg.getData().getString("message");
                     String url = msg.getData().getString("url");
-                    if (!mWebChromeClient.onJsBeforeUnload(mWebView, url,
+                    if (!mWebChromeClient.onJsBeforeUnload(mWebView.getWebView(), url,
                             message, res)) {
                         if (!canShowAlertDialog()) {
                             res.cancel();
@@ -710,7 +717,7 @@
 
             case SCALE_CHANGED:
                 if (mWebViewClient != null) {
-                    mWebViewClient.onScaleChanged(mWebView, msg.getData()
+                    mWebViewClient.onScaleChanged(mWebView.getWebView(), msg.getData()
                             .getFloat("old"), msg.getData().getFloat("new"));
                 }
                 break;
@@ -817,7 +824,7 @@
                     String realm = msg.getData().getString("realm");
                     String account = msg.getData().getString("account");
                     String args = msg.getData().getString("args");
-                    mWebViewClient.onReceivedLoginRequest(mWebView, realm,
+                    mWebViewClient.onReceivedLoginRequest(mWebView.getWebView(), realm,
                             account, args);
                 }
                 break;
@@ -1074,7 +1081,7 @@
         }
         // Note: This method does _not_ send a message.
         WebResourceResponse r =
-                mWebViewClient.shouldInterceptRequest(mWebView, url);
+                mWebViewClient.shouldInterceptRequest(mWebView.getWebView(), url);
         if (r == null) {
             sendMessage(obtainMessage(LOAD_RESOURCE, url));
         }
@@ -1219,7 +1226,8 @@
             return null;
         }
 
-        WebView.WebViewTransport transport = mWebView.new WebViewTransport();
+        WebView.WebViewTransport transport =
+            mWebView.getWebView().new WebViewTransport();
         final Message msg = obtainMessage(NOTIFY);
         msg.obj = transport;
         synchronized (this) {
@@ -1234,7 +1242,7 @@
             }
         }
 
-        WebView w = transport.getWebView();
+        WebViewClassic w = WebViewClassic.fromWebView(transport.getWebView());
         if (w != null) {
             WebViewCore core = w.getWebViewCore();
             // If WebView.destroy() has been called, core may be null.  Skip
@@ -1257,7 +1265,7 @@
         sendEmptyMessage(REQUEST_FOCUS);
     }
 
-    public void onCloseWindow(WebView window) {
+    public void onCloseWindow(WebViewClassic window) {
         // Do an unsynchronized quick check to avoid posting if no callback has
         // been set.
         if (mWebChromeClient == null) {
diff --git a/core/java/android/webkit/FindActionModeCallback.java b/core/java/android/webkit/FindActionModeCallback.java
index 10b0885..964cf3e 100644
--- a/core/java/android/webkit/FindActionModeCallback.java
+++ b/core/java/android/webkit/FindActionModeCallback.java
@@ -38,7 +38,7 @@
     private View mCustomView;
     private EditText mEditText;
     private TextView mMatches;
-    private WebView mWebView;
+    private WebViewClassic mWebView;
     private InputMethodManager mInput;
     private Resources mResources;
     private boolean mMatchesFound;
@@ -90,7 +90,7 @@
      * Set the WebView to search.  Must be non null, and set before calling
      * startActionMode.
      */
-    void setWebView(WebView webView) {
+    void setWebView(WebViewClassic webView) {
         if (null == webView) {
             throw new AssertionError("WebView supplied to "
                     + "FindActionModeCallback cannot be null");
@@ -218,7 +218,7 @@
     public void onDestroyActionMode(ActionMode mode) {
         mActionMode = null;
         mWebView.notifyFindDialogDismissed();
-        mInput.hideSoftInputFromWindow(mWebView.getWindowToken(), 0);
+        mInput.hideSoftInputFromWindow(mWebView.getWebView().getWindowToken(), 0);
     }
 
     @Override
@@ -232,7 +232,7 @@
             throw new AssertionError(
                     "No WebView for FindActionModeCallback::onActionItemClicked");
         }
-        mInput.hideSoftInputFromWindow(mWebView.getWindowToken(), 0);
+        mInput.hideSoftInputFromWindow(mWebView.getWebView().getWindowToken(), 0);
         switch(item.getItemId()) {
             case com.android.internal.R.id.find_prev:
                 findNext(false);
diff --git a/core/java/android/webkit/GeolocationService.java b/core/java/android/webkit/GeolocationService.java
index 91de1d8..225053b 100755
--- a/core/java/android/webkit/GeolocationService.java
+++ b/core/java/android/webkit/GeolocationService.java
@@ -24,7 +24,6 @@
 import android.location.LocationProvider;
 import android.os.Bundle;
 import android.util.Log;
-import android.webkit.WebView;
 import android.webkit.WebViewCore;
 
 
diff --git a/core/java/android/webkit/HTML5Audio.java b/core/java/android/webkit/HTML5Audio.java
index aedecf0..8e1f573 100644
--- a/core/java/android/webkit/HTML5Audio.java
+++ b/core/java/android/webkit/HTML5Audio.java
@@ -92,7 +92,7 @@
     private class IsPrivateBrowsingEnabledGetter {
         private boolean mIsReady;
         private boolean mIsPrivateBrowsingEnabled;
-        IsPrivateBrowsingEnabledGetter(Looper uiThreadLooper, final WebView webView) {
+        IsPrivateBrowsingEnabledGetter(Looper uiThreadLooper, final WebViewClassic webView) {
             new Handler(uiThreadLooper).post(new Runnable() {
                 @Override
                 public void run() {
diff --git a/core/java/android/webkit/HTML5VideoFullScreen.java b/core/java/android/webkit/HTML5VideoFullScreen.java
index bc0557e..fac549d 100644
--- a/core/java/android/webkit/HTML5VideoFullScreen.java
+++ b/core/java/android/webkit/HTML5VideoFullScreen.java
@@ -236,7 +236,7 @@
 
     @Override
     public void enterFullScreenVideoState(int layerId,
-            HTML5VideoViewProxy proxy, WebView webView) {
+            HTML5VideoViewProxy proxy, WebViewClassic webView) {
         mFullScreenMode = FULLSCREEN_SURFACECREATING;
         mCurrentBufferPercentage = 0;
         mPlayer.setOnBufferingUpdateListener(mBufferingUpdateListener);
diff --git a/core/java/android/webkit/HTML5VideoView.java b/core/java/android/webkit/HTML5VideoView.java
index 73166cb..0d3b755 100644
--- a/core/java/android/webkit/HTML5VideoView.java
+++ b/core/java/android/webkit/HTML5VideoView.java
@@ -280,7 +280,7 @@
     // screen mode. Some are specific to one type, but currently are called
     // directly from the proxy.
     public void enterFullScreenVideoState(int layerId,
-            HTML5VideoViewProxy proxy, WebView webView) {
+            HTML5VideoViewProxy proxy, WebViewClassic webView) {
     }
 
     public boolean isFullScreenMode() {
diff --git a/core/java/android/webkit/HTML5VideoViewProxy.java b/core/java/android/webkit/HTML5VideoViewProxy.java
index d306c86..1644b06 100644
--- a/core/java/android/webkit/HTML5VideoViewProxy.java
+++ b/core/java/android/webkit/HTML5VideoViewProxy.java
@@ -75,8 +75,8 @@
     int mNativePointer;
     // The handler for WebCore thread messages;
     private Handler mWebCoreHandler;
-    // The WebView instance that created this view.
-    private WebView mWebView;
+    // The WebViewClassic instance that created this view.
+    private WebViewClassic mWebView;
     // The poster image to be shown when the video is not playing.
     // This ref prevents the bitmap from being GC'ed.
     private Bitmap mPoster;
@@ -142,7 +142,7 @@
         }
 
         public static void enterFullScreenVideo(int layerId, String url,
-                HTML5VideoViewProxy proxy, WebView webView) {
+                HTML5VideoViewProxy proxy, WebViewClassic webView) {
                 // Save the inline video info and inherit it in the full screen
                 int savePosition = 0;
                 if (mHTML5VideoView != null) {
@@ -163,7 +163,7 @@
         }
 
         public static void exitFullScreenVideo(HTML5VideoViewProxy proxy,
-                WebView webView) {
+                WebViewClassic webView) {
             if (!mHTML5VideoView.fullScreenExited() && mHTML5VideoView.isFullScreenMode()) {
                 WebChromeClient client = webView.getWebChromeClient();
                 if (client != null) {
@@ -551,7 +551,7 @@
      * @param webView is the WebView that hosts the video.
      * @param nativePtr is the C++ pointer to the MediaPlayerPrivate object.
      */
-    private HTML5VideoViewProxy(WebView webView, int nativePtr) {
+    private HTML5VideoViewProxy(WebViewClassic webView, int nativePtr) {
         // This handler is for the main (UI) thread.
         super(Looper.getMainLooper());
         // Save the WebView object.
@@ -721,7 +721,7 @@
         return new HTML5VideoViewProxy(webViewCore.getWebView(), nativePtr);
     }
 
-    /* package */ WebView getWebView() {
+    /* package */ WebViewClassic getWebView() {
         return mWebView;
     }
 
diff --git a/core/java/android/webkit/JWebCoreJavaBridge.java b/core/java/android/webkit/JWebCoreJavaBridge.java
index b498435..e6eaa14 100644
--- a/core/java/android/webkit/JWebCoreJavaBridge.java
+++ b/core/java/android/webkit/JWebCoreJavaBridge.java
@@ -43,10 +43,10 @@
     private boolean mTimerPaused;
     private boolean mHasDeferredTimers;
 
-    // keep track of the main WebView attached to the current window so that we
+    // keep track of the main WebViewClassic attached to the current window so that we
     // can get the proper Context.
-    private static WeakReference<WebView> sCurrentMainWebView =
-            new WeakReference<WebView>(null);
+    private static WeakReference<WebViewClassic> sCurrentMainWebView =
+            new WeakReference<WebViewClassic>(null);
 
     /* package */
     static final int REFRESH_PLUGINS = 100;
@@ -67,15 +67,15 @@
         nativeFinalize();
     }
 
-    static synchronized void setActiveWebView(WebView webview) {
+    static synchronized void setActiveWebView(WebViewClassic webview) {
         if (sCurrentMainWebView.get() != null) {
             // it is possible if there is a sub-WebView. Do nothing.
             return;
         }
-        sCurrentMainWebView = new WeakReference<WebView>(webview);
+        sCurrentMainWebView = new WeakReference<WebViewClassic>(webview);
     }
 
-    static synchronized void removeActiveWebView(WebView webview) {
+    static synchronized void removeActiveWebView(WebViewClassic webview) {
         if (sCurrentMainWebView.get() != webview) {
             // it is possible if there is a sub-WebView. Do nothing.
             return;
@@ -259,7 +259,7 @@
 
     synchronized private String getSignedPublicKey(int index, String challenge,
             String url) {
-        WebView current = sCurrentMainWebView.get();
+        WebViewClassic current = sCurrentMainWebView.get();
         if (current != null) {
             // generateKeyPair expects organizations which we don't have. Ignore
             // url.
diff --git a/core/java/android/webkit/OverScrollGlow.java b/core/java/android/webkit/OverScrollGlow.java
index e906f7f..d91f860 100644
--- a/core/java/android/webkit/OverScrollGlow.java
+++ b/core/java/android/webkit/OverScrollGlow.java
@@ -29,7 +29,7 @@
  * @hide
  */
 public class OverScrollGlow {
-    private WebView mHostView;
+    private WebViewClassic mHostView;
 
     private EdgeEffect mEdgeGlowTop;
     private EdgeEffect mEdgeGlowBottom;
@@ -39,7 +39,7 @@
     private int mOverScrollDeltaX;
     private int mOverScrollDeltaY;
 
-    public OverScrollGlow(WebView host) {
+    public OverScrollGlow(WebViewClassic host) {
         mHostView = host;
         Context context = host.getContext();
         mEdgeGlowTop = new EdgeEffect(context);
@@ -80,7 +80,7 @@
                 mOverScrollDeltaX = 0;
             }
 
-            if (maxY > 0 || mHostView.getOverScrollMode() == View.OVER_SCROLL_ALWAYS) {
+            if (maxY > 0 || mHostView.getWebView().getOverScrollMode() == View.OVER_SCROLL_ALWAYS) {
                 final int pulledToY = oldY + mOverScrollDeltaY;
                 if (pulledToY < 0) {
                     mEdgeGlowTop.onPull((float) mOverScrollDeltaY / mHostView.getHeight());
@@ -120,7 +120,7 @@
      * @param rangeY Maximum range for vertical scrolling
      */
     public void absorbGlow(int x, int y, int oldX, int oldY, int rangeX, int rangeY) {
-        if (rangeY > 0 || mHostView.getOverScrollMode() == View.OVER_SCROLL_ALWAYS) {
+        if (rangeY > 0 || mHostView.getWebView().getOverScrollMode() == View.OVER_SCROLL_ALWAYS) {
             if (y < 0 && oldY >= 0) {
                 mEdgeGlowTop.onAbsorb((int) mHostView.mScroller.getCurrVelocity());
                 if (!mEdgeGlowBottom.isFinished()) {
diff --git a/core/java/android/webkit/PluginFullScreenHolder.java b/core/java/android/webkit/PluginFullScreenHolder.java
index 42ba7c9..665cd9d 100644
--- a/core/java/android/webkit/PluginFullScreenHolder.java
+++ b/core/java/android/webkit/PluginFullScreenHolder.java
@@ -35,7 +35,7 @@
 
 class PluginFullScreenHolder {
 
-    private final WebView mWebView;
+    private final WebViewClassic mWebView;
     private final int mNpp;
     private final int mOrientation;
 
@@ -44,7 +44,7 @@
 
     private View mContentView;
 
-    PluginFullScreenHolder(WebView webView, int orientation, int npp) {
+    PluginFullScreenHolder(WebViewClassic webView, int orientation, int npp) {
         mWebView = webView;
         mNpp = npp;
         mOrientation = orientation;
@@ -134,7 +134,7 @@
         new WebChromeClient.CustomViewCallback() {
             public void onCustomViewHidden() {
 
-                mWebView.mPrivateHandler.obtainMessage(WebView.HIDE_FULLSCREEN)
+                mWebView.mPrivateHandler.obtainMessage(WebViewClassic.HIDE_FULLSCREEN)
                     .sendToTarget();
 
                 mWebView.getWebViewCore().sendMessage(
diff --git a/core/java/android/webkit/PluginManager.java b/core/java/android/webkit/PluginManager.java
index ab3b6d5..fe40156 100644
--- a/core/java/android/webkit/PluginManager.java
+++ b/core/java/android/webkit/PluginManager.java
@@ -34,7 +34,7 @@
 import android.util.Log;
 
 /**
- * Class for managing the relationship between the {@link WebView} and installed
+ * Class for managing the relationship between the {@link WebViewClassic} and installed
  * plugins in the system. You can find this class through
  * {@link PluginManager#getInstance}.
  * 
diff --git a/core/java/android/webkit/SelectActionModeCallback.java b/core/java/android/webkit/SelectActionModeCallback.java
index 2a770f5..57628d3 100644
--- a/core/java/android/webkit/SelectActionModeCallback.java
+++ b/core/java/android/webkit/SelectActionModeCallback.java
@@ -26,11 +26,11 @@
 import android.view.MenuItem;
 
 class SelectActionModeCallback implements ActionMode.Callback {
-    private WebView mWebView;
+    private WebViewClassic mWebView;
     private ActionMode mActionMode;
     private boolean mIsTextSelected = true;
 
-    void setWebView(WebView webView) {
+    void setWebView(WebViewClassic webView) {
         mWebView = webView;
     }
 
diff --git a/core/java/android/webkit/ViewManager.java b/core/java/android/webkit/ViewManager.java
index 153c1c2..34065a1 100644
--- a/core/java/android/webkit/ViewManager.java
+++ b/core/java/android/webkit/ViewManager.java
@@ -16,6 +16,7 @@
 
 package android.webkit;
 
+import android.util.DisplayMetrics;
 import android.view.SurfaceView;
 import android.view.View;
 import android.view.ViewGroup;
@@ -24,7 +25,7 @@
 import java.util.ArrayList;
 
 class ViewManager {
-    private final WebView mWebView;
+    private final WebViewClassic mWebView;
     private final ArrayList<ChildView> mChildren = new ArrayList<ChildView>();
     private boolean mHidden;
     private boolean mReadyToDraw;
@@ -74,7 +75,7 @@
         }
 
         private void attachViewOnUIThread() {
-            mWebView.addView(mView);
+            mWebView.getWebView().addView(mView);
             mChildren.add(this);
             if (!mReadyToDraw) {
                 mView.setVisibility(View.GONE);
@@ -93,16 +94,15 @@
         }
 
         private void removeViewOnUIThread() {
-            mWebView.removeView(mView);
+            mWebView.getWebView().removeView(mView);
             mChildren.remove(this);
         }
     }
 
-    ViewManager(WebView w) {
+    ViewManager(WebViewClassic w) {
         mWebView = w;
-
-        int pixelArea = w.getResources().getDisplayMetrics().widthPixels *
-                        w.getResources().getDisplayMetrics().heightPixels;
+        DisplayMetrics metrics = w.getWebView().getResources().getDisplayMetrics();
+        int pixelArea = metrics.widthPixels * metrics.heightPixels;
         /* set the threshold to be 275% larger than the screen size. The
            percentage is simply an estimation and is not based on anything but
            basic trial-and-error tests run on multiple devices.
diff --git a/core/java/android/webkit/ViewStateSerializer.java b/core/java/android/webkit/ViewStateSerializer.java
index 5f91ed3..e672b62 100644
--- a/core/java/android/webkit/ViewStateSerializer.java
+++ b/core/java/android/webkit/ViewStateSerializer.java
@@ -34,7 +34,7 @@
 
     static final int VERSION = 1;
 
-    static boolean serializeViewState(OutputStream stream, WebView web)
+    static boolean serializeViewState(OutputStream stream, WebViewClassic web)
             throws IOException {
         int baseLayer = web.getBaseLayer();
         if (baseLayer == 0) {
@@ -48,16 +48,16 @@
                 new byte[WORKING_STREAM_STORAGE]);
     }
 
-    static DrawData deserializeViewState(InputStream stream, WebView web)
+    static DrawData deserializeViewState(InputStream stream, WebViewClassic web)
             throws IOException {
         DataInputStream dis = new DataInputStream(stream);
         int version = dis.readInt();
-        if (version != VERSION) {
+        if (version > VERSION) {
             throw new IOException("Unexpected version: " + version);
         }
         int contentWidth = dis.readInt();
         int contentHeight = dis.readInt();
-        int baseLayer = nativeDeserializeViewState(dis,
+        int baseLayer = nativeDeserializeViewState(version, dis,
                 new byte[WORKING_STREAM_STORAGE]);
 
         final WebViewCore.DrawData draw = new WebViewCore.DrawData();
@@ -76,7 +76,7 @@
             OutputStream stream, byte[] storage);
 
     // Returns a pointer to the BaseLayer
-    private static native int nativeDeserializeViewState(
+    private static native int nativeDeserializeViewState(int version,
             InputStream stream, byte[] storage);
 
     private ViewStateSerializer() {}
diff --git a/core/java/android/webkit/WebSettings.java b/core/java/android/webkit/WebSettings.java
index c463b40..cddd7ab 100644
--- a/core/java/android/webkit/WebSettings.java
+++ b/core/java/android/webkit/WebSettings.java
@@ -16,16 +16,7 @@
 
 package android.webkit;
 
-import android.content.Context;
-import android.content.SharedPreferences;
-import android.content.pm.PackageManager;
-import android.os.Build;
-import android.os.Handler;
 import android.os.Message;
-import android.util.DisplayMetrics;
-import android.util.EventLog;
-
-import java.util.Locale;
 
 /**
  * Manages settings state for a WebView. When a WebView is first created, it
@@ -35,7 +26,18 @@
  * been destroyed, any method call on WebSettings will throw an
  * IllegalStateException.
  */
+// This is (effectively) an abstract base class; concrete WebViewProviders must
+// create a class derived from this, and return an instance of it in the
+// WebViewProvider.getWebSettingsProvider() method implementation.
 public class WebSettings {
+    // TODO: Remove MustOverrideException and make all methods throwing it abstract instead;
+    // needs API file update.
+    private static class MustOverrideException extends RuntimeException {
+        MustOverrideException() {
+            super("abstract function called: must be overriden!");
+        }
+    }
+
     /**
      * Enum for controlling the layout of html.
      * NORMAL means no rendering changes.
@@ -141,379 +143,12 @@
         OFF
     }
 
-    // TODO: Keep this up to date
-    private static final String PREVIOUS_VERSION = "4.0.3";
-
-    // WebView associated with this WebSettings.
-    private WebView mWebView;
-    // BrowserFrame used to access the native frame pointer.
-    private BrowserFrame mBrowserFrame;
-    // Flag to prevent multiple SYNC messages at one time.
-    private boolean mSyncPending = false;
-    // Custom handler that queues messages until the WebCore thread is active.
-    private final EventHandler mEventHandler;
-
-    // Private settings so we don't have to go into native code to
-    // retrieve the values. After setXXX, postSync() needs to be called.
-    //
-    // The default values need to match those in WebSettings.cpp
-    // If the defaults change, please also update the JavaDocs so developers
-    // know what they are.
-    private LayoutAlgorithm mLayoutAlgorithm = LayoutAlgorithm.NARROW_COLUMNS;
-    private Context         mContext;
-    private int             mTextSize = 100;
-    private String          mStandardFontFamily = "sans-serif";
-    private String          mFixedFontFamily = "monospace";
-    private String          mSansSerifFontFamily = "sans-serif";
-    private String          mSerifFontFamily = "serif";
-    private String          mCursiveFontFamily = "cursive";
-    private String          mFantasyFontFamily = "fantasy";
-    private String          mDefaultTextEncoding;
-    private String          mUserAgent;
-    private boolean         mUseDefaultUserAgent;
-    private String          mAcceptLanguage;
-    private int             mMinimumFontSize = 8;
-    private int             mMinimumLogicalFontSize = 8;
-    private int             mDefaultFontSize = 16;
-    private int             mDefaultFixedFontSize = 13;
-    private int             mPageCacheCapacity = 0;
-    private boolean         mLoadsImagesAutomatically = true;
-    private boolean         mBlockNetworkImage = false;
-    private boolean         mBlockNetworkLoads;
-    private boolean         mJavaScriptEnabled = false;
-    private boolean         mHardwareAccelSkia = false;
-    private boolean         mShowVisualIndicator = false;
-    private PluginState     mPluginState = PluginState.OFF;
-    private boolean         mJavaScriptCanOpenWindowsAutomatically = false;
-    private boolean         mUseDoubleTree = false;
-    private boolean         mUseWideViewport = false;
-    private boolean         mSupportMultipleWindows = false;
-    private boolean         mShrinksStandaloneImagesToFit = false;
-    private long            mMaximumDecodedImageSize = 0; // 0 means default
-    private boolean         mPrivateBrowsingEnabled = false;
-    private boolean         mSyntheticLinksEnabled = true;
-    // HTML5 API flags
-    private boolean         mAppCacheEnabled = false;
-    private boolean         mDatabaseEnabled = false;
-    private boolean         mDomStorageEnabled = false;
-    private boolean         mWorkersEnabled = false;  // only affects V8.
-    private boolean         mGeolocationEnabled = true;
-    private boolean         mXSSAuditorEnabled = false;
-    // HTML5 configuration parameters
-    private long            mAppCacheMaxSize = Long.MAX_VALUE;
-    private String          mAppCachePath = null;
-    private String          mDatabasePath = "";
-    // The WebCore DatabaseTracker only allows the database path to be set
-    // once. Keep track of when the path has been set.
-    private boolean         mDatabasePathHasBeenSet = false;
-    private String          mGeolocationDatabasePath = "";
-    // Don't need to synchronize the get/set methods as they
-    // are basic types, also none of these values are used in
-    // native WebCore code.
-    private ZoomDensity     mDefaultZoom = ZoomDensity.MEDIUM;
-    private RenderPriority  mRenderPriority = RenderPriority.NORMAL;
-    private int             mOverrideCacheMode = LOAD_DEFAULT;
-    private int             mDoubleTapZoom = 100;
-    private boolean         mSaveFormData = true;
-    private boolean         mAutoFillEnabled = false;
-    private boolean         mSavePassword = true;
-    private boolean         mLightTouchEnabled = false;
-    private boolean         mNeedInitialFocus = true;
-    private boolean         mNavDump = false;
-    private boolean         mSupportZoom = true;
-    private boolean         mBuiltInZoomControls = false;
-    private boolean         mDisplayZoomControls = true;
-    private boolean         mAllowFileAccess = true;
-    private boolean         mAllowContentAccess = true;
-    private boolean         mLoadWithOverviewMode = false;
-    private boolean         mEnableSmoothTransition = false;
-    private boolean         mForceUserScalable = false;
-
-    // AutoFill Profile data
     /**
-     * @hide for now, pending API council approval.
+     * Hidden constructor to prevent clients from creating a new settings
+     * instance or deriving the class.
+     * @hide
      */
-    public static class AutoFillProfile {
-        private int mUniqueId;
-        private String mFullName;
-        private String mEmailAddress;
-        private String mCompanyName;
-        private String mAddressLine1;
-        private String mAddressLine2;
-        private String mCity;
-        private String mState;
-        private String mZipCode;
-        private String mCountry;
-        private String mPhoneNumber;
-
-        public AutoFillProfile(int uniqueId, String fullName, String email,
-                String companyName, String addressLine1, String addressLine2,
-                String city, String state, String zipCode, String country,
-                String phoneNumber) {
-            mUniqueId = uniqueId;
-            mFullName = fullName;
-            mEmailAddress = email;
-            mCompanyName = companyName;
-            mAddressLine1 = addressLine1;
-            mAddressLine2 = addressLine2;
-            mCity = city;
-            mState = state;
-            mZipCode = zipCode;
-            mCountry = country;
-            mPhoneNumber = phoneNumber;
-        }
-
-        public int getUniqueId() { return mUniqueId; }
-        public String getFullName() { return mFullName; }
-        public String getEmailAddress() { return mEmailAddress; }
-        public String getCompanyName() { return mCompanyName; }
-        public String getAddressLine1() { return mAddressLine1; }
-        public String getAddressLine2() { return mAddressLine2; }
-        public String getCity() { return mCity; }
-        public String getState() { return mState; }
-        public String getZipCode() { return mZipCode; }
-        public String getCountry() { return mCountry; }
-        public String getPhoneNumber() { return mPhoneNumber; }
-    }
-
-
-    private AutoFillProfile mAutoFillProfile;
-
-    private boolean         mUseWebViewBackgroundForOverscroll = true;
-
-    // private WebSettings, not accessible by the host activity
-    static private int      mDoubleTapToastCount = 3;
-
-    private static final String PREF_FILE = "WebViewSettings";
-    private static final String DOUBLE_TAP_TOAST_COUNT = "double_tap_toast_count";
-
-    // Class to handle messages before WebCore is ready.
-    private class EventHandler {
-        // Message id for syncing
-        static final int SYNC = 0;
-        // Message id for setting priority
-        static final int PRIORITY = 1;
-        // Message id for writing double-tap toast count
-        static final int SET_DOUBLE_TAP_TOAST_COUNT = 2;
-        // Actual WebCore thread handler
-        private Handler mHandler;
-
-        private synchronized void createHandler() {
-            // as mRenderPriority can be set before thread is running, sync up
-            setRenderPriority();
-
-            // create a new handler
-            mHandler = new Handler() {
-                @Override
-                public void handleMessage(Message msg) {
-                    switch (msg.what) {
-                        case SYNC:
-                            synchronized (WebSettings.this) {
-                                if (mBrowserFrame.mNativeFrame != 0) {
-                                    nativeSync(mBrowserFrame.mNativeFrame);
-                                }
-                                mSyncPending = false;
-                            }
-                            break;
-
-                        case PRIORITY: {
-                            setRenderPriority();
-                            break;
-                        }
-
-                        case SET_DOUBLE_TAP_TOAST_COUNT: {
-                            SharedPreferences.Editor editor = mContext
-                                    .getSharedPreferences(PREF_FILE,
-                                            Context.MODE_PRIVATE).edit();
-                            editor.putInt(DOUBLE_TAP_TOAST_COUNT,
-                                    mDoubleTapToastCount);
-                            editor.commit();
-                            break;
-                        }
-                    }
-                }
-            };
-        }
-
-        private void setRenderPriority() {
-            synchronized (WebSettings.this) {
-                if (mRenderPriority == RenderPriority.NORMAL) {
-                    android.os.Process.setThreadPriority(
-                            android.os.Process.THREAD_PRIORITY_DEFAULT);
-                } else if (mRenderPriority == RenderPriority.HIGH) {
-                    android.os.Process.setThreadPriority(
-                            android.os.Process.THREAD_PRIORITY_FOREGROUND +
-                            android.os.Process.THREAD_PRIORITY_LESS_FAVORABLE);
-                } else if (mRenderPriority == RenderPriority.LOW) {
-                    android.os.Process.setThreadPriority(
-                            android.os.Process.THREAD_PRIORITY_BACKGROUND);
-                }
-            }
-        }
-
-        /**
-         * Send a message to the private queue or handler.
-         */
-        private synchronized boolean sendMessage(Message msg) {
-            if (mHandler != null) {
-                mHandler.sendMessage(msg);
-                return true;
-            } else {
-                return false;
-            }
-        }
-    }
-
-    // User agent strings.
-    private static final String DESKTOP_USERAGENT = "Mozilla/5.0 (X11; " +
-        "Linux x86_64) AppleWebKit/534.24 (KHTML, like Gecko) " +
-        "Chrome/11.0.696.34 Safari/534.24";
-    private static final String IPHONE_USERAGENT =
-            "Mozilla/5.0 (iPhone; U; CPU iPhone OS 3_0 like Mac OS X; en-us)"
-            + " AppleWebKit/528.18 (KHTML, like Gecko) Version/4.0"
-            + " Mobile/7A341 Safari/528.16";
-    private static Locale sLocale;
-    private static Object sLockForLocaleSettings;
-
-    /**
-     * Package constructor to prevent clients from creating a new settings
-     * instance.
-     */
-    WebSettings(Context context, WebView webview) {
-        mEventHandler = new EventHandler();
-        mContext = context;
-        mWebView = webview;
-        mDefaultTextEncoding = context.getString(com.android.internal.
-                                                 R.string.default_text_encoding);
-
-        if (sLockForLocaleSettings == null) {
-            sLockForLocaleSettings = new Object();
-            sLocale = Locale.getDefault();
-        }
-        mAcceptLanguage = getCurrentAcceptLanguage();
-        mUserAgent = getCurrentUserAgent();
-        mUseDefaultUserAgent = true;
-
-        mBlockNetworkLoads = mContext.checkPermission(
-                "android.permission.INTERNET", android.os.Process.myPid(),
-                android.os.Process.myUid()) != PackageManager.PERMISSION_GRANTED;
-    }
-
-    private static final String ACCEPT_LANG_FOR_US_LOCALE = "en-US";
-
-    /**
-     * Looks at sLocale and returns current AcceptLanguage String.
-     * @return Current AcceptLanguage String.
-     */
-    private String getCurrentAcceptLanguage() {
-        Locale locale;
-        synchronized(sLockForLocaleSettings) {
-            locale = sLocale;
-        }
-        StringBuilder buffer = new StringBuilder();
-        addLocaleToHttpAcceptLanguage(buffer, locale);
-
-        if (!Locale.US.equals(locale)) {
-            if (buffer.length() > 0) {
-                buffer.append(", ");
-            }
-            buffer.append(ACCEPT_LANG_FOR_US_LOCALE);
-        }
-
-        return buffer.toString();
-    }
-
-    /**
-     * Convert obsolete language codes, including Hebrew/Indonesian/Yiddish,
-     * to new standard.
-     */
-    private static String convertObsoleteLanguageCodeToNew(String langCode) {
-        if (langCode == null) {
-            return null;
-        }
-        if ("iw".equals(langCode)) {
-            // Hebrew
-            return "he";
-        } else if ("in".equals(langCode)) {
-            // Indonesian
-            return "id";
-        } else if ("ji".equals(langCode)) {
-            // Yiddish
-            return "yi";
-        }
-        return langCode;
-    }
-
-    private static void addLocaleToHttpAcceptLanguage(StringBuilder builder,
-                                                      Locale locale) {
-        String language = convertObsoleteLanguageCodeToNew(locale.getLanguage());
-        if (language != null) {
-            builder.append(language);
-            String country = locale.getCountry();
-            if (country != null) {
-                builder.append("-");
-                builder.append(country);
-            }
-        }
-    }
-
-    /**
-     * Looks at sLocale and mContext and returns current UserAgent String.
-     * @return Current UserAgent String.
-     */
-    private synchronized String getCurrentUserAgent() {
-        Locale locale;
-        synchronized(sLockForLocaleSettings) {
-            locale = sLocale;
-        }
-        StringBuffer buffer = new StringBuffer();
-        // Add version
-        final String version = Build.VERSION.RELEASE;
-        if (version.length() > 0) {
-            if (Character.isDigit(version.charAt(0))) {
-                // Release is a version, eg "3.1"
-                buffer.append(version);
-            } else {
-                // Release is a codename, eg "Honeycomb"
-                // In this case, use the previous release's version
-                buffer.append(PREVIOUS_VERSION);
-            }
-        } else {
-            // default to "1.0"
-            buffer.append("1.0");
-        }
-        buffer.append("; ");
-        final String language = locale.getLanguage();
-        if (language != null) {
-            buffer.append(convertObsoleteLanguageCodeToNew(language));
-            final String country = locale.getCountry();
-            if (country != null) {
-                buffer.append("-");
-                buffer.append(country.toLowerCase());
-            }
-        } else {
-            // default to "en"
-            buffer.append("en");
-        }
-        buffer.append(";");
-        // add the model for the release build
-        if ("REL".equals(Build.VERSION.CODENAME)) {
-            final String model = Build.MODEL;
-            if (model.length() > 0) {
-                buffer.append(" ");
-                buffer.append(model);
-            }
-        }
-        final String id = Build.ID;
-        if (id.length() > 0) {
-            buffer.append(" Build/");
-            buffer.append(id);
-        }
-        String mobile = mContext.getResources().getText(
-            com.android.internal.R.string.web_user_agent_target_content).toString();
-        final String base = mContext.getResources().getText(
-                com.android.internal.R.string.web_user_agent).toString();
-        return String.format(base, buffer, mobile);
+    protected WebSettings() {
     }
 
     /**
@@ -522,7 +157,7 @@
      */
     @Deprecated
     public void setNavDump(boolean enabled) {
-        mNavDump = enabled;
+        throw new MustOverrideException();
     }
 
     /**
@@ -531,37 +166,35 @@
      */
     @Deprecated
     public boolean getNavDump() {
-        return mNavDump;
+        throw new MustOverrideException();
     }
 
     /**
      * Set whether the WebView supports zoom
      */
     public void setSupportZoom(boolean support) {
-        mSupportZoom = support;
-        mWebView.updateMultiTouchSupport(mContext);
+        throw new MustOverrideException();
     }
 
     /**
      * Returns whether the WebView supports zoom
      */
     public boolean supportZoom() {
-        return mSupportZoom;
+        throw new MustOverrideException();
     }
 
     /**
      * Sets whether the zoom mechanism built into WebView is used.
      */
     public void setBuiltInZoomControls(boolean enabled) {
-        mBuiltInZoomControls = enabled;
-        mWebView.updateMultiTouchSupport(mContext);
+        throw new MustOverrideException();
     }
 
     /**
      * Returns true if the zoom mechanism built into WebView is being used.
      */
     public boolean getBuiltInZoomControls() {
-        return mBuiltInZoomControls;
+        throw new MustOverrideException();
     }
 
     /**
@@ -571,15 +204,14 @@
      * to work without the on screen controls
      */
     public void setDisplayZoomControls(boolean enabled) {
-        mDisplayZoomControls = enabled;
-        mWebView.updateMultiTouchSupport(mContext);
+        throw new MustOverrideException();
     }
 
     /**
      * Returns true if the on screen zoom buttons are being used.
      */
     public boolean getDisplayZoomControls() {
-        return mDisplayZoomControls;
+        throw new MustOverrideException();
     }
 
     /**
@@ -589,14 +221,14 @@
      * file:///android_res.
      */
     public void setAllowFileAccess(boolean allow) {
-        mAllowFileAccess = allow;
+        throw new MustOverrideException();
     }
 
     /**
      * Returns true if this WebView supports file access.
      */
     public boolean getAllowFileAccess() {
-        return mAllowFileAccess;
+        throw new MustOverrideException();
     }
 
     /**
@@ -605,28 +237,28 @@
      * system.  The default is enabled.
      */
     public void setAllowContentAccess(boolean allow) {
-        mAllowContentAccess = allow;
+        throw new MustOverrideException();
     }
 
     /**
      * Returns true if this WebView supports content url access.
      */
     public boolean getAllowContentAccess() {
-        return mAllowContentAccess;
+        throw new MustOverrideException();
     }
 
     /**
      * Set whether the WebView loads a page with overview mode.
      */
     public void setLoadWithOverviewMode(boolean overview) {
-        mLoadWithOverviewMode = overview;
+        throw new MustOverrideException();
     }
 
     /**
      * Returns true if this WebView loads page with overview mode
      */
     public boolean getLoadWithOverviewMode() {
-        return mLoadWithOverviewMode;
+        throw new MustOverrideException();
     }
 
     /**
@@ -637,15 +269,14 @@
      * If it is false, WebView will keep its fidelity. The default value is false.
      */
     public void setEnableSmoothTransition(boolean enable) {
-        mEnableSmoothTransition = enable;
+        throw new MustOverrideException();
     }
-
     /**
      * Returns true if the WebView enables smooth transition while panning or
      * zooming.
      */
     public boolean enableSmoothTransition() {
-        return mEnableSmoothTransition;
+        throw new MustOverrideException();
     }
 
     /**
@@ -656,7 +287,7 @@
      */
     @Deprecated
     public void setUseWebViewBackgroundForOverscrollBackground(boolean view) {
-        mUseWebViewBackgroundForOverscroll = view;
+        throw new MustOverrideException();
     }
 
     /**
@@ -666,14 +297,14 @@
      */
     @Deprecated
     public boolean getUseWebViewBackgroundForOverscrollBackground() {
-        return mUseWebViewBackgroundForOverscroll;
+        throw new MustOverrideException();
     }
 
     /**
      * Store whether the WebView is saving form data.
      */
     public void setSaveFormData(boolean save) {
-        mSaveFormData = save;
+        throw new MustOverrideException();
     }
 
     /**
@@ -681,21 +312,21 @@
      *  entries/autofill++.  Always false in private browsing mode.
      */
     public boolean getSaveFormData() {
-        return mSaveFormData && !mPrivateBrowsingEnabled;
+        throw new MustOverrideException();
     }
 
     /**
      *  Store whether the WebView is saving password.
      */
     public void setSavePassword(boolean save) {
-        mSavePassword = save;
+        throw new MustOverrideException();
     }
 
     /**
      *  Return whether the WebView is saving password.
      */
     public boolean getSavePassword() {
-        return mSavePassword;
+        throw new MustOverrideException();
     }
 
     /**
@@ -703,14 +334,7 @@
      * @param textZoom A percent value for increasing or decreasing the text.
      */
     public synchronized void setTextZoom(int textZoom) {
-        if (mTextSize != textZoom) {
-            if (WebView.mLogEvent) {
-                EventLog.writeEvent(EventLogTags.BROWSER_TEXT_SIZE_CHANGE,
-                        mTextSize, textZoom);
-            }
-            mTextSize = textZoom;
-            postSync();
-        }
+        throw new MustOverrideException();
     }
 
     /**
@@ -719,7 +343,7 @@
      * @see setTextSizeZoom
      */
     public synchronized int getTextZoom() {
-        return mTextSize;
+        throw new MustOverrideException();
     }
 
     /**
@@ -729,7 +353,7 @@
      * @deprecated Use {@link #setTextZoom(int)} instead
      */
     public synchronized void setTextSize(TextSize t) {
-        setTextZoom(t.value);
+        throw new MustOverrideException();
     }
 
     /**
@@ -741,40 +365,7 @@
      * @deprecated Use {@link #getTextZoom()} instead
      */
     public synchronized TextSize getTextSize() {
-        TextSize closestSize = null;
-        int smallestDelta = Integer.MAX_VALUE;
-        for (TextSize size : TextSize.values()) {
-            int delta = Math.abs(mTextSize - size.value);
-            if (delta == 0) {
-                return size;
-            }
-            if (delta < smallestDelta) {
-                smallestDelta = delta;
-                closestSize = size;
-            }
-        }
-        return closestSize != null ? closestSize : TextSize.NORMAL;
-    }
-
-    /**
-     * Set the double-tap zoom of the page in percent. Default is 100.
-     * @param doubleTapZoom A percent value for increasing or decreasing the double-tap zoom.
-     * @hide
-     */
-    public void setDoubleTapZoom(int doubleTapZoom) {
-        if (mDoubleTapZoom != doubleTapZoom) {
-            mDoubleTapZoom = doubleTapZoom;
-            mWebView.updateDoubleTapZoom(doubleTapZoom);
-        }
-    }
-
-    /**
-     * Get the double-tap zoom of the page in percent.
-     * @return A percent value describing the double-tap zoom.
-     * @hide
-     */
-    public int getDoubleTapZoom() {
-        return mDoubleTapZoom;
+        throw new MustOverrideException();
     }
 
     /**
@@ -784,10 +375,7 @@
      * @see WebSettings.ZoomDensity
      */
     public void setDefaultZoom(ZoomDensity zoom) {
-        if (mDefaultZoom != zoom) {
-            mDefaultZoom = zoom;
-            mWebView.adjustDefaultZoomDensity(zoom.value);
-        }
+        throw new MustOverrideException();
     }
 
     /**
@@ -797,21 +385,21 @@
      * @see WebSettings.ZoomDensity
      */
     public ZoomDensity getDefaultZoom() {
-        return mDefaultZoom;
+        throw new MustOverrideException();
     }
 
     /**
      * Enables using light touches to make a selection and activate mouseovers.
      */
     public void setLightTouchEnabled(boolean enabled) {
-        mLightTouchEnabled = enabled;
+        throw new MustOverrideException();
     }
 
     /**
      * Returns true if light touches are enabled.
      */
     public boolean getLightTouchEnabled() {
-        return mLightTouchEnabled;
+        throw new MustOverrideException();
     }
 
     /**
@@ -820,7 +408,7 @@
      */
     @Deprecated
     public synchronized void setUseDoubleTree(boolean use) {
-        return;
+        // Specified to do nothing, so no need for derived classes to override.
     }
 
     /**
@@ -829,6 +417,7 @@
      */
     @Deprecated
     public synchronized boolean getUseDoubleTree() {
+        // Returns false unconditionally, so no need for derived classes to override.
         return false;
     }
 
@@ -841,23 +430,7 @@
      */
     @Deprecated
     public synchronized void setUserAgent(int ua) {
-        String uaString = null;
-        if (ua == 1) {
-            if (DESKTOP_USERAGENT.equals(mUserAgent)) {
-                return; // do nothing
-            } else {
-                uaString = DESKTOP_USERAGENT;
-            }
-        } else if (ua == 2) {
-            if (IPHONE_USERAGENT.equals(mUserAgent)) {
-                return; // do nothing
-            } else {
-                uaString = IPHONE_USERAGENT;
-            }
-        } else if (ua != 0) {
-            return; // do nothing
-        }
-        setUserAgentString(uaString);
+        throw new MustOverrideException();
     }
 
     /**
@@ -870,31 +443,21 @@
      */
     @Deprecated
     public synchronized int getUserAgent() {
-        if (DESKTOP_USERAGENT.equals(mUserAgent)) {
-            return 1;
-        } else if (IPHONE_USERAGENT.equals(mUserAgent)) {
-            return 2;
-        } else if (mUseDefaultUserAgent) {
-            return 0;
-        }
-        return -1;
+        throw new MustOverrideException();
     }
 
     /**
      * Tell the WebView to use the wide viewport
      */
     public synchronized void setUseWideViewPort(boolean use) {
-        if (mUseWideViewport != use) {
-            mUseWideViewport = use;
-            postSync();
-        }
+        throw new MustOverrideException();
     }
 
     /**
      * @return True if the WebView is using a wide viewport
      */
     public synchronized boolean getUseWideViewPort() {
-        return mUseWideViewport;
+        throw new MustOverrideException();
     }
 
     /**
@@ -903,10 +466,7 @@
      *         boolean, Message)} is implemented by the host application.
      */
     public synchronized void setSupportMultipleWindows(boolean support) {
-        if (mSupportMultipleWindows != support) {
-            mSupportMultipleWindows = support;
-            postSync();
-        }
+        throw new MustOverrideException();
     }
 
     /**
@@ -915,7 +475,7 @@
      *         boolean, Message)} is implemented by the host application.
      */
     public synchronized boolean supportMultipleWindows() {
-        return mSupportMultipleWindows;
+        throw new MustOverrideException();
     }
 
     /**
@@ -925,12 +485,7 @@
      * @see WebSettings.LayoutAlgorithm
      */
     public synchronized void setLayoutAlgorithm(LayoutAlgorithm l) {
-        // XXX: This will only be affective if libwebcore was built with
-        // ANDROID_LAYOUT defined.
-        if (mLayoutAlgorithm != l) {
-            mLayoutAlgorithm = l;
-            postSync();
-        }
+        throw new MustOverrideException();
     }
 
     /**
@@ -940,7 +495,7 @@
      * @see WebSettings.LayoutAlgorithm
      */
     public synchronized LayoutAlgorithm getLayoutAlgorithm() {
-        return mLayoutAlgorithm;
+        throw new MustOverrideException();
     }
 
     /**
@@ -948,10 +503,7 @@
      * @param font A font family name.
      */
     public synchronized void setStandardFontFamily(String font) {
-        if (font != null && !font.equals(mStandardFontFamily)) {
-            mStandardFontFamily = font;
-            postSync();
-        }
+        throw new MustOverrideException();
     }
 
     /**
@@ -959,7 +511,7 @@
      * @return The standard font family name as a string.
      */
     public synchronized String getStandardFontFamily() {
-        return mStandardFontFamily;
+        throw new MustOverrideException();
     }
 
     /**
@@ -967,10 +519,7 @@
      * @param font A font family name.
      */
     public synchronized void setFixedFontFamily(String font) {
-        if (font != null && !font.equals(mFixedFontFamily)) {
-            mFixedFontFamily = font;
-            postSync();
-        }
+        throw new MustOverrideException();
     }
 
     /**
@@ -978,7 +527,7 @@
      * @return The fixed font family name as a string.
      */
     public synchronized String getFixedFontFamily() {
-        return mFixedFontFamily;
+        throw new MustOverrideException();
     }
 
     /**
@@ -986,10 +535,7 @@
      * @param font A font family name.
      */
     public synchronized void setSansSerifFontFamily(String font) {
-        if (font != null && !font.equals(mSansSerifFontFamily)) {
-            mSansSerifFontFamily = font;
-            postSync();
-        }
+        throw new MustOverrideException();
     }
 
     /**
@@ -997,7 +543,7 @@
      * @return The sans-serif font family name as a string.
      */
     public synchronized String getSansSerifFontFamily() {
-        return mSansSerifFontFamily;
+        throw new MustOverrideException();
     }
 
     /**
@@ -1005,10 +551,7 @@
      * @param font A font family name.
      */
     public synchronized void setSerifFontFamily(String font) {
-        if (font != null && !font.equals(mSerifFontFamily)) {
-            mSerifFontFamily = font;
-            postSync();
-        }
+        throw new MustOverrideException();
     }
 
     /**
@@ -1016,7 +559,7 @@
      * @return The serif font family name as a string.
      */
     public synchronized String getSerifFontFamily() {
-        return mSerifFontFamily;
+        throw new MustOverrideException();
     }
 
     /**
@@ -1024,10 +567,7 @@
      * @param font A font family name.
      */
     public synchronized void setCursiveFontFamily(String font) {
-        if (font != null && !font.equals(mCursiveFontFamily)) {
-            mCursiveFontFamily = font;
-            postSync();
-        }
+        throw new MustOverrideException();
     }
 
     /**
@@ -1035,7 +575,7 @@
      * @return The cursive font family name as a string.
      */
     public synchronized String getCursiveFontFamily() {
-        return mCursiveFontFamily;
+        throw new MustOverrideException();
     }
 
     /**
@@ -1043,10 +583,7 @@
      * @param font A font family name.
      */
     public synchronized void setFantasyFontFamily(String font) {
-        if (font != null && !font.equals(mFantasyFontFamily)) {
-            mFantasyFontFamily = font;
-            postSync();
-        }
+        throw new MustOverrideException();
     }
 
     /**
@@ -1054,7 +591,7 @@
      * @return The fantasy font family name as a string.
      */
     public synchronized String getFantasyFontFamily() {
-        return mFantasyFontFamily;
+        throw new MustOverrideException();
     }
 
     /**
@@ -1063,11 +600,7 @@
      * Any number outside the specified range will be pinned.
      */
     public synchronized void setMinimumFontSize(int size) {
-        size = pin(size);
-        if (mMinimumFontSize != size) {
-            mMinimumFontSize = size;
-            postSync();
-        }
+        throw new MustOverrideException();
     }
 
     /**
@@ -1075,7 +608,7 @@
      * @return A non-negative integer between 1 and 72.
      */
     public synchronized int getMinimumFontSize() {
-        return mMinimumFontSize;
+        throw new MustOverrideException();
     }
 
     /**
@@ -1084,11 +617,7 @@
      * Any number outside the specified range will be pinned.
      */
     public synchronized void setMinimumLogicalFontSize(int size) {
-        size = pin(size);
-        if (mMinimumLogicalFontSize != size) {
-            mMinimumLogicalFontSize = size;
-            postSync();
-        }
+        throw new MustOverrideException();
     }
 
     /**
@@ -1096,7 +625,7 @@
      * @return A non-negative integer between 1 and 72.
      */
     public synchronized int getMinimumLogicalFontSize() {
-        return mMinimumLogicalFontSize;
+        throw new MustOverrideException();
     }
 
     /**
@@ -1105,11 +634,7 @@
      * Any number outside the specified range will be pinned.
      */
     public synchronized void setDefaultFontSize(int size) {
-        size = pin(size);
-        if (mDefaultFontSize != size) {
-            mDefaultFontSize = size;
-            postSync();
-        }
+        throw new MustOverrideException();
     }
 
     /**
@@ -1117,7 +642,7 @@
      * @return A non-negative integer between 1 and 72.
      */
     public synchronized int getDefaultFontSize() {
-        return mDefaultFontSize;
+        throw new MustOverrideException();
     }
 
     /**
@@ -1126,11 +651,7 @@
      * Any number outside the specified range will be pinned.
      */
     public synchronized void setDefaultFixedFontSize(int size) {
-        size = pin(size);
-        if (mDefaultFixedFontSize != size) {
-            mDefaultFixedFontSize = size;
-            postSync();
-        }
+        throw new MustOverrideException();
     }
 
     /**
@@ -1138,21 +659,7 @@
      * @return A non-negative integer between 1 and 72.
      */
     public synchronized int getDefaultFixedFontSize() {
-        return mDefaultFixedFontSize;
-    }
-
-    /**
-     * Set the number of pages cached by the WebKit for the history navigation.
-     * @param size A non-negative integer between 0 (no cache) and 20 (max).
-     * @hide
-     */
-    public synchronized void setPageCacheCapacity(int size) {
-        if (size < 0) size = 0;
-        if (size > 20) size = 20;
-        if (mPageCacheCapacity != size) {
-            mPageCacheCapacity = size;
-            postSync();
-        }
+        throw new MustOverrideException();
     }
 
     /**
@@ -1165,10 +672,7 @@
      * @param flag Whether the WebView should load image resources.
      */
     public synchronized void setLoadsImagesAutomatically(boolean flag) {
-        if (mLoadsImagesAutomatically != flag) {
-            mLoadsImagesAutomatically = flag;
-            postSync();
-        }
+        throw new MustOverrideException();
     }
 
     /**
@@ -1177,7 +681,7 @@
      * @return True if the WebView loads image resources.
      */
     public synchronized boolean getLoadsImagesAutomatically() {
-        return mLoadsImagesAutomatically;
+        throw new MustOverrideException();
     }
 
     /**
@@ -1195,10 +699,7 @@
      * @see #setBlockNetworkLoads
      */
     public synchronized void setBlockNetworkImage(boolean flag) {
-        if (mBlockNetworkImage != flag) {
-            mBlockNetworkImage = flag;
-            postSync();
-        }
+        throw new MustOverrideException();
     }
 
     /**
@@ -1207,7 +708,7 @@
      * @return True if the WebView does not load image resources from the network.
      */
     public synchronized boolean getBlockNetworkImage() {
-        return mBlockNetworkImage;
+        throw new MustOverrideException();
     }
 
     /**
@@ -1226,11 +727,7 @@
      * @see android.webkit.WebView#reload
      */
     public synchronized void setBlockNetworkLoads(boolean flag) {
-        if (mBlockNetworkLoads != flag) {
-            mBlockNetworkLoads = flag;
-            verifyNetworkAccess();
-            postSync();
-        }
+        throw new MustOverrideException();
     }
 
     /**
@@ -1241,20 +738,7 @@
      * @return True if the WebView does not load any resources from the network.
      */
     public synchronized boolean getBlockNetworkLoads() {
-        return mBlockNetworkLoads;
-    }
-
-
-    private void verifyNetworkAccess() {
-        if (!mBlockNetworkLoads) {
-            if (mContext.checkPermission("android.permission.INTERNET",
-                    android.os.Process.myPid(), android.os.Process.myUid()) !=
-                        PackageManager.PERMISSION_GRANTED) {
-                throw new SecurityException
-                        ("Permission denied - " +
-                                "application missing INTERNET permission");
-            }
-        }
+        throw new MustOverrideException();
     }
 
     /**
@@ -1262,50 +746,7 @@
      * @param flag True if the WebView should execute javascript.
      */
     public synchronized void setJavaScriptEnabled(boolean flag) {
-        if (mJavaScriptEnabled != flag) {
-            mJavaScriptEnabled = flag;
-            postSync();
-        }
-    }
-
-    /**
-     * Tell the WebView to use Skia's hardware accelerated rendering path
-     * @param flag True if the WebView should use Skia's hw-accel path
-     * @hide
-     */
-    public synchronized void setHardwareAccelSkiaEnabled(boolean flag) {
-        if (mHardwareAccelSkia != flag) {
-            mHardwareAccelSkia = flag;
-            postSync();
-        }
-    }
-
-    /**
-     * @return True if the WebView is using hardware accelerated skia
-     * @hide
-     */
-    public synchronized boolean getHardwareAccelSkiaEnabled() {
-        return mHardwareAccelSkia;
-    }
-
-    /**
-     * Tell the WebView to show the visual indicator
-     * @param flag True if the WebView should show the visual indicator
-     * @hide
-     */
-    public synchronized void setShowVisualIndicator(boolean flag) {
-        if (mShowVisualIndicator != flag) {
-            mShowVisualIndicator = flag;
-            postSync();
-        }
-    }
-
-    /**
-     * @return True if the WebView is showing the visual indicator
-     * @hide
-     */
-    public synchronized boolean getShowVisualIndicator() {
-        return mShowVisualIndicator;
+        throw new MustOverrideException();
     }
 
     /**
@@ -1316,7 +757,7 @@
      */
     @Deprecated
     public synchronized void setPluginsEnabled(boolean flag) {
-        setPluginState(flag ? PluginState.ON : PluginState.OFF);
+        throw new MustOverrideException();
     }
 
     /**
@@ -1327,10 +768,7 @@
      * @param state One of the PluginState values.
      */
     public synchronized void setPluginState(PluginState state) {
-        if (mPluginState != state) {
-            mPluginState = state;
-            postSync();
-        }
+        throw new MustOverrideException();
     }
 
     /**
@@ -1342,6 +780,7 @@
      */
     @Deprecated
     public synchronized void setPluginsPath(String pluginsPath) {
+        // Specified to do nothing, so no need for derived classes to override.
     }
 
     /**
@@ -1352,11 +791,7 @@
      *     be saved. May be the empty string but should never be null.
      */
     public synchronized void setDatabasePath(String databasePath) {
-        if (databasePath != null && !mDatabasePathHasBeenSet) {
-            mDatabasePath = databasePath;
-            mDatabasePathHasBeenSet = true;
-            postSync();
-        }
+        throw new MustOverrideException();
     }
 
     /**
@@ -1367,40 +802,26 @@
      *     should never be null.
      */
     public synchronized void setGeolocationDatabasePath(String databasePath) {
-        if (databasePath != null
-                && !databasePath.equals(mGeolocationDatabasePath)) {
-            mGeolocationDatabasePath = databasePath;
-            postSync();
-        }
+        throw new MustOverrideException();
     }
 
     /**
-     * Enable or disable the Application Cache API.
-     * @param flag Whether to enable the Application Cache API.
+     * Tell the WebView to enable Application Caches API.
+     * @param flag True if the WebView should enable Application Caches.
      */
     public synchronized void setAppCacheEnabled(boolean flag) {
-        if (mAppCacheEnabled != flag) {
-            mAppCacheEnabled = flag;
-            postSync();
-        }
+        throw new MustOverrideException();
     }
 
     /**
-     * Set the path used by the Application Cache API to store files. This
-     * setting is applied to all WebViews in the application. In order for the
-     * Application Cache API to function, this method must be called with a
-     * path which exists and is writable by the application. This method may
-     * only be called once: repeated calls are ignored.
-     * @param path Path to the directory that should be used to store Application
-     * Cache files.
+     * Set a custom path to the Application Caches files. The client
+     * must ensure it exists before this call.
+     * @param appCachePath String path to the directory containing Application
+     * Caches files. The appCache path can be the empty string but should not
+     * be null. Passing null for this parameter will result in a no-op.
      */
-    public synchronized void setAppCachePath(String path) {
-        // We test for a valid path and for repeated setting on the native
-        // side, but we can avoid syncing in some simple cases. 
-        if (mAppCachePath == null && path != null && !path.isEmpty()) {
-            mAppCachePath = path;
-            postSync();
-        }
+    public synchronized void setAppCachePath(String appCachePath) {
+        throw new MustOverrideException();
     }
 
     /**
@@ -1408,10 +829,7 @@
      * @param appCacheMaxSize the maximum size in bytes.
      */
     public synchronized void setAppCacheMaxSize(long appCacheMaxSize) {
-        if (appCacheMaxSize != mAppCacheMaxSize) {
-            mAppCacheMaxSize = appCacheMaxSize;
-            postSync();
-        }
+        throw new MustOverrideException();
     }
 
     /**
@@ -1420,10 +838,7 @@
      *     API.
      */
     public synchronized void setDatabaseEnabled(boolean flag) {
-       if (mDatabaseEnabled != flag) {
-           mDatabaseEnabled = flag;
-           postSync();
-       }
+        throw new MustOverrideException();
     }
 
     /**
@@ -1432,10 +847,7 @@
      *     API.
      */
     public synchronized void setDomStorageEnabled(boolean flag) {
-       if (mDomStorageEnabled != flag) {
-           mDomStorageEnabled = flag;
-           postSync();
-       }
+        throw new MustOverrideException();
     }
 
     /**
@@ -1443,16 +855,15 @@
      * @return True if the DOM Storage API's are enabled.
      */
     public synchronized boolean getDomStorageEnabled() {
-       return mDomStorageEnabled;
+        throw new MustOverrideException();
     }
-
     /**
      * Return the path to where database storage API databases are saved for
      * the current WebView.
      * @return the String path to the database storage API databases.
      */
     public synchronized String getDatabasePath() {
-        return mDatabasePath;
+        throw new MustOverrideException();
     }
 
     /**
@@ -1460,21 +871,7 @@
      * @return True if the database storage API is enabled.
      */
     public synchronized boolean getDatabaseEnabled() {
-        return mDatabaseEnabled;
-    }
-
-    /**
-     * Tell the WebView to enable WebWorkers API.
-     * @param flag True if the WebView should enable WebWorkers.
-     * Note that this flag only affects V8. JSC does not have
-     * an equivalent setting.
-     * @hide
-     */
-    public synchronized void setWorkersEnabled(boolean flag) {
-        if (mWorkersEnabled != flag) {
-            mWorkersEnabled = flag;
-            postSync();
-        }
+        throw new MustOverrideException();
     }
 
     /**
@@ -1482,22 +879,7 @@
      * @param flag Whether Geolocation should be enabled.
      */
     public synchronized void setGeolocationEnabled(boolean flag) {
-        if (mGeolocationEnabled != flag) {
-            mGeolocationEnabled = flag;
-            postSync();
-        }
-    }
-
-    /**
-     * Sets whether XSS Auditor is enabled.
-     * @param flag Whether XSS Auditor should be enabled.
-     * @hide Only used by LayoutTestController.
-     */
-    public synchronized void setXSSAuditorEnabled(boolean flag) {
-        if (mXSSAuditorEnabled != flag) {
-            mXSSAuditorEnabled = flag;
-            postSync();
-        }
+        throw new MustOverrideException();
     }
 
     /**
@@ -1505,7 +887,7 @@
      * @return True if javascript is enabled.
      */
     public synchronized boolean getJavaScriptEnabled() {
-        return mJavaScriptEnabled;
+        throw new MustOverrideException();
     }
 
     /**
@@ -1515,7 +897,7 @@
      */
     @Deprecated
     public synchronized boolean getPluginsEnabled() {
-        return mPluginState == PluginState.ON;
+        throw new MustOverrideException();
     }
 
     /**
@@ -1523,7 +905,7 @@
      * @return A value corresponding to the enum PluginState.
      */
     public synchronized PluginState getPluginState() {
-        return mPluginState;
+        throw new MustOverrideException();
     }
 
     /**
@@ -1535,6 +917,7 @@
      */
     @Deprecated
     public synchronized String getPluginsPath() {
+        // Unconditionally returns empty string, so no need for derived classes to override.
         return "";
     }
 
@@ -1543,12 +926,8 @@
      * javascript function window.open().
      * @param flag True if javascript can open windows automatically.
      */
-    public synchronized void setJavaScriptCanOpenWindowsAutomatically(
-            boolean flag) {
-        if (mJavaScriptCanOpenWindowsAutomatically != flag) {
-            mJavaScriptCanOpenWindowsAutomatically = flag;
-            postSync();
-        }
+    public synchronized void setJavaScriptCanOpenWindowsAutomatically(boolean flag) {
+        throw new MustOverrideException();
     }
 
     /**
@@ -1558,18 +937,14 @@
      *         window.open().
      */
     public synchronized boolean getJavaScriptCanOpenWindowsAutomatically() {
-        return mJavaScriptCanOpenWindowsAutomatically;
+        throw new MustOverrideException();
     }
-
     /**
      * Set the default text encoding name to use when decoding html pages.
      * @param encoding The text encoding name.
      */
     public synchronized void setDefaultTextEncodingName(String encoding) {
-        if (encoding != null && !encoding.equals(mDefaultTextEncoding)) {
-            mDefaultTextEncoding = encoding;
-            postSync();
-        }
+        throw new MustOverrideException();
     }
 
     /**
@@ -1577,7 +952,7 @@
      * @return The default text encoding name as a string.
      */
     public synchronized String getDefaultTextEncodingName() {
-        return mDefaultTextEncoding;
+        throw new MustOverrideException();
     }
 
     /**
@@ -1585,66 +960,14 @@
      * it will use the system default user-agent string.
      */
     public synchronized void setUserAgentString(String ua) {
-        if (ua == null || ua.length() == 0) {
-            synchronized(sLockForLocaleSettings) {
-                Locale currentLocale = Locale.getDefault();
-                if (!sLocale.equals(currentLocale)) {
-                    sLocale = currentLocale;
-                    mAcceptLanguage = getCurrentAcceptLanguage();
-                }
-            }
-            ua = getCurrentUserAgent();
-            mUseDefaultUserAgent = true;
-        } else  {
-            mUseDefaultUserAgent = false;
-        }
-
-        if (!ua.equals(mUserAgent)) {
-            mUserAgent = ua;
-            postSync();
-        }
+        throw new MustOverrideException();
     }
 
     /**
      * Return the WebView's user-agent string.
      */
     public synchronized String getUserAgentString() {
-        if (DESKTOP_USERAGENT.equals(mUserAgent) ||
-                IPHONE_USERAGENT.equals(mUserAgent) ||
-                !mUseDefaultUserAgent) {
-            return mUserAgent;
-        }
-
-        boolean doPostSync = false;
-        synchronized(sLockForLocaleSettings) {
-            Locale currentLocale = Locale.getDefault();
-            if (!sLocale.equals(currentLocale)) {
-                sLocale = currentLocale;
-                mUserAgent = getCurrentUserAgent();
-                mAcceptLanguage = getCurrentAcceptLanguage();
-                doPostSync = true;
-            }
-        }
-        if (doPostSync) {
-            postSync();
-        }
-        return mUserAgent;
-    }
-
-    /* package api to grab the Accept Language string. */
-    /*package*/ synchronized String getAcceptLanguage() {
-        synchronized(sLockForLocaleSettings) {
-            Locale currentLocale = Locale.getDefault();
-            if (!sLocale.equals(currentLocale)) {
-                sLocale = currentLocale;
-                mAcceptLanguage = getCurrentAcceptLanguage();
-            }
-        }
-        return mAcceptLanguage;
-    }
-
-    /* package */ boolean isNarrowColumnLayout() {
-        return getLayoutAlgorithm() == LayoutAlgorithm.NARROW_COLUMNS;
+        throw new MustOverrideException();
     }
 
     /**
@@ -1654,14 +977,7 @@
      * @param flag
      */
     public void setNeedInitialFocus(boolean flag) {
-        if (mNeedInitialFocus != flag) {
-            mNeedInitialFocus = flag;
-        }
-    }
-
-    /* Package api to get the choice whether it needs to set initial focus. */
-    /* package */ boolean getNeedInitialFocus() {
-        return mNeedInitialFocus;
+        throw new MustOverrideException();
     }
 
     /**
@@ -1671,11 +987,7 @@
      * @param priority RenderPriority, can be normal, high or low.
      */
     public synchronized void setRenderPriority(RenderPriority priority) {
-        if (mRenderPriority != priority) {
-            mRenderPriority = priority;
-            mEventHandler.sendMessage(Message.obtain(null,
-                    EventHandler.PRIORITY));
-        }
+        throw new MustOverrideException();
     }
 
     /**
@@ -1687,10 +999,7 @@
      * @param mode One of the LOAD_ values.
      */
     public void setCacheMode(int mode) {
-        if (mode != mOverrideCacheMode) {
-            mOverrideCacheMode = mode;
-            postSync();
-        }
+        throw new MustOverrideException();
     }
 
     /**
@@ -1698,204 +1007,6 @@
      * description, see the {@link #setCacheMode(int)} function.
      */
     public int getCacheMode() {
-        return mOverrideCacheMode;
+        throw new MustOverrideException();
     }
-
-    /**
-     * If set, webkit alternately shrinks and expands images viewed outside
-     * of an HTML page to fit the screen. This conflicts with attempts by
-     * the UI to zoom in and out of an image, so it is set false by default.
-     * @param shrink Set true to let webkit shrink the standalone image to fit.
-     * {@hide}
-     */
-    public void setShrinksStandaloneImagesToFit(boolean shrink) {
-        if (mShrinksStandaloneImagesToFit != shrink) {
-            mShrinksStandaloneImagesToFit = shrink;
-            postSync();
-        }
-     }
-
-    /**
-     * Specify the maximum decoded image size. The default is
-     * 2 megs for small memory devices and 8 megs for large memory devices.
-     * @param size The maximum decoded size, or zero to set to the default.
-     * @hide
-     */
-    public void setMaximumDecodedImageSize(long size) {
-        if (mMaximumDecodedImageSize != size) {
-            mMaximumDecodedImageSize = size;
-            postSync();
-        }
-    }
-
-    /**
-     * Returns whether to use fixed viewport.  Use fixed viewport
-     * whenever wide viewport is on.
-     */
-    /* package */ boolean getUseFixedViewport() {
-        return getUseWideViewPort();
-    }
-
-    /**
-     * Returns whether private browsing is enabled.
-     */
-    /* package */ boolean isPrivateBrowsingEnabled() {
-        return mPrivateBrowsingEnabled;
-    }
-
-    /**
-     * Sets whether private browsing is enabled.
-     * @param flag Whether private browsing should be enabled.
-     */
-    /* package */ synchronized void setPrivateBrowsingEnabled(boolean flag) {
-        if (mPrivateBrowsingEnabled != flag) {
-            mPrivateBrowsingEnabled = flag;
-
-            // AutoFill is dependant on private browsing being enabled so
-            // reset it to take account of the new value of mPrivateBrowsingEnabled.
-            setAutoFillEnabled(mAutoFillEnabled);
-
-            postSync();
-        }
-    }
-
-    /**
-     * Returns whether the viewport metatag can disable zooming
-     * @hide
-     */
-    public boolean forceUserScalable() {
-        return mForceUserScalable;
-    }
-
-    /**
-     * Sets whether viewport metatag can disable zooming.
-     * @param flag Whether or not to forceably enable user scalable.
-     * @hide
-     */
-    public synchronized void setForceUserScalable(boolean flag) {
-        mForceUserScalable = flag;
-    }
-
-    synchronized void setSyntheticLinksEnabled(boolean flag) {
-        if (mSyntheticLinksEnabled != flag) {
-            mSyntheticLinksEnabled = flag;
-            postSync();
-        }
-    }
-
-    /**
-     * @hide
-     */
-    public synchronized void setAutoFillEnabled(boolean enabled) {
-        // AutoFill is always disabled in private browsing mode.
-        boolean autoFillEnabled = enabled && !mPrivateBrowsingEnabled;
-        if (mAutoFillEnabled != autoFillEnabled) {
-            mAutoFillEnabled = autoFillEnabled;
-            postSync();
-        }
-    }
-
-    /**
-     * @hide
-     */
-    public synchronized boolean getAutoFillEnabled() {
-        return mAutoFillEnabled;
-    }
-
-    /**
-     * @hide
-     */
-    public synchronized void setAutoFillProfile(AutoFillProfile profile) {
-        if (mAutoFillProfile != profile) {
-            mAutoFillProfile = profile;
-            postSync();
-        }
-    }
-
-    /**
-     * @hide
-     */
-    public synchronized AutoFillProfile getAutoFillProfile() {
-        return mAutoFillProfile;
-    }
-
-    int getDoubleTapToastCount() {
-        return mDoubleTapToastCount;
-    }
-
-    void setDoubleTapToastCount(int count) {
-        if (mDoubleTapToastCount != count) {
-            mDoubleTapToastCount = count;
-            // write the settings in the non-UI thread
-            mEventHandler.sendMessage(Message.obtain(null,
-                    EventHandler.SET_DOUBLE_TAP_TOAST_COUNT));
-        }
-    }
-
-    /**
-     * @hide
-     */
-    public void setProperty(String key, String value) {
-        if (mWebView.nativeSetProperty(key, value)) {
-            mWebView.contentInvalidateAll();
-        }
-    }
-
-    /**
-     * @hide
-     */
-    public String getProperty(String key) {
-        return mWebView.nativeGetProperty(key);
-    }
-
-    /**
-     * Transfer messages from the queue to the new WebCoreThread. Called from
-     * WebCore thread.
-     */
-    /*package*/
-    synchronized void syncSettingsAndCreateHandler(BrowserFrame frame) {
-        mBrowserFrame = frame;
-        if (DebugFlags.WEB_SETTINGS) {
-            junit.framework.Assert.assertTrue(frame.mNativeFrame != 0);
-        }
-
-        SharedPreferences sp = mContext.getSharedPreferences(PREF_FILE,
-                Context.MODE_PRIVATE);
-        if (mDoubleTapToastCount > 0) {
-            mDoubleTapToastCount = sp.getInt(DOUBLE_TAP_TOAST_COUNT,
-                    mDoubleTapToastCount);
-        }
-        nativeSync(frame.mNativeFrame);
-        mSyncPending = false;
-        mEventHandler.createHandler();
-    }
-
-    /**
-     * Let the Settings object know that our owner is being destroyed.
-     */
-    /*package*/
-    synchronized void onDestroyed() {
-    }
-
-    private int pin(int size) {
-        // FIXME: 72 is just an arbitrary max text size value.
-        if (size < 1) {
-            return 1;
-        } else if (size > 72) {
-            return 72;
-        }
-        return size;
-    }
-
-    /* Post a SYNC message to handle syncing the native settings. */
-    private synchronized void postSync() {
-        // Only post if a sync is not pending
-        if (!mSyncPending) {
-            mSyncPending = mEventHandler.sendMessage(
-                    Message.obtain(null, EventHandler.SYNC));
-        }
-    }
-
-    // Synchronize the native and java settings.
-    private native void nativeSync(int nativeFrame);
 }
diff --git a/core/java/android/webkit/WebSettingsClassic.java b/core/java/android/webkit/WebSettingsClassic.java
new file mode 100644
index 0000000..6850eea
--- /dev/null
+++ b/core/java/android/webkit/WebSettingsClassic.java
@@ -0,0 +1,1702 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.webkit;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.content.pm.PackageManager;
+import android.os.Build;
+import android.os.Handler;
+import android.os.Message;
+import android.util.DisplayMetrics;
+import android.util.EventLog;
+
+import java.util.Locale;
+
+/**
+ * WebSettings implementation for the WebViewClassic implementation of WebView.
+ * @hide
+ */
+public class WebSettingsClassic extends WebSettings {
+    // TODO: Keep this up to date
+    private static final String PREVIOUS_VERSION = "4.0.3";
+
+    // WebView associated with this WebSettings.
+    private WebViewClassic mWebView;
+    // BrowserFrame used to access the native frame pointer.
+    private BrowserFrame mBrowserFrame;
+    // Flag to prevent multiple SYNC messages at one time.
+    private boolean mSyncPending = false;
+    // Custom handler that queues messages until the WebCore thread is active.
+    private final EventHandler mEventHandler;
+
+    // Private settings so we don't have to go into native code to
+    // retrieve the values. After setXXX, postSync() needs to be called.
+    //
+    // The default values need to match those in WebSettings.cpp
+    // If the defaults change, please also update the JavaDocs so developers
+    // know what they are.
+    private LayoutAlgorithm mLayoutAlgorithm = LayoutAlgorithm.NARROW_COLUMNS;
+    private Context         mContext;
+    private int             mTextSize = 100;
+    private String          mStandardFontFamily = "sans-serif";
+    private String          mFixedFontFamily = "monospace";
+    private String          mSansSerifFontFamily = "sans-serif";
+    private String          mSerifFontFamily = "serif";
+    private String          mCursiveFontFamily = "cursive";
+    private String          mFantasyFontFamily = "fantasy";
+    private String          mDefaultTextEncoding;
+    private String          mUserAgent;
+    private boolean         mUseDefaultUserAgent;
+    private String          mAcceptLanguage;
+    private int             mMinimumFontSize = 8;
+    private int             mMinimumLogicalFontSize = 8;
+    private int             mDefaultFontSize = 16;
+    private int             mDefaultFixedFontSize = 13;
+    private int             mPageCacheCapacity = 0;
+    private boolean         mLoadsImagesAutomatically = true;
+    private boolean         mBlockNetworkImage = false;
+    private boolean         mBlockNetworkLoads;
+    private boolean         mJavaScriptEnabled = false;
+    private boolean         mHardwareAccelSkia = false;
+    private boolean         mShowVisualIndicator = false;
+    private PluginState     mPluginState = PluginState.OFF;
+    private boolean         mJavaScriptCanOpenWindowsAutomatically = false;
+    private boolean         mUseDoubleTree = false;
+    private boolean         mUseWideViewport = false;
+    private boolean         mSupportMultipleWindows = false;
+    private boolean         mShrinksStandaloneImagesToFit = false;
+    private long            mMaximumDecodedImageSize = 0; // 0 means default
+    private boolean         mPrivateBrowsingEnabled = false;
+    private boolean         mSyntheticLinksEnabled = true;
+    // HTML5 API flags
+    private boolean         mAppCacheEnabled = false;
+    private boolean         mDatabaseEnabled = false;
+    private boolean         mDomStorageEnabled = false;
+    private boolean         mWorkersEnabled = false;  // only affects V8.
+    private boolean         mGeolocationEnabled = true;
+    private boolean         mXSSAuditorEnabled = false;
+    // HTML5 configuration parameters
+    private long            mAppCacheMaxSize = Long.MAX_VALUE;
+    private String          mAppCachePath = null;
+    private String          mDatabasePath = "";
+    // The WebCore DatabaseTracker only allows the database path to be set
+    // once. Keep track of when the path has been set.
+    private boolean         mDatabasePathHasBeenSet = false;
+    private String          mGeolocationDatabasePath = "";
+    // Don't need to synchronize the get/set methods as they
+    // are basic types, also none of these values are used in
+    // native WebCore code.
+    private ZoomDensity     mDefaultZoom = ZoomDensity.MEDIUM;
+    private RenderPriority  mRenderPriority = RenderPriority.NORMAL;
+    private int             mOverrideCacheMode = LOAD_DEFAULT;
+    private int             mDoubleTapZoom = 100;
+    private boolean         mSaveFormData = true;
+    private boolean         mAutoFillEnabled = false;
+    private boolean         mSavePassword = true;
+    private boolean         mLightTouchEnabled = false;
+    private boolean         mNeedInitialFocus = true;
+    private boolean         mNavDump = false;
+    private boolean         mSupportZoom = true;
+    private boolean         mBuiltInZoomControls = false;
+    private boolean         mDisplayZoomControls = true;
+    private boolean         mAllowFileAccess = true;
+    private boolean         mAllowContentAccess = true;
+    private boolean         mLoadWithOverviewMode = false;
+    private boolean         mEnableSmoothTransition = false;
+    private boolean         mForceUserScalable = false;
+
+    // AutoFill Profile data
+    /**
+     * @hide for now, pending API council approval.
+     */
+    public static class AutoFillProfile {
+        private int mUniqueId;
+        private String mFullName;
+        private String mEmailAddress;
+        private String mCompanyName;
+        private String mAddressLine1;
+        private String mAddressLine2;
+        private String mCity;
+        private String mState;
+        private String mZipCode;
+        private String mCountry;
+        private String mPhoneNumber;
+
+        public AutoFillProfile(int uniqueId, String fullName, String email,
+                String companyName, String addressLine1, String addressLine2,
+                String city, String state, String zipCode, String country,
+                String phoneNumber) {
+            mUniqueId = uniqueId;
+            mFullName = fullName;
+            mEmailAddress = email;
+            mCompanyName = companyName;
+            mAddressLine1 = addressLine1;
+            mAddressLine2 = addressLine2;
+            mCity = city;
+            mState = state;
+            mZipCode = zipCode;
+            mCountry = country;
+            mPhoneNumber = phoneNumber;
+        }
+
+        public int getUniqueId() { return mUniqueId; }
+        public String getFullName() { return mFullName; }
+        public String getEmailAddress() { return mEmailAddress; }
+        public String getCompanyName() { return mCompanyName; }
+        public String getAddressLine1() { return mAddressLine1; }
+        public String getAddressLine2() { return mAddressLine2; }
+        public String getCity() { return mCity; }
+        public String getState() { return mState; }
+        public String getZipCode() { return mZipCode; }
+        public String getCountry() { return mCountry; }
+        public String getPhoneNumber() { return mPhoneNumber; }
+    }
+
+
+    private AutoFillProfile mAutoFillProfile;
+
+    private boolean         mUseWebViewBackgroundForOverscroll = true;
+
+    // private WebSettings, not accessible by the host activity
+    static private int      mDoubleTapToastCount = 3;
+
+    private static final String PREF_FILE = "WebViewSettings";
+    private static final String DOUBLE_TAP_TOAST_COUNT = "double_tap_toast_count";
+
+    // Class to handle messages before WebCore is ready.
+    private class EventHandler {
+        // Message id for syncing
+        static final int SYNC = 0;
+        // Message id for setting priority
+        static final int PRIORITY = 1;
+        // Message id for writing double-tap toast count
+        static final int SET_DOUBLE_TAP_TOAST_COUNT = 2;
+        // Actual WebCore thread handler
+        private Handler mHandler;
+
+        private synchronized void createHandler() {
+            // as mRenderPriority can be set before thread is running, sync up
+            setRenderPriority();
+
+            // create a new handler
+            mHandler = new Handler() {
+                @Override
+                public void handleMessage(Message msg) {
+                    switch (msg.what) {
+                        case SYNC:
+                            synchronized (WebSettingsClassic.this) {
+                                if (mBrowserFrame.mNativeFrame != 0) {
+                                    nativeSync(mBrowserFrame.mNativeFrame);
+                                }
+                                mSyncPending = false;
+                            }
+                            break;
+
+                        case PRIORITY: {
+                            setRenderPriority();
+                            break;
+                        }
+
+                        case SET_DOUBLE_TAP_TOAST_COUNT: {
+                            SharedPreferences.Editor editor = mContext
+                                    .getSharedPreferences(PREF_FILE,
+                                            Context.MODE_PRIVATE).edit();
+                            editor.putInt(DOUBLE_TAP_TOAST_COUNT,
+                                    mDoubleTapToastCount);
+                            editor.commit();
+                            break;
+                        }
+                    }
+                }
+            };
+        }
+
+        private void setRenderPriority() {
+            synchronized (WebSettingsClassic.this) {
+                if (mRenderPriority == RenderPriority.NORMAL) {
+                    android.os.Process.setThreadPriority(
+                            android.os.Process.THREAD_PRIORITY_DEFAULT);
+                } else if (mRenderPriority == RenderPriority.HIGH) {
+                    android.os.Process.setThreadPriority(
+                            android.os.Process.THREAD_PRIORITY_FOREGROUND +
+                            android.os.Process.THREAD_PRIORITY_LESS_FAVORABLE);
+                } else if (mRenderPriority == RenderPriority.LOW) {
+                    android.os.Process.setThreadPriority(
+                            android.os.Process.THREAD_PRIORITY_BACKGROUND);
+                }
+            }
+        }
+
+        /**
+         * Send a message to the private queue or handler.
+         */
+        private synchronized boolean sendMessage(Message msg) {
+            if (mHandler != null) {
+                mHandler.sendMessage(msg);
+                return true;
+            } else {
+                return false;
+            }
+        }
+    }
+
+    // User agent strings.
+    private static final String DESKTOP_USERAGENT = "Mozilla/5.0 (X11; " +
+        "Linux x86_64) AppleWebKit/534.24 (KHTML, like Gecko) " +
+        "Chrome/11.0.696.34 Safari/534.24";
+    private static final String IPHONE_USERAGENT =
+            "Mozilla/5.0 (iPhone; U; CPU iPhone OS 3_0 like Mac OS X; en-us)"
+            + " AppleWebKit/528.18 (KHTML, like Gecko) Version/4.0"
+            + " Mobile/7A341 Safari/528.16";
+    private static Locale sLocale;
+    private static Object sLockForLocaleSettings;
+
+    /**
+     * Package constructor to prevent clients from creating a new settings
+     * instance.
+     */
+    WebSettingsClassic(Context context, WebViewClassic webview) {
+        mEventHandler = new EventHandler();
+        mContext = context;
+        mWebView = webview;
+        mDefaultTextEncoding = context.getString(com.android.internal.
+                                                 R.string.default_text_encoding);
+
+        if (sLockForLocaleSettings == null) {
+            sLockForLocaleSettings = new Object();
+            sLocale = Locale.getDefault();
+        }
+        mAcceptLanguage = getCurrentAcceptLanguage();
+        mUserAgent = getCurrentUserAgent();
+        mUseDefaultUserAgent = true;
+
+        mBlockNetworkLoads = mContext.checkPermission(
+                "android.permission.INTERNET", android.os.Process.myPid(),
+                android.os.Process.myUid()) != PackageManager.PERMISSION_GRANTED;
+    }
+
+    private static final String ACCEPT_LANG_FOR_US_LOCALE = "en-US";
+
+    /**
+     * Looks at sLocale and returns current AcceptLanguage String.
+     * @return Current AcceptLanguage String.
+     */
+    private String getCurrentAcceptLanguage() {
+        Locale locale;
+        synchronized(sLockForLocaleSettings) {
+            locale = sLocale;
+        }
+        StringBuilder buffer = new StringBuilder();
+        addLocaleToHttpAcceptLanguage(buffer, locale);
+
+        if (!Locale.US.equals(locale)) {
+            if (buffer.length() > 0) {
+                buffer.append(", ");
+            }
+            buffer.append(ACCEPT_LANG_FOR_US_LOCALE);
+        }
+
+        return buffer.toString();
+    }
+
+    /**
+     * Convert obsolete language codes, including Hebrew/Indonesian/Yiddish,
+     * to new standard.
+     */
+    private static String convertObsoleteLanguageCodeToNew(String langCode) {
+        if (langCode == null) {
+            return null;
+        }
+        if ("iw".equals(langCode)) {
+            // Hebrew
+            return "he";
+        } else if ("in".equals(langCode)) {
+            // Indonesian
+            return "id";
+        } else if ("ji".equals(langCode)) {
+            // Yiddish
+            return "yi";
+        }
+        return langCode;
+    }
+
+    private static void addLocaleToHttpAcceptLanguage(StringBuilder builder,
+                                                      Locale locale) {
+        String language = convertObsoleteLanguageCodeToNew(locale.getLanguage());
+        if (language != null) {
+            builder.append(language);
+            String country = locale.getCountry();
+            if (country != null) {
+                builder.append("-");
+                builder.append(country);
+            }
+        }
+    }
+
+    /**
+     * Looks at sLocale and mContext and returns current UserAgent String.
+     * @return Current UserAgent String.
+     */
+    private synchronized String getCurrentUserAgent() {
+        Locale locale;
+        synchronized(sLockForLocaleSettings) {
+            locale = sLocale;
+        }
+        StringBuffer buffer = new StringBuffer();
+        // Add version
+        final String version = Build.VERSION.RELEASE;
+        if (version.length() > 0) {
+            if (Character.isDigit(version.charAt(0))) {
+                // Release is a version, eg "3.1"
+                buffer.append(version);
+            } else {
+                // Release is a codename, eg "Honeycomb"
+                // In this case, use the previous release's version
+                buffer.append(PREVIOUS_VERSION);
+            }
+        } else {
+            // default to "1.0"
+            buffer.append("1.0");
+        }
+        buffer.append("; ");
+        final String language = locale.getLanguage();
+        if (language != null) {
+            buffer.append(convertObsoleteLanguageCodeToNew(language));
+            final String country = locale.getCountry();
+            if (country != null) {
+                buffer.append("-");
+                buffer.append(country.toLowerCase());
+            }
+        } else {
+            // default to "en"
+            buffer.append("en");
+        }
+        buffer.append(";");
+        // add the model for the release build
+        if ("REL".equals(Build.VERSION.CODENAME)) {
+            final String model = Build.MODEL;
+            if (model.length() > 0) {
+                buffer.append(" ");
+                buffer.append(model);
+            }
+        }
+        final String id = Build.ID;
+        if (id.length() > 0) {
+            buffer.append(" Build/");
+            buffer.append(id);
+        }
+        String mobile = mContext.getResources().getText(
+            com.android.internal.R.string.web_user_agent_target_content).toString();
+        final String base = mContext.getResources().getText(
+                com.android.internal.R.string.web_user_agent).toString();
+        return String.format(base, buffer, mobile);
+    }
+
+    /**
+     * @see android.webkit.WebSettings#setNavDump(boolean)
+     */
+    @Override
+    @Deprecated
+    public void setNavDump(boolean enabled) {
+        mNavDump = enabled;
+    }
+
+    /**
+     * @see android.webkit.WebSettings#getNavDump()
+     */
+    @Override
+    @Deprecated
+    public boolean getNavDump() {
+        return mNavDump;
+    }
+
+    /**
+     * @see android.webkit.WebSettings#setSupportZoom(boolean)
+     */
+    @Override
+    public void setSupportZoom(boolean support) {
+        mSupportZoom = support;
+        mWebView.updateMultiTouchSupport(mContext);
+    }
+
+    /**
+     * @see android.webkit.WebSettings#supportZoom()
+     */
+    @Override
+    public boolean supportZoom() {
+        return mSupportZoom;
+    }
+
+    /**
+     * @see android.webkit.WebSettings#setBuiltInZoomControls(boolean)
+     */
+    @Override
+    public void setBuiltInZoomControls(boolean enabled) {
+        mBuiltInZoomControls = enabled;
+        mWebView.updateMultiTouchSupport(mContext);
+    }
+
+    /**
+     * @see android.webkit.WebSettings#getBuiltInZoomControls()
+     */
+    @Override
+    public boolean getBuiltInZoomControls() {
+        return mBuiltInZoomControls;
+    }
+
+    /**
+     * @see android.webkit.WebSettings#setDisplayZoomControls(boolean)
+     */
+    @Override
+    public void setDisplayZoomControls(boolean enabled) {
+        mDisplayZoomControls = enabled;
+        mWebView.updateMultiTouchSupport(mContext);
+    }
+
+    /**
+     * @see android.webkit.WebSettings#getDisplayZoomControls()
+     */
+    @Override
+    public boolean getDisplayZoomControls() {
+        return mDisplayZoomControls;
+    }
+
+    /**
+     * @see android.webkit.WebSettings#setAllowFileAccess(boolean)
+     */
+    @Override
+    public void setAllowFileAccess(boolean allow) {
+        mAllowFileAccess = allow;
+    }
+
+    /**
+     * @see android.webkit.WebSettings#getAllowFileAccess()
+     */
+    @Override
+    public boolean getAllowFileAccess() {
+        return mAllowFileAccess;
+    }
+
+    /**
+     * @see android.webkit.WebSettings#setAllowContentAccess(boolean)
+     */
+    @Override
+    public void setAllowContentAccess(boolean allow) {
+        mAllowContentAccess = allow;
+    }
+
+    /**
+     * @see android.webkit.WebSettings#getAllowContentAccess()
+     */
+    @Override
+    public boolean getAllowContentAccess() {
+        return mAllowContentAccess;
+    }
+
+    /**
+     * @see android.webkit.WebSettings#setLoadWithOverviewMode(boolean)
+     */
+    @Override
+    public void setLoadWithOverviewMode(boolean overview) {
+        mLoadWithOverviewMode = overview;
+    }
+
+    /**
+     * @see android.webkit.WebSettings#getLoadWithOverviewMode()
+     */
+    @Override
+    public boolean getLoadWithOverviewMode() {
+        return mLoadWithOverviewMode;
+    }
+
+    /**
+     * @see android.webkit.WebSettings#setEnableSmoothTransition(boolean)
+     */
+    @Override
+    public void setEnableSmoothTransition(boolean enable) {
+        mEnableSmoothTransition = enable;
+    }
+
+    /**
+     * @see android.webkit.WebSettings#enableSmoothTransition()
+     */
+    @Override
+    public boolean enableSmoothTransition() {
+        return mEnableSmoothTransition;
+    }
+
+    /**
+     * @see android.webkit.WebSettings#setUseWebViewBackgroundForOverscrollBackground(boolean)
+     */
+    @Override
+    @Deprecated
+    public void setUseWebViewBackgroundForOverscrollBackground(boolean view) {
+        mUseWebViewBackgroundForOverscroll = view;
+    }
+
+    /**
+     * @see android.webkit.WebSettings#getUseWebViewBackgroundForOverscrollBackground()
+     */
+    @Override
+    @Deprecated
+    public boolean getUseWebViewBackgroundForOverscrollBackground() {
+        return mUseWebViewBackgroundForOverscroll;
+    }
+
+    /**
+     * @see android.webkit.WebSettings#setSaveFormData(boolean)
+     */
+    @Override
+    public void setSaveFormData(boolean save) {
+        mSaveFormData = save;
+    }
+
+    /**
+     * @see android.webkit.WebSettings#getSaveFormData()
+     */
+    @Override
+    public boolean getSaveFormData() {
+        return mSaveFormData && !mPrivateBrowsingEnabled;
+    }
+
+    /**
+     * @see android.webkit.WebSettings#setSavePassword(boolean)
+     */
+    @Override
+    public void setSavePassword(boolean save) {
+        mSavePassword = save;
+    }
+
+    /**
+     * @see android.webkit.WebSettings#getSavePassword()
+     */
+    @Override
+    public boolean getSavePassword() {
+        return mSavePassword;
+    }
+
+    /**
+     * @see android.webkit.WebSettings#setTextZoom(int)
+     */
+    @Override
+    public synchronized void setTextZoom(int textZoom) {
+        if (mTextSize != textZoom) {
+            if (WebViewClassic.mLogEvent) {
+                EventLog.writeEvent(EventLogTags.BROWSER_TEXT_SIZE_CHANGE,
+                        mTextSize, textZoom);
+            }
+            mTextSize = textZoom;
+            postSync();
+        }
+    }
+
+    /**
+     * @see android.webkit.WebSettings#getTextZoom()
+     */
+    @Override
+    public synchronized int getTextZoom() {
+        return mTextSize;
+    }
+
+    /**
+     * @see android.webkit.WebSettings#setTextSize(android.webkit.WebSettingsClassic.TextSize)
+     */
+    @Override
+    public synchronized void setTextSize(TextSize t) {
+        setTextZoom(t.value);
+    }
+
+    /**
+     * @see android.webkit.WebSettings#getTextSize()
+     */
+    @Override
+    public synchronized TextSize getTextSize() {
+        TextSize closestSize = null;
+        int smallestDelta = Integer.MAX_VALUE;
+        for (TextSize size : TextSize.values()) {
+            int delta = Math.abs(mTextSize - size.value);
+            if (delta == 0) {
+                return size;
+            }
+            if (delta < smallestDelta) {
+                smallestDelta = delta;
+                closestSize = size;
+            }
+        }
+        return closestSize != null ? closestSize : TextSize.NORMAL;
+    }
+
+    /**
+     * Set the double-tap zoom of the page in percent. Default is 100.
+     * @param doubleTapZoom A percent value for increasing or decreasing the double-tap zoom.
+     * @hide
+     */
+    public void setDoubleTapZoom(int doubleTapZoom) {
+        if (mDoubleTapZoom != doubleTapZoom) {
+            mDoubleTapZoom = doubleTapZoom;
+            mWebView.updateDoubleTapZoom(doubleTapZoom);
+        }
+    }
+
+    /**
+     * Get the double-tap zoom of the page in percent.
+     * @return A percent value describing the double-tap zoom.
+     * @hide
+     */
+    public int getDoubleTapZoom() {
+        return mDoubleTapZoom;
+    }
+
+    /**
+     * @see android.webkit.WebSettings#setDefaultZoom(android.webkit.WebSettingsClassic.ZoomDensity)
+     */
+    @Override
+    public void setDefaultZoom(ZoomDensity zoom) {
+        if (mDefaultZoom != zoom) {
+            mDefaultZoom = zoom;
+            mWebView.adjustDefaultZoomDensity(zoom.value);
+        }
+    }
+
+    /**
+     * @see android.webkit.WebSettings#getDefaultZoom()
+     */
+    @Override
+    public ZoomDensity getDefaultZoom() {
+        return mDefaultZoom;
+    }
+
+    /**
+     * @see android.webkit.WebSettings#setLightTouchEnabled(boolean)
+     */
+    @Override
+    public void setLightTouchEnabled(boolean enabled) {
+        mLightTouchEnabled = enabled;
+    }
+
+    /**
+     * @see android.webkit.WebSettings#getLightTouchEnabled()
+     */
+    @Override
+    public boolean getLightTouchEnabled() {
+        return mLightTouchEnabled;
+    }
+
+    /**
+     * @see android.webkit.WebSettings#setUseDoubleTree(boolean)
+     */
+    @Override
+    @Deprecated
+    public synchronized void setUseDoubleTree(boolean use) {
+        return;
+    }
+
+    /**
+     * @see android.webkit.WebSettings#getUseDoubleTree()
+     */
+    @Override
+    @Deprecated
+    public synchronized boolean getUseDoubleTree() {
+        return false;
+    }
+
+    /**
+     * @see android.webkit.WebSettings#setUserAgent(int)
+     */
+    @Override
+    @Deprecated
+    public synchronized void setUserAgent(int ua) {
+        String uaString = null;
+        if (ua == 1) {
+            if (DESKTOP_USERAGENT.equals(mUserAgent)) {
+                return; // do nothing
+            } else {
+                uaString = DESKTOP_USERAGENT;
+            }
+        } else if (ua == 2) {
+            if (IPHONE_USERAGENT.equals(mUserAgent)) {
+                return; // do nothing
+            } else {
+                uaString = IPHONE_USERAGENT;
+            }
+        } else if (ua != 0) {
+            return; // do nothing
+        }
+        setUserAgentString(uaString);
+    }
+
+    /**
+     * @see android.webkit.WebSettings#getUserAgent()
+     */
+    @Override
+    @Deprecated
+    public synchronized int getUserAgent() {
+        if (DESKTOP_USERAGENT.equals(mUserAgent)) {
+            return 1;
+        } else if (IPHONE_USERAGENT.equals(mUserAgent)) {
+            return 2;
+        } else if (mUseDefaultUserAgent) {
+            return 0;
+        }
+        return -1;
+    }
+
+    /**
+     * @see android.webkit.WebSettings#setUseWideViewPort(boolean)
+     */
+    @Override
+    public synchronized void setUseWideViewPort(boolean use) {
+        if (mUseWideViewport != use) {
+            mUseWideViewport = use;
+            postSync();
+        }
+    }
+
+    /**
+     * @see android.webkit.WebSettings#getUseWideViewPort()
+     */
+    @Override
+    public synchronized boolean getUseWideViewPort() {
+        return mUseWideViewport;
+    }
+
+    /**
+     * @see android.webkit.WebSettings#setSupportMultipleWindows(boolean)
+     */
+    @Override
+    public synchronized void setSupportMultipleWindows(boolean support) {
+        if (mSupportMultipleWindows != support) {
+            mSupportMultipleWindows = support;
+            postSync();
+        }
+    }
+
+    /**
+     * @see android.webkit.WebSettings#supportMultipleWindows()
+     */
+    @Override
+    public synchronized boolean supportMultipleWindows() {
+        return mSupportMultipleWindows;
+    }
+
+    /**
+     * @see android.webkit.WebSettings#setLayoutAlgorithm(android.webkit.WebSettingsClassic.LayoutAlgorithm)
+     */
+    @Override
+    public synchronized void setLayoutAlgorithm(LayoutAlgorithm l) {
+        // XXX: This will only be affective if libwebcore was built with
+        // ANDROID_LAYOUT defined.
+        if (mLayoutAlgorithm != l) {
+            mLayoutAlgorithm = l;
+            postSync();
+        }
+    }
+
+    /**
+     * @see android.webkit.WebSettings#getLayoutAlgorithm()
+     */
+    @Override
+    public synchronized LayoutAlgorithm getLayoutAlgorithm() {
+        return mLayoutAlgorithm;
+    }
+
+    /**
+     * @see android.webkit.WebSettings#setStandardFontFamily(java.lang.String)
+     */
+    @Override
+    public synchronized void setStandardFontFamily(String font) {
+        if (font != null && !font.equals(mStandardFontFamily)) {
+            mStandardFontFamily = font;
+            postSync();
+        }
+    }
+
+    /**
+     * @see android.webkit.WebSettings#getStandardFontFamily()
+     */
+    @Override
+    public synchronized String getStandardFontFamily() {
+        return mStandardFontFamily;
+    }
+
+    /**
+     * @see android.webkit.WebSettings#setFixedFontFamily(java.lang.String)
+     */
+    @Override
+    public synchronized void setFixedFontFamily(String font) {
+        if (font != null && !font.equals(mFixedFontFamily)) {
+            mFixedFontFamily = font;
+            postSync();
+        }
+    }
+
+    /**
+     * @see android.webkit.WebSettings#getFixedFontFamily()
+     */
+    @Override
+    public synchronized String getFixedFontFamily() {
+        return mFixedFontFamily;
+    }
+
+    /**
+     * @see android.webkit.WebSettings#setSansSerifFontFamily(java.lang.String)
+     */
+    @Override
+    public synchronized void setSansSerifFontFamily(String font) {
+        if (font != null && !font.equals(mSansSerifFontFamily)) {
+            mSansSerifFontFamily = font;
+            postSync();
+        }
+    }
+
+    /**
+     * @see android.webkit.WebSettings#getSansSerifFontFamily()
+     */
+    @Override
+    public synchronized String getSansSerifFontFamily() {
+        return mSansSerifFontFamily;
+    }
+
+    /**
+     * @see android.webkit.WebSettings#setSerifFontFamily(java.lang.String)
+     */
+    @Override
+    public synchronized void setSerifFontFamily(String font) {
+        if (font != null && !font.equals(mSerifFontFamily)) {
+            mSerifFontFamily = font;
+            postSync();
+        }
+    }
+
+    /**
+     * @see android.webkit.WebSettings#getSerifFontFamily()
+     */
+    @Override
+    public synchronized String getSerifFontFamily() {
+        return mSerifFontFamily;
+    }
+
+    /**
+     * @see android.webkit.WebSettings#setCursiveFontFamily(java.lang.String)
+     */
+    @Override
+    public synchronized void setCursiveFontFamily(String font) {
+        if (font != null && !font.equals(mCursiveFontFamily)) {
+            mCursiveFontFamily = font;
+            postSync();
+        }
+    }
+
+    /**
+     * @see android.webkit.WebSettings#getCursiveFontFamily()
+     */
+    @Override
+    public synchronized String getCursiveFontFamily() {
+        return mCursiveFontFamily;
+    }
+
+    /**
+     * @see android.webkit.WebSettings#setFantasyFontFamily(java.lang.String)
+     */
+    @Override
+    public synchronized void setFantasyFontFamily(String font) {
+        if (font != null && !font.equals(mFantasyFontFamily)) {
+            mFantasyFontFamily = font;
+            postSync();
+        }
+    }
+
+    /**
+     * @see android.webkit.WebSettings#getFantasyFontFamily()
+     */
+    @Override
+    public synchronized String getFantasyFontFamily() {
+        return mFantasyFontFamily;
+    }
+
+    /**
+     * @see android.webkit.WebSettings#setMinimumFontSize(int)
+     */
+    @Override
+    public synchronized void setMinimumFontSize(int size) {
+        size = pin(size);
+        if (mMinimumFontSize != size) {
+            mMinimumFontSize = size;
+            postSync();
+        }
+    }
+
+    /**
+     * @see android.webkit.WebSettings#getMinimumFontSize()
+     */
+    @Override
+    public synchronized int getMinimumFontSize() {
+        return mMinimumFontSize;
+    }
+
+    /**
+     * @see android.webkit.WebSettings#setMinimumLogicalFontSize(int)
+     */
+    @Override
+    public synchronized void setMinimumLogicalFontSize(int size) {
+        size = pin(size);
+        if (mMinimumLogicalFontSize != size) {
+            mMinimumLogicalFontSize = size;
+            postSync();
+        }
+    }
+
+    /**
+     * @see android.webkit.WebSettings#getMinimumLogicalFontSize()
+     */
+    @Override
+    public synchronized int getMinimumLogicalFontSize() {
+        return mMinimumLogicalFontSize;
+    }
+
+    /**
+     * @see android.webkit.WebSettings#setDefaultFontSize(int)
+     */
+    @Override
+    public synchronized void setDefaultFontSize(int size) {
+        size = pin(size);
+        if (mDefaultFontSize != size) {
+            mDefaultFontSize = size;
+            postSync();
+        }
+    }
+
+    /**
+     * @see android.webkit.WebSettings#getDefaultFontSize()
+     */
+    @Override
+    public synchronized int getDefaultFontSize() {
+        return mDefaultFontSize;
+    }
+
+    /**
+     * @see android.webkit.WebSettings#setDefaultFixedFontSize(int)
+     */
+    @Override
+    public synchronized void setDefaultFixedFontSize(int size) {
+        size = pin(size);
+        if (mDefaultFixedFontSize != size) {
+            mDefaultFixedFontSize = size;
+            postSync();
+        }
+    }
+
+    /**
+     * @see android.webkit.WebSettings#getDefaultFixedFontSize()
+     */
+    @Override
+    public synchronized int getDefaultFixedFontSize() {
+        return mDefaultFixedFontSize;
+    }
+
+    /**
+     * Set the number of pages cached by the WebKit for the history navigation.
+     * @param size A non-negative integer between 0 (no cache) and 20 (max).
+     * @hide
+     */
+    public synchronized void setPageCacheCapacity(int size) {
+        if (size < 0) size = 0;
+        if (size > 20) size = 20;
+        if (mPageCacheCapacity != size) {
+            mPageCacheCapacity = size;
+            postSync();
+        }
+    }
+
+    /**
+     * @see android.webkit.WebSettings#setLoadsImagesAutomatically(boolean)
+     */
+    @Override
+    public synchronized void setLoadsImagesAutomatically(boolean flag) {
+        if (mLoadsImagesAutomatically != flag) {
+            mLoadsImagesAutomatically = flag;
+            postSync();
+        }
+    }
+
+    /**
+     * @see android.webkit.WebSettings#getLoadsImagesAutomatically()
+     */
+    @Override
+    public synchronized boolean getLoadsImagesAutomatically() {
+        return mLoadsImagesAutomatically;
+    }
+
+    /**
+     * @see android.webkit.WebSettings#setBlockNetworkImage(boolean)
+     */
+    @Override
+    public synchronized void setBlockNetworkImage(boolean flag) {
+        if (mBlockNetworkImage != flag) {
+            mBlockNetworkImage = flag;
+            postSync();
+        }
+    }
+
+    /**
+     * @see android.webkit.WebSettings#getBlockNetworkImage()
+     */
+    @Override
+    public synchronized boolean getBlockNetworkImage() {
+        return mBlockNetworkImage;
+    }
+
+    /**
+     * @see android.webkit.WebSettings#setBlockNetworkLoads(boolean)
+     */
+    @Override
+    public synchronized void setBlockNetworkLoads(boolean flag) {
+        if (mBlockNetworkLoads != flag) {
+            mBlockNetworkLoads = flag;
+            verifyNetworkAccess();
+            postSync();
+        }
+    }
+
+    /**
+     * @see android.webkit.WebSettings#getBlockNetworkLoads()
+     */
+    @Override
+    public synchronized boolean getBlockNetworkLoads() {
+        return mBlockNetworkLoads;
+    }
+
+
+    private void verifyNetworkAccess() {
+        if (!mBlockNetworkLoads) {
+            if (mContext.checkPermission("android.permission.INTERNET",
+                    android.os.Process.myPid(), android.os.Process.myUid()) !=
+                        PackageManager.PERMISSION_GRANTED) {
+                throw new SecurityException
+                        ("Permission denied - " +
+                                "application missing INTERNET permission");
+            }
+        }
+    }
+
+    /**
+     * @see android.webkit.WebSettings#setJavaScriptEnabled(boolean)
+     */
+    @Override
+    public synchronized void setJavaScriptEnabled(boolean flag) {
+        if (mJavaScriptEnabled != flag) {
+            mJavaScriptEnabled = flag;
+            postSync();
+        }
+    }
+
+    /**
+     * Tell the WebView to use Skia's hardware accelerated rendering path
+     * @param flag True if the WebView should use Skia's hw-accel path
+     * @hide
+     */
+    public synchronized void setHardwareAccelSkiaEnabled(boolean flag) {
+        if (mHardwareAccelSkia != flag) {
+            mHardwareAccelSkia = flag;
+            postSync();
+        }
+    }
+
+    /**
+     * @return True if the WebView is using hardware accelerated skia
+     * @hide
+     */
+    public synchronized boolean getHardwareAccelSkiaEnabled() {
+        return mHardwareAccelSkia;
+    }
+
+    /**
+     * Tell the WebView to show the visual indicator
+     * @param flag True if the WebView should show the visual indicator
+     * @hide
+     */
+    public synchronized void setShowVisualIndicator(boolean flag) {
+        if (mShowVisualIndicator != flag) {
+            mShowVisualIndicator = flag;
+            postSync();
+        }
+    }
+
+    /**
+     * @return True if the WebView is showing the visual indicator
+     * @hide
+     */
+    public synchronized boolean getShowVisualIndicator() {
+        return mShowVisualIndicator;
+    }
+
+    /**
+     * @see android.webkit.WebSettings#setPluginsEnabled(boolean)
+     */
+    @Override
+    @Deprecated
+    public synchronized void setPluginsEnabled(boolean flag) {
+        setPluginState(flag ? PluginState.ON : PluginState.OFF);
+    }
+
+    /**
+     * @see android.webkit.WebSettings#setPluginState(android.webkit.WebSettingsClassic.PluginState)
+     */
+    @Override
+    public synchronized void setPluginState(PluginState state) {
+        if (mPluginState != state) {
+            mPluginState = state;
+            postSync();
+        }
+    }
+
+    /**
+     * @see android.webkit.WebSettings#setPluginsPath(java.lang.String)
+     */
+    @Override
+    @Deprecated
+    public synchronized void setPluginsPath(String pluginsPath) {
+    }
+
+    /**
+     * @see android.webkit.WebSettings#setDatabasePath(java.lang.String)
+     */
+    @Override
+    public synchronized void setDatabasePath(String databasePath) {
+        if (databasePath != null && !mDatabasePathHasBeenSet) {
+            mDatabasePath = databasePath;
+            mDatabasePathHasBeenSet = true;
+            postSync();
+        }
+    }
+
+    /**
+     * @see android.webkit.WebSettings#setGeolocationDatabasePath(java.lang.String)
+     */
+    @Override
+    public synchronized void setGeolocationDatabasePath(String databasePath) {
+        if (databasePath != null
+                && !databasePath.equals(mGeolocationDatabasePath)) {
+            mGeolocationDatabasePath = databasePath;
+            postSync();
+        }
+    }
+
+    /**
+     * @see android.webkit.WebSettings#setAppCacheEnabled(boolean)
+     */
+    @Override
+    public synchronized void setAppCacheEnabled(boolean flag) {
+        if (mAppCacheEnabled != flag) {
+            mAppCacheEnabled = flag;
+            postSync();
+        }
+    }
+
+    /**
+     * @see android.webkit.WebSettings#setAppCachePath(java.lang.String)
+     */
+    @Override
+    public synchronized void setAppCachePath(String path) {
+        // We test for a valid path and for repeated setting on the native
+        // side, but we can avoid syncing in some simple cases. 
+        if (mAppCachePath == null && path != null && !path.isEmpty()) {
+            mAppCachePath = path;
+            postSync();
+        }
+    }
+
+    /**
+     * @see android.webkit.WebSettings#setAppCacheMaxSize(long)
+     */
+    @Override
+    public synchronized void setAppCacheMaxSize(long appCacheMaxSize) {
+        if (appCacheMaxSize != mAppCacheMaxSize) {
+            mAppCacheMaxSize = appCacheMaxSize;
+            postSync();
+        }
+    }
+
+    /**
+     * @see android.webkit.WebSettings#setDatabaseEnabled(boolean)
+     */
+    @Override
+    public synchronized void setDatabaseEnabled(boolean flag) {
+       if (mDatabaseEnabled != flag) {
+           mDatabaseEnabled = flag;
+           postSync();
+       }
+    }
+
+    /**
+     * @see android.webkit.WebSettings#setDomStorageEnabled(boolean)
+     */
+    @Override
+    public synchronized void setDomStorageEnabled(boolean flag) {
+       if (mDomStorageEnabled != flag) {
+           mDomStorageEnabled = flag;
+           postSync();
+       }
+    }
+
+    /**
+     * @see android.webkit.WebSettings#getDomStorageEnabled()
+     */
+    @Override
+    public synchronized boolean getDomStorageEnabled() {
+       return mDomStorageEnabled;
+    }
+
+    /**
+     * @see android.webkit.WebSettings#getDatabasePath()
+     */
+    @Override
+    public synchronized String getDatabasePath() {
+        return mDatabasePath;
+    }
+
+    /**
+     * @see android.webkit.WebSettings#getDatabaseEnabled()
+     */
+    @Override
+    public synchronized boolean getDatabaseEnabled() {
+        return mDatabaseEnabled;
+    }
+
+    /**
+     * Tell the WebView to enable WebWorkers API.
+     * @param flag True if the WebView should enable WebWorkers.
+     * Note that this flag only affects V8. JSC does not have
+     * an equivalent setting.
+     * @hide
+     */
+    public synchronized void setWorkersEnabled(boolean flag) {
+        if (mWorkersEnabled != flag) {
+            mWorkersEnabled = flag;
+            postSync();
+        }
+    }
+
+    /**
+     * @see android.webkit.WebSettings#setGeolocationEnabled(boolean)
+     */
+    @Override
+    public synchronized void setGeolocationEnabled(boolean flag) {
+        if (mGeolocationEnabled != flag) {
+            mGeolocationEnabled = flag;
+            postSync();
+        }
+    }
+
+    /**
+     * Sets whether XSS Auditor is enabled.
+     * @param flag Whether XSS Auditor should be enabled.
+     * @hide Only used by LayoutTestController.
+     */
+    public synchronized void setXSSAuditorEnabled(boolean flag) {
+        if (mXSSAuditorEnabled != flag) {
+            mXSSAuditorEnabled = flag;
+            postSync();
+        }
+    }
+
+    /**
+     * @see android.webkit.WebSettings#getJavaScriptEnabled()
+     */
+    @Override
+    public synchronized boolean getJavaScriptEnabled() {
+        return mJavaScriptEnabled;
+    }
+
+    /**
+     * @see android.webkit.WebSettings#getPluginsEnabled()
+     */
+    @Override
+    @Deprecated
+    public synchronized boolean getPluginsEnabled() {
+        return mPluginState == PluginState.ON;
+    }
+
+    /**
+     * @see android.webkit.WebSettings#getPluginState()
+     */
+    @Override
+    public synchronized PluginState getPluginState() {
+        return mPluginState;
+    }
+
+    /**
+     * @see android.webkit.WebSettings#getPluginsPath()
+     */
+    @Override
+    @Deprecated
+    public synchronized String getPluginsPath() {
+        return "";
+    }
+
+    /**
+     * @see android.webkit.WebSettings#setJavaScriptCanOpenWindowsAutomatically(boolean)
+     */
+    @Override
+    public synchronized void setJavaScriptCanOpenWindowsAutomatically(
+            boolean flag) {
+        if (mJavaScriptCanOpenWindowsAutomatically != flag) {
+            mJavaScriptCanOpenWindowsAutomatically = flag;
+            postSync();
+        }
+    }
+
+    /**
+     * @see android.webkit.WebSettings#getJavaScriptCanOpenWindowsAutomatically()
+     */
+    @Override
+    public synchronized boolean getJavaScriptCanOpenWindowsAutomatically() {
+        return mJavaScriptCanOpenWindowsAutomatically;
+    }
+
+    /**
+     * @see android.webkit.WebSettings#setDefaultTextEncodingName(java.lang.String)
+     */
+    @Override
+    public synchronized void setDefaultTextEncodingName(String encoding) {
+        if (encoding != null && !encoding.equals(mDefaultTextEncoding)) {
+            mDefaultTextEncoding = encoding;
+            postSync();
+        }
+    }
+
+    /**
+     * @see android.webkit.WebSettings#getDefaultTextEncodingName()
+     */
+    @Override
+    public synchronized String getDefaultTextEncodingName() {
+        return mDefaultTextEncoding;
+    }
+
+    /**
+     * @see android.webkit.WebSettings#setUserAgentString(java.lang.String)
+     */
+    @Override
+    public synchronized void setUserAgentString(String ua) {
+        if (ua == null || ua.length() == 0) {
+            synchronized(sLockForLocaleSettings) {
+                Locale currentLocale = Locale.getDefault();
+                if (!sLocale.equals(currentLocale)) {
+                    sLocale = currentLocale;
+                    mAcceptLanguage = getCurrentAcceptLanguage();
+                }
+            }
+            ua = getCurrentUserAgent();
+            mUseDefaultUserAgent = true;
+        } else  {
+            mUseDefaultUserAgent = false;
+        }
+
+        if (!ua.equals(mUserAgent)) {
+            mUserAgent = ua;
+            postSync();
+        }
+    }
+
+    /**
+     * @see android.webkit.WebSettings#getUserAgentString()
+     */
+    @Override
+    public synchronized String getUserAgentString() {
+        if (DESKTOP_USERAGENT.equals(mUserAgent) ||
+                IPHONE_USERAGENT.equals(mUserAgent) ||
+                !mUseDefaultUserAgent) {
+            return mUserAgent;
+        }
+
+        boolean doPostSync = false;
+        synchronized(sLockForLocaleSettings) {
+            Locale currentLocale = Locale.getDefault();
+            if (!sLocale.equals(currentLocale)) {
+                sLocale = currentLocale;
+                mUserAgent = getCurrentUserAgent();
+                mAcceptLanguage = getCurrentAcceptLanguage();
+                doPostSync = true;
+            }
+        }
+        if (doPostSync) {
+            postSync();
+        }
+        return mUserAgent;
+    }
+
+    /* package api to grab the Accept Language string. */
+    /*package*/ synchronized String getAcceptLanguage() {
+        synchronized(sLockForLocaleSettings) {
+            Locale currentLocale = Locale.getDefault();
+            if (!sLocale.equals(currentLocale)) {
+                sLocale = currentLocale;
+                mAcceptLanguage = getCurrentAcceptLanguage();
+            }
+        }
+        return mAcceptLanguage;
+    }
+
+    /* package */ boolean isNarrowColumnLayout() {
+        return getLayoutAlgorithm() == LayoutAlgorithm.NARROW_COLUMNS;
+    }
+
+    /**
+     * @see android.webkit.WebSettings#setNeedInitialFocus(boolean)
+     */
+    @Override
+    public void setNeedInitialFocus(boolean flag) {
+        if (mNeedInitialFocus != flag) {
+            mNeedInitialFocus = flag;
+        }
+    }
+
+    /* Package api to get the choice whether it needs to set initial focus. */
+    /* package */ boolean getNeedInitialFocus() {
+        return mNeedInitialFocus;
+    }
+
+    /**
+     * @see android.webkit.WebSettings#setRenderPriority(android.webkit.WebSettingsClassic.RenderPriority)
+     */
+    @Override
+    public synchronized void setRenderPriority(RenderPriority priority) {
+        if (mRenderPriority != priority) {
+            mRenderPriority = priority;
+            mEventHandler.sendMessage(Message.obtain(null,
+                    EventHandler.PRIORITY));
+        }
+    }
+
+    /**
+     * @see android.webkit.WebSettings#setCacheMode(int)
+     */
+    @Override
+    public void setCacheMode(int mode) {
+        if (mode != mOverrideCacheMode) {
+            mOverrideCacheMode = mode;
+            postSync();
+        }
+    }
+
+    /**
+     * @see android.webkit.WebSettings#getCacheMode()
+     */
+    @Override
+    public int getCacheMode() {
+        return mOverrideCacheMode;
+    }
+
+    /**
+     * If set, webkit alternately shrinks and expands images viewed outside
+     * of an HTML page to fit the screen. This conflicts with attempts by
+     * the UI to zoom in and out of an image, so it is set false by default.
+     * @param shrink Set true to let webkit shrink the standalone image to fit.
+     * {@hide}
+     */
+    public void setShrinksStandaloneImagesToFit(boolean shrink) {
+        if (mShrinksStandaloneImagesToFit != shrink) {
+            mShrinksStandaloneImagesToFit = shrink;
+            postSync();
+        }
+     }
+
+    /**
+     * Specify the maximum decoded image size. The default is
+     * 2 megs for small memory devices and 8 megs for large memory devices.
+     * @param size The maximum decoded size, or zero to set to the default.
+     * @hide
+     */
+    public void setMaximumDecodedImageSize(long size) {
+        if (mMaximumDecodedImageSize != size) {
+            mMaximumDecodedImageSize = size;
+            postSync();
+        }
+    }
+
+    /**
+     * Returns whether to use fixed viewport.  Use fixed viewport
+     * whenever wide viewport is on.
+     */
+    /* package */ boolean getUseFixedViewport() {
+        return getUseWideViewPort();
+    }
+
+    /**
+     * Returns whether private browsing is enabled.
+     */
+    /* package */ boolean isPrivateBrowsingEnabled() {
+        return mPrivateBrowsingEnabled;
+    }
+
+    /**
+     * Sets whether private browsing is enabled.
+     * @param flag Whether private browsing should be enabled.
+     */
+    /* package */ synchronized void setPrivateBrowsingEnabled(boolean flag) {
+        if (mPrivateBrowsingEnabled != flag) {
+            mPrivateBrowsingEnabled = flag;
+
+            // AutoFill is dependant on private browsing being enabled so
+            // reset it to take account of the new value of mPrivateBrowsingEnabled.
+            setAutoFillEnabled(mAutoFillEnabled);
+
+            postSync();
+        }
+    }
+
+    /**
+     * Returns whether the viewport metatag can disable zooming
+     * @hide
+     */
+    public boolean forceUserScalable() {
+        return mForceUserScalable;
+    }
+
+    /**
+     * Sets whether viewport metatag can disable zooming.
+     * @param flag Whether or not to forceably enable user scalable.
+     * @hide
+     */
+    public synchronized void setForceUserScalable(boolean flag) {
+        mForceUserScalable = flag;
+    }
+
+    synchronized void setSyntheticLinksEnabled(boolean flag) {
+        if (mSyntheticLinksEnabled != flag) {
+            mSyntheticLinksEnabled = flag;
+            postSync();
+        }
+    }
+
+    /**
+     * @hide
+     */
+    public synchronized void setAutoFillEnabled(boolean enabled) {
+        // AutoFill is always disabled in private browsing mode.
+        boolean autoFillEnabled = enabled && !mPrivateBrowsingEnabled;
+        if (mAutoFillEnabled != autoFillEnabled) {
+            mAutoFillEnabled = autoFillEnabled;
+            postSync();
+        }
+    }
+
+    /**
+     * @hide
+     */
+    public synchronized boolean getAutoFillEnabled() {
+        return mAutoFillEnabled;
+    }
+
+    /**
+     * @hide
+     */
+    public synchronized void setAutoFillProfile(AutoFillProfile profile) {
+        if (mAutoFillProfile != profile) {
+            mAutoFillProfile = profile;
+            postSync();
+        }
+    }
+
+    /**
+     * @hide
+     */
+    public synchronized AutoFillProfile getAutoFillProfile() {
+        return mAutoFillProfile;
+    }
+
+    int getDoubleTapToastCount() {
+        return mDoubleTapToastCount;
+    }
+
+    void setDoubleTapToastCount(int count) {
+        if (mDoubleTapToastCount != count) {
+            mDoubleTapToastCount = count;
+            // write the settings in the non-UI thread
+            mEventHandler.sendMessage(Message.obtain(null,
+                    EventHandler.SET_DOUBLE_TAP_TOAST_COUNT));
+        }
+    }
+
+    /**
+     * @hide
+     */
+    public void setProperty(String key, String value) {
+        if (mWebView.nativeSetProperty(key, value)) {
+            mWebView.contentInvalidateAll();
+        }
+    }
+
+    /**
+     * @hide
+     */
+    public String getProperty(String key) {
+        return mWebView.nativeGetProperty(key);
+    }
+
+    /**
+     * Transfer messages from the queue to the new WebCoreThread. Called from
+     * WebCore thread.
+     */
+    /*package*/
+    synchronized void syncSettingsAndCreateHandler(BrowserFrame frame) {
+        mBrowserFrame = frame;
+        if (DebugFlags.WEB_SETTINGS) {
+            junit.framework.Assert.assertTrue(frame.mNativeFrame != 0);
+        }
+
+        SharedPreferences sp = mContext.getSharedPreferences(PREF_FILE,
+                Context.MODE_PRIVATE);
+        if (mDoubleTapToastCount > 0) {
+            mDoubleTapToastCount = sp.getInt(DOUBLE_TAP_TOAST_COUNT,
+                    mDoubleTapToastCount);
+        }
+        nativeSync(frame.mNativeFrame);
+        mSyncPending = false;
+        mEventHandler.createHandler();
+    }
+
+    /**
+     * Let the Settings object know that our owner is being destroyed.
+     */
+    /*package*/
+    synchronized void onDestroyed() {
+    }
+
+    private int pin(int size) {
+        // FIXME: 72 is just an arbitrary max text size value.
+        if (size < 1) {
+            return 1;
+        } else if (size > 72) {
+            return 72;
+        }
+        return size;
+    }
+
+    /* Post a SYNC message to handle syncing the native settings. */
+    private synchronized void postSync() {
+        // Only post if a sync is not pending
+        if (!mSyncPending) {
+            mSyncPending = mEventHandler.sendMessage(
+                    Message.obtain(null, EventHandler.SYNC));
+        }
+    }
+
+    // Synchronize the native and java settings.
+    private native void nativeSync(int nativeFrame);
+}
diff --git a/core/java/android/webkit/WebTextView.java b/core/java/android/webkit/WebTextView.java
index 510c168..911073d 100644
--- a/core/java/android/webkit/WebTextView.java
+++ b/core/java/android/webkit/WebTextView.java
@@ -16,148 +16,15 @@
 
 package android.webkit;
 
-import android.content.Context;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.ColorFilter;
-import android.graphics.Paint;
-import android.graphics.Paint.Style;
-import android.graphics.PixelFormat;
-import android.graphics.Rect;
-import android.graphics.drawable.ColorDrawable;
-import android.graphics.drawable.Drawable;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.Message;
-import android.os.ResultReceiver;
-import android.text.BoringLayout.Metrics;
-import android.text.DynamicLayout;
-import android.text.Editable;
-import android.text.InputFilter;
-import android.text.InputType;
-import android.text.Layout;
-import android.text.Selection;
-import android.text.Spannable;
-import android.text.TextPaint;
-import android.text.TextUtils;
-import android.text.method.MovementMethod;
-import android.text.method.Touch;
 import android.util.Log;
-import android.util.TypedValue;
-import android.view.Gravity;
-import android.view.KeyCharacterMap;
-import android.view.KeyEvent;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.ViewConfiguration;
-import android.view.ViewGroup;
-import android.view.inputmethod.EditorInfo;
-import android.view.inputmethod.InputConnection;
-import android.view.inputmethod.InputMethodManager;
-import android.widget.AbsoluteLayout.LayoutParams;
-import android.widget.AdapterView;
-import android.widget.ArrayAdapter;
-import android.widget.AutoCompleteTextView;
-import android.widget.TextView;
-
-import junit.framework.Assert;
 
 import java.net.MalformedURLException;
 import java.net.URL;
-import java.util.ArrayList;
 
-/**
- * WebTextView is a specialized version of EditText used by WebView
- * to overlay html textfields (and textareas) to use our standard
- * text editing.
- */
-/* package */ class WebTextView extends AutoCompleteTextView
-        implements AdapterView.OnItemClickListener {
+// TODO: Move these to a better place.
+/* package */ abstract class WebTextView {
 
-    static final String LOGTAG = "webtextview";
-
-    private int mRingInset;
-
-    private WebView         mWebView;
-    private boolean         mSingle;
-    private int             mWidthSpec;
-    private int             mHeightSpec;
-    private int             mNodePointer;
-    // FIXME: This is a hack for blocking unmatched key ups, in particular
-    // on the enter key.  The method for blocking unmatched key ups prevents
-    // the shift key from working properly.
-    private boolean         mGotEnterDown;
-    private int             mMaxLength;
-    // Keep track of the text before the change so we know whether we actually
-    // need to send down the DOM events.
-    private String          mPreChange;
-    // Variables for keeping track of the touch down, to send to the WebView
-    // when a drag starts
-    private float           mDragStartX;
-    private float           mDragStartY;
-    private long            mDragStartTime;
-    private boolean         mDragSent;
-    // True if the most recent drag event has caused either the TextView to
-    // scroll or the web page to scroll.  Gets reset after a touch down.
-    private boolean         mScrolled;
-    // Whether or not a selection change was generated from webkit.  If it was,
-    // we do not need to pass the selection back to webkit.
-    private boolean         mFromWebKit;
-    // Whether or not a selection change was generated from the WebTextView
-    // gaining focus.  If it is, we do not want to pass it to webkit.  This
-    // selection comes from the MovementMethod, but we behave differently.  If
-    // WebTextView gained focus from a touch, webkit will determine the
-    // selection.
-    private boolean         mFromFocusChange;
-    // Whether or not a selection change was generated from setInputType.  We
-    // do not want to pass this change to webkit.
-    private boolean         mFromSetInputType;
-    private boolean         mGotTouchDown;
-    // Keep track of whether a long press has happened.  Only meaningful after
-    // an ACTION_DOWN MotionEvent
-    private boolean         mHasPerformedLongClick;
-    private boolean         mInSetTextAndKeepSelection;
-    // Array to store the final character added in onTextChanged, so that its
-    // KeyEvents may be determined.
-    private char[]          mCharacter = new char[1];
-    // This is used to reset the length filter when on a textfield
-    // with no max length.
-    // FIXME: This can be replaced with TextView.NO_FILTERS if that
-    // is made public/protected.
-    private static final InputFilter[] NO_FILTERS = new InputFilter[0];
-    // For keeping track of the fact that the delete key was pressed, so
-    // we can simply pass a delete key instead of calling deleteSelection.
-    private boolean mGotDelete;
-    private int mDelSelStart;
-    private int mDelSelEnd;
-
-    // Keep in sync with native constant in
-    // external/webkit/WebKit/android/WebCoreSupport/autofill/WebAutoFill.cpp
-    /* package */ static final int FORM_NOT_AUTOFILLABLE = -1;
-
-    private boolean mAutoFillable; // Is this textview part of an autofillable form?
-    private int mQueryId;
-    private boolean mAutoFillProfileIsSet;
-    // Used to determine whether onFocusChanged was called as a result of
-    // calling remove().
-    private boolean mInsideRemove;
-    private class MyResultReceiver extends ResultReceiver {
-        @Override
-        protected void onReceiveResult(int resultCode, Bundle resultData) {
-            if (resultCode == InputMethodManager.RESULT_SHOWN
-                    && mWebView != null) {
-                mWebView.revealSelection();
-            }
-        }
-
-        /**
-         * @param handler
-         */
-        public MyResultReceiver(Handler handler) {
-            super(handler);
-        }
-    }
-    private MyResultReceiver mReceiver;
+    private static final String LOGTAG = "WebTextView";
 
     // Types used with setType.  Keep in sync with CachedInput.h
     static final int NORMAL_TEXT_FIELD = 0;
@@ -169,1006 +36,7 @@
     static final int TELEPHONE = 6;
     static final int URL = 7;
 
-    private static final int AUTOFILL_FORM = 100;
-    private Handler mHandler;
-
-    /**
-     * Create a new WebTextView.
-     * @param   context The Context for this WebTextView.
-     * @param   webView The WebView that created this.
-     */
-    /* package */ WebTextView(Context context, WebView webView, int autoFillQueryId) {
-        super(context, null, com.android.internal.R.attr.webTextViewStyle);
-        mWebView = webView;
-        mMaxLength = -1;
-        setAutoFillable(autoFillQueryId);
-        // Turn on subpixel text, and turn off kerning, so it better matches
-        // the text in webkit.
-        TextPaint paint = getPaint();
-        int flags = paint.getFlags() & ~Paint.DEV_KERN_TEXT_FLAG
-                | Paint.SUBPIXEL_TEXT_FLAG | Paint.DITHER_FLAG;
-        paint.setFlags(flags);
-
-        // Set the text color to black, regardless of the theme.  This ensures
-        // that other applications that use embedded WebViews will properly
-        // display the text in password textfields.
-        setTextColor(DebugFlags.DRAW_WEBTEXTVIEW ? Color.RED : Color.BLACK);
-        setBackgroundDrawable(DebugFlags.DRAW_WEBTEXTVIEW ? null : new ColorDrawable(Color.WHITE));
-
-        // This helps to align the text better with the text in the web page.
-        setIncludeFontPadding(false);
-
-        mHandler = new Handler() {
-            @Override
-            public void handleMessage(Message msg) {
-                switch (msg.what) {
-                case AUTOFILL_FORM:
-                    mWebView.autoFillForm(mQueryId);
-                    break;
-                }
-            }
-        };
-        mReceiver = new MyResultReceiver(mHandler);
-        float ringWidth = 2f * context.getResources().getDisplayMetrics().density;
-        mRingInset = (int) ringWidth;
-        setBackgroundDrawable(new BackgroundDrawable(mRingInset));
-        setPadding(getPaddingLeft(), getPaddingTop(), getPaddingRight(),
-                getPaddingBottom());
-    }
-
-    private static class BackgroundDrawable extends Drawable {
-
-        private Paint mPaint = new Paint();
-        private int mBorderWidth;
-        private Rect mInsetRect = new Rect();
-
-        public BackgroundDrawable(int width) {
-            mPaint = new Paint();
-            mPaint.setStrokeWidth(width);
-            mBorderWidth = width;
-        }
-
-        @Override
-        public void draw(Canvas canvas) {
-            mPaint.setColor(0x6633b5e5);
-            canvas.drawRect(getBounds(), mPaint);
-            mInsetRect.left = getBounds().left + mBorderWidth;
-            mInsetRect.top = getBounds().top + mBorderWidth;
-            mInsetRect.right = getBounds().right - mBorderWidth;
-            mInsetRect.bottom = getBounds().bottom - mBorderWidth;
-            mPaint.setColor(Color.WHITE);
-            canvas.drawRect(mInsetRect, mPaint);
-        }
-
-        @Override
-        public void setAlpha(int alpha) {
-        }
-
-        @Override
-        public void setColorFilter(ColorFilter cf) {
-        }
-
-        @Override
-        public int getOpacity() {
-            return PixelFormat.TRANSLUCENT;
-        }
-
-    }
-
-    public void setAutoFillable(int queryId) {
-        mAutoFillable = mWebView.getSettings().getAutoFillEnabled()
-                && (queryId != FORM_NOT_AUTOFILLABLE);
-        mQueryId = queryId;
-    }
-
-    @Override
-    public void setPadding(int left, int top, int right, int bottom) {
-        super.setPadding(left + mRingInset, top + mRingInset,
-                right + mRingInset, bottom + mRingInset);
-    }
-
-    @Override
-    public boolean dispatchKeyEvent(KeyEvent event) {
-        if (event.isSystem()) {
-            return super.dispatchKeyEvent(event);
-        }
-        // Treat ACTION_DOWN and ACTION MULTIPLE the same
-        boolean down = event.getAction() != KeyEvent.ACTION_UP;
-        int keyCode = event.getKeyCode();
-
-        boolean isArrowKey = false;
-        switch(keyCode) {
-            case KeyEvent.KEYCODE_DPAD_LEFT:
-            case KeyEvent.KEYCODE_DPAD_RIGHT:
-            case KeyEvent.KEYCODE_DPAD_UP:
-            case KeyEvent.KEYCODE_DPAD_DOWN:
-                isArrowKey = true;
-                break;
-        }
-
-        if (KeyEvent.KEYCODE_TAB == keyCode) {
-            if (down) {
-                onEditorAction(EditorInfo.IME_ACTION_NEXT);
-            }
-            return true;
-        }
-        Spannable text = (Spannable) getText();
-        int oldStart = Selection.getSelectionStart(text);
-        int oldEnd = Selection.getSelectionEnd(text);
-        // Normally the delete key's dom events are sent via onTextChanged.
-        // However, if the cursor is at the beginning of the field, which
-        // includes the case where it has zero length, then the text is not
-        // changed, so send the events immediately.
-        if (KeyEvent.KEYCODE_DEL == keyCode) {
-            if (oldStart == 0 && oldEnd == 0) {
-                sendDomEvent(event);
-                return true;
-            }
-            if (down) {
-                mGotDelete = true;
-                mDelSelStart = oldStart;
-                mDelSelEnd = oldEnd;
-            }
-        }
-
-        if (mSingle && (KeyEvent.KEYCODE_ENTER == keyCode
-                    || KeyEvent.KEYCODE_NUMPAD_ENTER == keyCode)) {
-            if (isPopupShowing()) {
-                return super.dispatchKeyEvent(event);
-            }
-            if (!down) {
-                // Hide the keyboard, since the user has just submitted this
-                // form.  The submission happens thanks to the two calls
-                // to sendDomEvent.
-                InputMethodManager.getInstance(mContext)
-                        .hideSoftInputFromWindow(getWindowToken(), 0);
-                sendDomEvent(new KeyEvent(KeyEvent.ACTION_DOWN, keyCode));
-                sendDomEvent(event);
-            }
-            return super.dispatchKeyEvent(event);
-        } else if (KeyEvent.KEYCODE_DPAD_CENTER == keyCode) {
-            // Note that this handles center key and trackball.
-            if (isPopupShowing()) {
-                return super.dispatchKeyEvent(event);
-            }
-            // Center key should be passed to a potential onClick
-            if (!down) {
-                mWebView.centerKeyPressOnTextField();
-            }
-            // Pass to super to handle longpress.
-            return super.dispatchKeyEvent(event);
-        }
-
-        // Ensure there is a layout so arrow keys are handled properly.
-        if (getLayout() == null) {
-            measure(mWidthSpec, mHeightSpec);
-        }
-
-        int oldLength = text.length();
-        boolean maxedOut = mMaxLength != -1 && oldLength == mMaxLength;
-        // If we are at max length, and there is a selection rather than a
-        // cursor, we need to store the text to compare later, since the key
-        // may have changed the string.
-        String oldText;
-        if (maxedOut && oldEnd != oldStart) {
-            oldText = text.toString();
-        } else {
-            oldText = "";
-        }
-        if (super.dispatchKeyEvent(event)) {
-            // If the WebTextView handled the key it was either an alphanumeric
-            // key, a delete, or a movement within the text. All of those are
-            // ok to pass to javascript.
-
-            // UNLESS there is a max length determined by the html.  In that
-            // case, if the string was already at the max length, an
-            // alphanumeric key will be erased by the LengthFilter,
-            // so do not pass down to javascript, and instead
-            // return true.  If it is an arrow key or a delete key, we can go
-            // ahead and pass it down.
-            if (KeyEvent.KEYCODE_ENTER == keyCode
-                        || KeyEvent.KEYCODE_NUMPAD_ENTER == keyCode) {
-                // For multi-line text boxes, newlines will
-                // trigger onTextChanged for key down (which will send both
-                // key up and key down) but not key up.
-                mGotEnterDown = true;
-            }
-            if (maxedOut && !isArrowKey && keyCode != KeyEvent.KEYCODE_DEL) {
-                if (oldEnd == oldStart) {
-                    // Return true so the key gets dropped.
-                    return true;
-                } else if (!oldText.equals(getText().toString())) {
-                    // FIXME: This makes the text work properly, but it
-                    // does not pass down the key event, so it may not
-                    // work for a textfield that has the type of
-                    // behavior of GoogleSuggest.  That said, it is
-                    // unlikely that a site would combine the two in
-                    // one textfield.
-                    Spannable span = (Spannable) getText();
-                    int newStart = Selection.getSelectionStart(span);
-                    int newEnd = Selection.getSelectionEnd(span);
-                    mWebView.replaceTextfieldText(0, oldLength, span.toString(),
-                            newStart, newEnd);
-                    return true;
-                }
-            }
-            /* FIXME:
-             * In theory, we would like to send the events for the arrow keys.
-             * However, the TextView can arbitrarily change the selection (i.e.
-             * long press followed by using the trackball).  Therefore, we keep
-             * in sync with the TextView via onSelectionChanged.  If we also
-             * send the DOM event, we lose the correct selection.
-            if (isArrowKey) {
-                // Arrow key does not change the text, but we still want to send
-                // the DOM events.
-                sendDomEvent(event);
-            }
-             */
-            return true;
-        }
-        // Ignore the key up event for newlines. This prevents
-        // multiple newlines in the native textarea.
-        if (mGotEnterDown && !down) {
-            return true;
-        }
-        // if it is a navigation key, pass it to WebView
-        if (isArrowKey) {
-            // WebView check the trackballtime in onKeyDown to avoid calling
-            // native from both trackball and key handling. As this is called
-            // from WebTextView, we always want WebView to check with native.
-            // Reset trackballtime to ensure it.
-            mWebView.resetTrackballTime();
-            return down ? mWebView.onKeyDown(keyCode, event) : mWebView
-                    .onKeyUp(keyCode, event);
-        }
-        return false;
-    }
-
-    void ensureLayout() {
-        if (getLayout() == null) {
-            // Ensure we have a Layout
-            measure(mWidthSpec, mHeightSpec);
-            LayoutParams params = (LayoutParams) getLayoutParams();
-            if (params != null) {
-                layout(params.x, params.y, params.x + params.width,
-                        params.y + params.height);
-            }
-        }
-    }
-
-    /* package */ ResultReceiver getResultReceiver() { return mReceiver; }
-
-    /**
-     *  Determine whether this WebTextView currently represents the node
-     *  represented by ptr.
-     *  @param  ptr Pointer to a node to compare to.
-     *  @return boolean Whether this WebTextView already represents the node
-     *          pointed to by ptr.
-     */
-    /* package */ boolean isSameTextField(int ptr) {
-        return ptr == mNodePointer;
-    }
-
-    /**
-     * Ensure that the underlying text field/area is lined up with the WebTextView.
-     */
-    private void lineUpScroll() {
-        Layout layout = getLayout();
-        if (mWebView != null && layout != null) {
-            if (mSingle) {
-                // textfields only need to be lined up horizontally.
-                float maxScrollX = layout.getLineRight(0) - getWidth();
-                if (DebugFlags.WEB_TEXT_VIEW) {
-                    Log.v(LOGTAG, "onTouchEvent x=" + mScrollX + " y="
-                            + mScrollY + " maxX=" + maxScrollX);
-                }
-                mWebView.scrollFocusedTextInputX(maxScrollX > 0 ?
-                        mScrollX / maxScrollX : 0);
-            } else {
-                // textareas only need to be lined up vertically.
-                mWebView.scrollFocusedTextInputY(mScrollY);
-            }
-        }
-    }
-
-    @Override
-    protected void makeNewLayout(int w, int hintWidth, Metrics boring,
-            Metrics hintBoring, int ellipsisWidth, boolean bringIntoView) {
-        // Necessary to get a Layout to work with, and to do the other work that
-        // makeNewLayout does.
-        super.makeNewLayout(w, hintWidth, boring, hintBoring, ellipsisWidth,
-                bringIntoView);
-        lineUpScroll();
-    }
-
-    /**
-     * Custom layout which figures out its line spacing.  If -1 is passed in for
-     * the height, it will use the ascent and descent from the paint to
-     * determine the line spacing.  Otherwise it will use the spacing provided.
-     */
-    private static class WebTextViewLayout extends DynamicLayout {
-        private float mLineHeight;
-        private float mDifference;
-        public WebTextViewLayout(CharSequence base, CharSequence display,
-                TextPaint paint,
-                int width, Alignment align,
-                float spacingMult, float spacingAdd,
-                boolean includepad,
-                TextUtils.TruncateAt ellipsize, int ellipsizedWidth,
-                float lineHeight) {
-            super(base, display, paint, width, align, spacingMult, spacingAdd,
-                    includepad, ellipsize, ellipsizedWidth);
-            float paintLineHeight = paint.descent() - paint.ascent();
-            if (lineHeight == -1f) {
-                mLineHeight = paintLineHeight;
-                mDifference = 0f;
-            } else {
-                mLineHeight = lineHeight;
-                // Through trial and error, I found this calculation to improve
-                // the accuracy of line placement.
-                mDifference = (lineHeight - paintLineHeight) / 2;
-            }
-        }
-
-        @Override
-        public int getLineTop(int line) {
-            return Math.round(mLineHeight * line - mDifference);
-        }
-    }
-
-    @Override public InputConnection onCreateInputConnection(
-            EditorInfo outAttrs) {
-        InputConnection connection = super.onCreateInputConnection(outAttrs);
-        if (mWebView != null) {
-            // Use the name of the textfield + the url.  Use backslash as an
-            // arbitrary separator.
-            outAttrs.fieldName = mWebView.nativeFocusCandidateName() + "\\"
-                    + mWebView.getUrl();
-        }
-        return connection;
-    }
-
-    @Override
-    public void onEditorAction(int actionCode) {
-        switch (actionCode) {
-        case EditorInfo.IME_ACTION_NEXT:
-            if (mWebView.nativeMoveCursorToNextTextInput()) {
-                // Preemptively rebuild the WebTextView, so that the action will
-                // be set properly.
-                mWebView.rebuildWebTextView();
-                setDefaultSelection();
-                mWebView.invalidate();
-            }
-            break;
-        case EditorInfo.IME_ACTION_DONE:
-            super.onEditorAction(actionCode);
-            break;
-        case EditorInfo.IME_ACTION_GO:
-        case EditorInfo.IME_ACTION_SEARCH:
-            // Send an enter and hide the soft keyboard
-            InputMethodManager.getInstance(mContext)
-                    .hideSoftInputFromWindow(getWindowToken(), 0);
-            sendDomEvent(new KeyEvent(KeyEvent.ACTION_DOWN,
-                    KeyEvent.KEYCODE_ENTER));
-            sendDomEvent(new KeyEvent(KeyEvent.ACTION_UP,
-                    KeyEvent.KEYCODE_ENTER));
-
-        default:
-            break;
-        }
-    }
-
-    @Override
-    protected void onFocusChanged(boolean focused, int direction,
-            Rect previouslyFocusedRect) {
-        mFromFocusChange = true;
-        super.onFocusChanged(focused, direction, previouslyFocusedRect);
-        if (focused) {
-            mWebView.setActive(true);
-        } else if (!mInsideRemove) {
-            mWebView.setActive(false);
-        }
-        mFromFocusChange = false;
-    }
-
-    // AdapterView.OnItemClickListener implementation
-
-    @Override
-    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
-        if (id == 0 && position == 0) {
-            // Blank out the text box while we wait for WebCore to fill the form.
-            replaceText("");
-            WebSettings settings = mWebView.getSettings();
-            if (mAutoFillProfileIsSet) {
-                // Call a webview method to tell WebCore to autofill the form.
-                mWebView.autoFillForm(mQueryId);
-            } else {
-                // There is no autofill profile setup yet and the user has
-                // elected to try and set one up. Call through to the
-                // embedder to action that.
-                mWebView.getWebChromeClient().setupAutoFill(
-                        mHandler.obtainMessage(AUTOFILL_FORM));
-            }
-        }
-    }
-
-    @Override
-    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
-        super.onScrollChanged(l, t, oldl, oldt);
-        lineUpScroll();
-    }
-
-    @Override
-    protected void onSelectionChanged(int selStart, int selEnd) {
-        if (!mFromWebKit && !mFromFocusChange && !mFromSetInputType
-                && mWebView != null && !mInSetTextAndKeepSelection) {
-            if (DebugFlags.WEB_TEXT_VIEW) {
-                Log.v(LOGTAG, "onSelectionChanged selStart=" + selStart
-                        + " selEnd=" + selEnd);
-            }
-            mWebView.setSelection(selStart, selEnd);
-            lineUpScroll();
-        }
-    }
-
-    @Override
-    protected void onTextChanged(CharSequence s,int start,int before,int count){
-        super.onTextChanged(s, start, before, count);
-        String postChange = s.toString();
-        // Prevent calls to setText from invoking onTextChanged (since this will
-        // mean we are on a different textfield).  Also prevent the change when
-        // going from a textfield with a string of text to one with a smaller
-        // limit on text length from registering the onTextChanged event.
-        if (mPreChange == null || mPreChange.equals(postChange) ||
-                (mMaxLength > -1 && mPreChange.length() > mMaxLength &&
-                mPreChange.substring(0, mMaxLength).equals(postChange))) {
-            return;
-        }
-        if (0 == count) {
-            if (before > 0) {
-                // For this and all changes to the text, update our cache
-                updateCachedTextfield();
-                if (mGotDelete) {
-                    mGotDelete = false;
-                    int oldEnd = start + before;
-                    if (mDelSelEnd == oldEnd
-                            && (mDelSelStart == start
-                            || (mDelSelStart == oldEnd && before == 1))) {
-                        // If the selection is set up properly before the
-                        // delete, send the DOM events.
-                        sendDomEvent(new KeyEvent(KeyEvent.ACTION_DOWN,
-                                KeyEvent.KEYCODE_DEL));
-                        sendDomEvent(new KeyEvent(KeyEvent.ACTION_UP,
-                                KeyEvent.KEYCODE_DEL));
-                        return;
-                    }
-                }
-                // This was simply a delete or a cut, so just delete the
-                // selection.
-                mWebView.deleteSelection(start, start + before);
-            }
-            mGotDelete = false;
-            // before should never be negative, so whether it was a cut
-            // (handled above), or before is 0, in which case nothing has
-            // changed, we should return.
-            return;
-        }
-        // Ensure that this flag gets cleared, since with autocorrect on, a
-        // delete key press may have a more complex result than deleting one
-        // character or the existing selection, so it will not get cleared
-        // above.
-        mGotDelete = false;
-        // Prefer sending javascript events, so when adding one character,
-        // don't replace the unchanged text.
-        if (count > 1 && before == count - 1) {
-            String replaceButOne =  mPreChange.subSequence(start,
-                    start + before).toString();
-            String replacedString = s.subSequence(start,
-                    start + before).toString();
-            if (replaceButOne.equals(replacedString)) {
-                // we're just adding one character
-                start += before;
-                before = 0;
-                count = 1;
-            }
-        }
-        mPreChange = postChange;
-        // Find the last character being replaced.  If it can be represented by
-        // events, we will pass them to native so we can see javascript events.
-        // Otherwise, replace the text being changed in the textfield.
-        KeyEvent[] events = null;
-        if (count == 1) {
-            TextUtils.getChars(s, start + count - 1, start + count, mCharacter, 0);
-            KeyCharacterMap kmap = KeyCharacterMap.load(KeyCharacterMap.VIRTUAL_KEYBOARD);
-            events = kmap.getEvents(mCharacter);
-        }
-        boolean useKeyEvents = (events != null);
-        if (useKeyEvents) {
-            // This corrects the selection which may have been affected by the
-            // trackball or auto-correct.
-            if (DebugFlags.WEB_TEXT_VIEW) {
-                Log.v(LOGTAG, "onTextChanged start=" + start
-                        + " start + before=" + (start + before));
-            }
-            if (!mInSetTextAndKeepSelection) {
-                mWebView.setSelection(start, start + before);
-            }
-            int length = events.length;
-            for (int i = 0; i < length; i++) {
-                // We never send modifier keys to native code so don't send them
-                // here either.
-                if (!KeyEvent.isModifierKey(events[i].getKeyCode())) {
-                    sendDomEvent(events[i]);
-                }
-            }
-        } else {
-            String replace = s.subSequence(start,
-                    start + count).toString();
-            mWebView.replaceTextfieldText(start, start + before, replace,
-                    start + count,
-                    start + count);
-        }
-        updateCachedTextfield();
-    }
-
-    @Override
-    public boolean onTouchEvent(MotionEvent event) {
-        switch (event.getAction()) {
-        case MotionEvent.ACTION_DOWN:
-            super.onTouchEvent(event);
-            // This event may be the start of a drag, so store it to pass to the
-            // WebView if it is.
-            mDragStartX = event.getX();
-            mDragStartY = event.getY();
-            mDragStartTime = event.getEventTime();
-            mDragSent = false;
-            mScrolled = false;
-            mGotTouchDown = true;
-            mHasPerformedLongClick = false;
-            break;
-        case MotionEvent.ACTION_MOVE:
-            if (mHasPerformedLongClick) {
-                mGotTouchDown = false;
-                return false;
-            }
-            int slop = ViewConfiguration.get(mContext).getScaledTouchSlop();
-            Spannable buffer = getText();
-            int initialScrollX = Touch.getInitialScrollX(this, buffer);
-            int initialScrollY = Touch.getInitialScrollY(this, buffer);
-            super.onTouchEvent(event);
-            int dx = Math.abs(mScrollX - initialScrollX);
-            int dy = Math.abs(mScrollY - initialScrollY);
-            // Use a smaller slop when checking to see if we've moved far enough
-            // to scroll the text, because experimentally, slop has shown to be
-            // to big for the case of a small textfield.
-            int smallerSlop = slop/2;
-            if (dx > smallerSlop || dy > smallerSlop) {
-                // Scrolling is handled in onScrollChanged.
-                mScrolled = true;
-                cancelLongPress();
-                return true;
-            }
-            if (Math.abs((int) event.getX() - mDragStartX) < slop
-                    && Math.abs((int) event.getY() - mDragStartY) < slop) {
-                // If the user has not scrolled further than slop, we should not
-                // send the drag.  Instead, do nothing, and when the user lifts
-                // their finger, we will change the selection.
-                return true;
-            }
-            if (mWebView != null) {
-                // Only want to set the initial state once.
-                if (!mDragSent) {
-                    mWebView.initiateTextFieldDrag(mDragStartX, mDragStartY,
-                            mDragStartTime);
-                    mDragSent = true;
-                }
-                boolean scrolled = mWebView.textFieldDrag(event);
-                if (scrolled) {
-                    mScrolled = true;
-                    cancelLongPress();
-                    return true;
-                }
-            }
-            return false;
-        case MotionEvent.ACTION_UP:
-        case MotionEvent.ACTION_CANCEL:
-            super.onTouchEvent(event);
-            if (mHasPerformedLongClick) {
-                mGotTouchDown = false;
-                return false;
-            }
-            if (!mScrolled) {
-                // If the page scrolled, or the TextView scrolled, we do not
-                // want to change the selection
-                cancelLongPress();
-                if (mGotTouchDown && mWebView != null) {
-                    mWebView.touchUpOnTextField(event);
-                }
-            }
-            // Necessary for the WebView to reset its state
-            if (mWebView != null && mDragSent) {
-                mWebView.onTouchEvent(event);
-            }
-            mGotTouchDown = false;
-            break;
-        default:
-            break;
-        }
-        return true;
-    }
-
-    @Override
-    public boolean onTrackballEvent(MotionEvent event) {
-        if (isPopupShowing()) {
-            return super.onTrackballEvent(event);
-        }
-        if (event.getAction() != MotionEvent.ACTION_MOVE) {
-            return false;
-        }
-        Spannable text = getText();
-        MovementMethod move = getMovementMethod();
-        if (move != null && getLayout() != null &&
-            move.onTrackballEvent(this, text, event)) {
-            // Selection is changed in onSelectionChanged
-            return true;
-        }
-        return false;
-    }
-
-    @Override
-    public boolean performLongClick() {
-        mHasPerformedLongClick = true;
-        return super.performLongClick();
-    }
-
-    /**
-     * Remove this WebTextView from its host WebView, and return
-     * focus to the host.
-     */
-    /* package */ void remove() {
-        // hide the soft keyboard when the edit text is out of focus
-        InputMethodManager imm = InputMethodManager.getInstance(mContext);
-        if (imm.isActive(this)) {
-            imm.hideSoftInputFromWindow(getWindowToken(), 0);
-        }
-        mInsideRemove = true;
-        boolean isFocused = hasFocus();
-        mWebView.removeView(this);
-        if (isFocused) {
-            mWebView.requestFocus();
-        }
-        mInsideRemove = false;
-        mHandler.removeCallbacksAndMessages(null);
-    }
-
-    @Override
-    public boolean requestRectangleOnScreen(Rect rectangle, boolean immediate) {
-        // Do nothing, since webkit will put the textfield on screen.
-        return true;
-    }
-
-    /**
-     *  Send the DOM events for the specified event.
-     *  @param event    KeyEvent to be translated into a DOM event.
-     */
-    private void sendDomEvent(KeyEvent event) {
-        mWebView.passToJavaScript(getText().toString(), event);
-    }
-
-    /**
-     *  Always use this instead of setAdapter, as this has features specific to
-     *  the WebTextView.
-     */
-    public void setAdapterCustom(AutoCompleteAdapter adapter) {
-        if (adapter != null) {
-            setInputType(getInputType()
-                    | InputType.TYPE_TEXT_FLAG_AUTO_COMPLETE);
-            adapter.setTextView(this);
-            if (mAutoFillable) {
-                setOnItemClickListener(this);
-            } else {
-                setOnItemClickListener(null);
-            }
-            showDropDown();
-        } else {
-            dismissDropDown();
-        }
-        super.setAdapter(adapter);
-    }
-
-    /**
-     *  This is a special version of ArrayAdapter which changes its text size
-     *  to match the text size of its host TextView.
-     */
-    public static class AutoCompleteAdapter extends ArrayAdapter<String> {
-        private TextView mTextView;
-
-        public AutoCompleteAdapter(Context context, ArrayList<String> entries) {
-            super(context, com.android.internal.R.layout
-                    .web_text_view_dropdown, entries);
-        }
-
-        /**
-         * {@inheritDoc}
-         */
-        @Override
-        public View getView(int position, View convertView, ViewGroup parent) {
-            TextView tv =
-                    (TextView) super.getView(position, convertView, parent);
-            if (tv != null && mTextView != null) {
-                tv.setTextSize(TypedValue.COMPLEX_UNIT_PX, mTextView.getTextSize());
-            }
-            return tv;
-        }
-
-        /**
-         * Set the TextView so we can match its text size.
-         */
-        private void setTextView(TextView tv) {
-            mTextView = tv;
-        }
-    }
-
-    /**
-     * Sets the selection when the user clicks on a textfield or textarea with
-     * the trackball or center key, or starts typing into it without clicking on
-     * it.
-     */
-    /* package */ void setDefaultSelection() {
-        Spannable text = (Spannable) getText();
-        int selection = mSingle ? text.length() : 0;
-        if (Selection.getSelectionStart(text) == selection
-                && Selection.getSelectionEnd(text) == selection) {
-            // The selection of the UI copy is set correctly, but the
-            // WebTextView still needs to inform the webkit thread to set the
-            // selection.  Normally that is done in onSelectionChanged, but
-            // onSelectionChanged will not be called because the UI copy is not
-            // changing.  (This can happen when the WebTextView takes focus.
-            // That onSelectionChanged was blocked because the selection set
-            // when focusing is not necessarily the desirable selection for
-            // WebTextView.)
-            if (mWebView != null) {
-                mWebView.setSelection(selection, selection);
-            }
-        } else {
-            Selection.setSelection(text, selection, selection);
-        }
-        if (mWebView != null) mWebView.incrementTextGeneration();
-    }
-
-    @Override
-    public void setInputType(int type) {
-        mFromSetInputType = true;
-        super.setInputType(type);
-        mFromSetInputType = false;
-    }
-
-    private void setMaxLength(int maxLength) {
-        mMaxLength = maxLength;
-        if (-1 == maxLength) {
-            setFilters(NO_FILTERS);
-        } else {
-            setFilters(new InputFilter[] {
-                new InputFilter.LengthFilter(maxLength) });
-        }
-    }
-
-    /**
-     *  Set the pointer for this node so it can be determined which node this
-     *  WebTextView represents.
-     *  @param  ptr Integer representing the pointer to the node which this
-     *          WebTextView represents.
-     */
-    /* package */ void setNodePointer(int ptr) {
-        if (ptr != mNodePointer) {
-            mNodePointer = ptr;
-            setAdapterCustom(null);
-        }
-    }
-
-    /**
-     * Determine the position and size of WebTextView, and add it to the
-     * WebView's view heirarchy.  All parameters are presumed to be in
-     * view coordinates.  Also requests Focus and sets the cursor to not
-     * request to be in view.
-     * @param x         x-position of the textfield.
-     * @param y         y-position of the textfield.
-     * @param width     width of the textfield.
-     * @param height    height of the textfield.
-     */
-    /* package */ void setRect(int x, int y, int width, int height) {
-        LayoutParams lp = (LayoutParams) getLayoutParams();
-        x -= mRingInset;
-        y -= mRingInset;
-        width += 2 * mRingInset;
-        height += 2 * mRingInset;
-        boolean needsUpdate = false;
-        if (null == lp) {
-            lp = new LayoutParams(width, height, x, y);
-        } else {
-            if ((lp.x != x) || (lp.y != y) || (lp.width != width)
-                    || (lp.height != height)) {
-                needsUpdate = true;
-                lp.x = x;
-                lp.y = y;
-                lp.width = width;
-                lp.height = height;
-            }
-        }
-        if (getParent() == null) {
-            // Insert the view so that it's drawn first (at index 0)
-            mWebView.addView(this, 0, lp);
-        } else if (needsUpdate) {
-            setLayoutParams(lp);
-        }
-        // Set up a measure spec so a layout can always be recreated.
-        mWidthSpec = MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY);
-        mHeightSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY);
-    }
-
-    /**
-     * Set the selection, and disable our onSelectionChanged action.
-     */
-    /* package */ void setSelectionFromWebKit(int start, int end) {
-        if (start < 0 || end < 0) return;
-        Spannable text = (Spannable) getText();
-        int length = text.length();
-        if (start > length || end > length) return;
-        mFromWebKit = true;
-        Selection.setSelection(text, start, end);
-        mFromWebKit = false;
-    }
-
-    /**
-     * Update the text size according to the size of the focus candidate's text
-     * size in mWebView.  Should only be called from mWebView.
-     */
-    /* package */ void updateTextSize() {
-        Assert.assertNotNull("updateTextSize should only be called from "
-                + "mWebView, so mWebView should never be null!", mWebView);
-        // Note that this is approximately WebView.contentToViewDimension,
-        // without being rounded.
-        float size = mWebView.nativeFocusCandidateTextSize()
-                * mWebView.getScale();
-        setTextSize(TypedValue.COMPLEX_UNIT_PX, size);
-    }
-
-    /**
-     * Set the text to the new string, but use the old selection, making sure
-     * to keep it within the new string.
-     * @param   text    The new text to place in the textfield.
-     */
-    /* package */ void setTextAndKeepSelection(String text) {
-        Editable edit = getText();
-        mPreChange = text;
-        if (edit.toString().equals(text)) {
-            return;
-        }
-        int selStart = Selection.getSelectionStart(edit);
-        int selEnd = Selection.getSelectionEnd(edit);
-        mInSetTextAndKeepSelection = true;
-        edit.replace(0, edit.length(), text);
-        int newLength = edit.length();
-        if (selStart > newLength) selStart = newLength;
-        if (selEnd > newLength) selEnd = newLength;
-        Selection.setSelection(edit, selStart, selEnd);
-        mInSetTextAndKeepSelection = false;
-        InputMethodManager imm = InputMethodManager.peekInstance();
-        if (imm != null && imm.isActive(this)) {
-            // Since the text has changed, do not allow the IME to replace the
-            // existing text as though it were a completion.
-            imm.restartInput(this);
-        }
-        updateCachedTextfield();
-    }
-
-    /**
-     * Called by WebView.rebuildWebTextView().  Based on the type of the <input>
-     * element, set up the WebTextView, its InputType, and IME Options properly.
-     * @param type int corresponding to enum "Type" defined in CachedInput.h.
-     *              Does not correspond to HTMLInputElement::InputType so this
-     *              is unaffected if that changes, and also because that has no
-     *              type corresponding to textarea (which is its own tag).
-     */
-    /* package */ void setType(int type) {
-        if (mWebView == null) return;
-        boolean single = true;
-        int maxLength = -1;
-        int inputType = InputType.TYPE_CLASS_TEXT
-                | InputType.TYPE_TEXT_VARIATION_WEB_EDIT_TEXT;
-        int imeOptions = EditorInfo.IME_FLAG_NO_EXTRACT_UI
-                | EditorInfo.IME_FLAG_NO_FULLSCREEN;
-        if (!mWebView.nativeFocusCandidateIsSpellcheck()) {
-            inputType |= InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS;
-        }
-        if (TEXT_AREA != type
-                && mWebView.nativeFocusCandidateHasNextTextfield()) {
-            imeOptions |= EditorInfo.IME_FLAG_NAVIGATE_NEXT;
-        }
-        switch (type) {
-            case NORMAL_TEXT_FIELD:
-                imeOptions |= EditorInfo.IME_ACTION_GO;
-                break;
-            case TEXT_AREA:
-                single = false;
-                inputType |= InputType.TYPE_TEXT_FLAG_MULTI_LINE
-                        | InputType.TYPE_TEXT_FLAG_CAP_SENTENCES
-                        | InputType.TYPE_TEXT_FLAG_AUTO_CORRECT;
-                imeOptions |= EditorInfo.IME_ACTION_NONE;
-                break;
-            case PASSWORD:
-                inputType |= EditorInfo.TYPE_TEXT_VARIATION_WEB_PASSWORD;
-                imeOptions |= EditorInfo.IME_ACTION_GO;
-                break;
-            case SEARCH:
-                imeOptions |= EditorInfo.IME_ACTION_SEARCH;
-                break;
-            case EMAIL:
-                // inputType needs to be overwritten because of the different text variation.
-                inputType = InputType.TYPE_CLASS_TEXT
-                        | InputType.TYPE_TEXT_VARIATION_WEB_EMAIL_ADDRESS;
-                imeOptions |= EditorInfo.IME_ACTION_GO;
-                break;
-            case NUMBER:
-                // inputType needs to be overwritten because of the different class.
-                inputType = InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_VARIATION_NORMAL
-                        | InputType.TYPE_NUMBER_FLAG_SIGNED | InputType.TYPE_NUMBER_FLAG_DECIMAL;
-                // Number and telephone do not have both a Tab key and an
-                // action, so set the action to NEXT
-                imeOptions |= EditorInfo.IME_ACTION_NEXT;
-                break;
-            case TELEPHONE:
-                // inputType needs to be overwritten because of the different class.
-                inputType = InputType.TYPE_CLASS_PHONE;
-                imeOptions |= EditorInfo.IME_ACTION_NEXT;
-                break;
-            case URL:
-                // TYPE_TEXT_VARIATION_URI prevents Tab key from showing, so
-                // exclude it for now.
-                imeOptions |= EditorInfo.IME_ACTION_GO;
-                break;
-            default:
-                imeOptions |= EditorInfo.IME_ACTION_GO;
-                break;
-        }
-        setHint(null);
-        setThreshold(1);
-        boolean autoComplete = false;
-        if (single) {
-            mWebView.requestLabel(mWebView.nativeFocusCandidateFramePointer(),
-                    mNodePointer);
-            maxLength = mWebView.nativeFocusCandidateMaxLength();
-            autoComplete = mWebView.nativeFocusCandidateIsAutoComplete();
-            if (type != PASSWORD && (mAutoFillable || autoComplete)) {
-                String name = mWebView.nativeFocusCandidateName();
-                if (name != null && name.length() > 0) {
-                    mWebView.requestFormData(name, mNodePointer, mAutoFillable,
-                            autoComplete);
-                }
-            }
-        }
-        mSingle = single;
-        setMaxLength(maxLength);
-        setHorizontallyScrolling(single);
-        setInputType(inputType);
-        clearComposingText();
-        setImeOptions(imeOptions);
-        setVisibility(VISIBLE);
-        if (!autoComplete) {
-            setAdapterCustom(null);
-        }
-    }
-
-    /**
-     *  Update the cache to reflect the current text.
-     */
-    /* package */ void updateCachedTextfield() {
-        mWebView.updateCachedTextfield(getText().toString());
-    }
-
-    /* package */ void setAutoFillProfileIsSet(boolean autoFillProfileIsSet) {
-        mAutoFillProfileIsSet = autoFillProfileIsSet;
-    }
+    static final int FORM_NOT_AUTOFILLABLE = -1;
 
     static String urlForAutoCompleteData(String urlString) {
         // Remove any fragment or query string.
@@ -1182,10 +50,4 @@
         return url != null ? url.getProtocol() + "://" + url.getHost() + url.getPath() : null;
     }
 
-    public void setGravityForRtl(boolean rtl) {
-        int gravity = rtl ? Gravity.RIGHT : Gravity.LEFT;
-        gravity |= mSingle ? Gravity.CENTER_VERTICAL : Gravity.TOP;
-        setGravity(gravity);
-    }
-
 }
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index a850379..a561577 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -16,126 +16,35 @@
 
 package android.webkit;
 
-import android.animation.ObjectAnimator;
 import android.annotation.Widget;
-import android.app.ActivityManager;
-import android.app.AlertDialog;
-import android.content.BroadcastReceiver;
-import android.content.ClipData;
-import android.content.ClipboardManager;
-import android.content.ComponentCallbacks2;
 import android.content.Context;
-import android.content.DialogInterface;
-import android.content.DialogInterface.OnCancelListener;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.pm.PackageManager;
 import android.content.res.Configuration;
-import android.database.DataSetObserver;
 import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.graphics.BitmapShader;
 import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.ColorFilter;
-import android.graphics.DrawFilter;
-import android.graphics.Paint;
-import android.graphics.PaintFlagsDrawFilter;
 import android.graphics.Picture;
-import android.graphics.Point;
 import android.graphics.Rect;
-import android.graphics.RectF;
-import android.graphics.Region;
-import android.graphics.RegionIterator;
-import android.graphics.Shader;
 import android.graphics.drawable.Drawable;
-import android.net.Proxy;
-import android.net.ProxyProperties;
-import android.net.Uri;
 import android.net.http.SslCertificate;
-import android.os.AsyncTask;
 import android.os.Bundle;
-import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
 import android.os.StrictMode;
-import android.os.SystemClock;
-import android.provider.Settings;
-import android.security.KeyChain;
-import android.speech.tts.TextToSpeech;
-import android.text.Editable;
-import android.text.InputType;
-import android.text.Selection;
-import android.text.TextUtils;
 import android.util.AttributeSet;
-import android.util.DisplayMetrics;
-import android.util.EventLog;
 import android.util.Log;
-import android.view.Display;
-import android.view.Gravity;
-import android.view.HapticFeedbackConstants;
-import android.view.HardwareCanvas;
-import android.view.InputDevice;
-import android.view.KeyCharacterMap;
 import android.view.KeyEvent;
-import android.view.LayoutInflater;
 import android.view.MotionEvent;
-import android.view.ScaleGestureDetector;
-import android.view.SoundEffectConstants;
-import android.view.VelocityTracker;
 import android.view.View;
-import android.view.ViewConfiguration;
 import android.view.ViewGroup;
-import android.view.ViewParent;
+import android.view.ViewGroup.LayoutParams;
 import android.view.ViewTreeObserver;
-import android.view.WindowManager;
 import android.view.accessibility.AccessibilityEvent;
-import android.view.accessibility.AccessibilityManager;
 import android.view.accessibility.AccessibilityNodeInfo;
-import android.view.inputmethod.BaseInputConnection;
 import android.view.inputmethod.EditorInfo;
 import android.view.inputmethod.InputConnection;
-import android.view.inputmethod.InputMethodManager;
-import android.webkit.HTML5VideoInline;
-import android.webkit.WebTextView.AutoCompleteAdapter;
-import android.webkit.WebViewCore.DrawData;
-import android.webkit.WebViewCore.EventHub;
-import android.webkit.WebViewCore.TextFieldInitData;
-import android.webkit.WebViewCore.TouchEventData;
-import android.webkit.WebViewCore.TouchHighlightData;
-import android.webkit.WebViewCore.WebKitHitTest;
 import android.widget.AbsoluteLayout;
-import android.widget.Adapter;
-import android.widget.AdapterView;
-import android.widget.AdapterView.OnItemClickListener;
-import android.widget.ArrayAdapter;
-import android.widget.CheckedTextView;
-import android.widget.LinearLayout;
-import android.widget.ListView;
-import android.widget.OverScroller;
-import android.widget.PopupWindow;
-import android.widget.TextView;
-import android.widget.Toast;
-
-import junit.framework.Assert;
 
 import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.net.URLDecoder;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
 import java.util.Map;
-import java.util.Set;
-import java.util.Vector;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
 
 /**
  * <p>A View that displays web pages. This class is the basis upon which you
@@ -345,452 +254,25 @@
  *
  *
  */
+/*
+ * Implementation notes.
+ * The WebView is a thin API class that delegates its public API to a backend WebViewProvider
+ * class instance. WebView extends {@link AbsoluteLayout} for backward compatibility reasons.
+ * Methods are delegated to the provider implementation: all public API methods introduced in this
+ * file are fully delegated, whereas public and protected methods from the View base classes are
+ * only delegated where a specific need exists for them to do so.
+ */
 @Widget
 public class WebView extends AbsoluteLayout
         implements ViewTreeObserver.OnGlobalFocusChangeListener,
         ViewGroup.OnHierarchyChangeListener {
 
-    private class InnerGlobalLayoutListener implements ViewTreeObserver.OnGlobalLayoutListener {
-        @Override
-        public void onGlobalLayout() {
-            if (isShown()) {
-                setGLRectViewport();
-            }
-        }
-    }
+    // Default Provider factory class name.
+    private static final String DEFAULT_WEB_VIEW_FACTORY = "android.webkit.WebViewClassic$Factory";
 
-    private class InnerScrollChangedListener implements ViewTreeObserver.OnScrollChangedListener {
-        @Override
-        public void onScrollChanged() {
-            if (isShown()) {
-                setGLRectViewport();
-            }
-        }
-    }
-
-    /**
-     * InputConnection used for ContentEditable. This captures changes
-     * to the text and sends them either as key strokes or text changes.
-     */
-    private class WebViewInputConnection extends BaseInputConnection {
-        // Used for mapping characters to keys typed.
-        private KeyCharacterMap mKeyCharacterMap;
-        private boolean mIsKeySentByMe;
-        private int mInputType;
-        private int mImeOptions;
-        private String mHint;
-        private int mMaxLength;
-
-        public WebViewInputConnection() {
-            super(WebView.this, true);
-        }
-
-        @Override
-        public boolean sendKeyEvent(KeyEvent event) {
-            // Some IMEs send key events directly using sendKeyEvents.
-            // WebViewInputConnection should treat these as text changes.
-            if (!mIsKeySentByMe) {
-                if (event.getAction() == KeyEvent.ACTION_UP) {
-                    if (event.getKeyCode() == KeyEvent.KEYCODE_DEL) {
-                        return deleteSurroundingText(1, 0);
-                    } else if (event.getKeyCode() == KeyEvent.KEYCODE_FORWARD_DEL) {
-                        return deleteSurroundingText(0, 1);
-                    } else if (event.getUnicodeChar() != 0){
-                        String newComposingText =
-                                Character.toString((char)event.getUnicodeChar());
-                        return commitText(newComposingText, 1);
-                    }
-                } else if (event.getAction() == KeyEvent.ACTION_DOWN &&
-                        (event.getKeyCode() == KeyEvent.KEYCODE_DEL
-                        || event.getKeyCode() == KeyEvent.KEYCODE_FORWARD_DEL
-                        || event.getUnicodeChar() != 0)) {
-                    return true; // only act on action_down
-                }
-            }
-            return super.sendKeyEvent(event);
-        }
-
-        public void setTextAndKeepSelection(CharSequence text) {
-            Editable editable = getEditable();
-            int selectionStart = Selection.getSelectionStart(editable);
-            int selectionEnd = Selection.getSelectionEnd(editable);
-            text = limitReplaceTextByMaxLength(text, editable.length());
-            editable.replace(0, editable.length(), text);
-            restartInput();
-            // Keep the previous selection.
-            selectionStart = Math.min(selectionStart, editable.length());
-            selectionEnd = Math.min(selectionEnd, editable.length());
-            setSelection(selectionStart, selectionEnd);
-        }
-
-        public void replaceSelection(CharSequence text) {
-            Editable editable = getEditable();
-            int selectionStart = Selection.getSelectionStart(editable);
-            int selectionEnd = Selection.getSelectionEnd(editable);
-            text = limitReplaceTextByMaxLength(text, selectionEnd - selectionStart);
-            setNewText(selectionStart, selectionEnd, text);
-            editable.replace(selectionStart, selectionEnd, text);
-            restartInput();
-            // Move caret to the end of the new text
-            int newCaret = selectionStart + text.length();
-            setSelection(newCaret, newCaret);
-        }
-
-        @Override
-        public boolean setComposingText(CharSequence text, int newCursorPosition) {
-            Editable editable = getEditable();
-            int start = getComposingSpanStart(editable);
-            int end = getComposingSpanEnd(editable);
-            if (start < 0 || end < 0) {
-                start = Selection.getSelectionStart(editable);
-                end = Selection.getSelectionEnd(editable);
-            }
-            if (end < start) {
-                int temp = end;
-                end = start;
-                start = temp;
-            }
-            CharSequence limitedText = limitReplaceTextByMaxLength(text, end - start);
-            setNewText(start, end, limitedText);
-            if (limitedText != text) {
-                newCursorPosition -= text.length() - limitedText.length();
-            }
-            super.setComposingText(limitedText, newCursorPosition);
-            if (limitedText != text) {
-                restartInput();
-                int lastCaret = start + limitedText.length();
-                finishComposingText();
-                setSelection(lastCaret, lastCaret);
-            }
-            return true;
-        }
-
-        @Override
-        public boolean commitText(CharSequence text, int newCursorPosition) {
-            setComposingText(text, newCursorPosition);
-            int cursorPosition = Selection.getSelectionEnd(getEditable());
-            setComposingRegion(cursorPosition, cursorPosition);
-            return true;
-        }
-
-        @Override
-        public boolean deleteSurroundingText(int leftLength, int rightLength) {
-            Editable editable = getEditable();
-            int cursorPosition = Selection.getSelectionEnd(editable);
-            int startDelete = Math.max(0, cursorPosition - leftLength);
-            int endDelete = Math.min(editable.length(),
-                    cursorPosition + rightLength);
-            setNewText(startDelete, endDelete, "");
-            return super.deleteSurroundingText(leftLength, rightLength);
-        }
-
-        @Override
-        public boolean performEditorAction(int editorAction) {
-
-            boolean handled = true;
-            switch (editorAction) {
-            case EditorInfo.IME_ACTION_NEXT:
-                WebView.this.requestFocus(FOCUS_FORWARD);
-                break;
-            case EditorInfo.IME_ACTION_PREVIOUS:
-                WebView.this.requestFocus(FOCUS_BACKWARD);
-                break;
-            case EditorInfo.IME_ACTION_DONE:
-                WebView.this.hideSoftKeyboard();
-                break;
-            case EditorInfo.IME_ACTION_GO:
-            case EditorInfo.IME_ACTION_SEARCH:
-                WebView.this.hideSoftKeyboard();
-                String text = getEditable().toString();
-                passToJavaScript(text, new KeyEvent(KeyEvent.ACTION_DOWN,
-                        KeyEvent.KEYCODE_ENTER));
-                passToJavaScript(text, new KeyEvent(KeyEvent.ACTION_UP,
-                        KeyEvent.KEYCODE_ENTER));
-                break;
-
-            default:
-                handled = super.performEditorAction(editorAction);
-                break;
-            }
-
-            return handled;
-        }
-
-        public void initEditorInfo(WebViewCore.TextFieldInitData initData) {
-            int type = initData.mType;
-            int inputType = InputType.TYPE_CLASS_TEXT
-                    | InputType.TYPE_TEXT_VARIATION_WEB_EDIT_TEXT;
-            int imeOptions = EditorInfo.IME_FLAG_NO_EXTRACT_UI
-                    | EditorInfo.IME_FLAG_NO_FULLSCREEN;
-            if (!initData.mIsSpellCheckEnabled) {
-                inputType |= InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS;
-            }
-            if (WebTextView.TEXT_AREA != type
-                    && initData.mIsTextFieldNext) {
-                imeOptions |= EditorInfo.IME_FLAG_NAVIGATE_NEXT;
-            }
-            switch (type) {
-                case WebTextView.NORMAL_TEXT_FIELD:
-                    imeOptions |= EditorInfo.IME_ACTION_GO;
-                    break;
-                case WebTextView.TEXT_AREA:
-                    inputType |= InputType.TYPE_TEXT_FLAG_MULTI_LINE
-                            | InputType.TYPE_TEXT_FLAG_CAP_SENTENCES
-                            | InputType.TYPE_TEXT_FLAG_AUTO_CORRECT;
-                    imeOptions |= EditorInfo.IME_ACTION_NONE;
-                    break;
-                case WebTextView.PASSWORD:
-                    inputType |= EditorInfo.TYPE_TEXT_VARIATION_WEB_PASSWORD;
-                    imeOptions |= EditorInfo.IME_ACTION_GO;
-                    break;
-                case WebTextView.SEARCH:
-                    imeOptions |= EditorInfo.IME_ACTION_SEARCH;
-                    break;
-                case WebTextView.EMAIL:
-                    // inputType needs to be overwritten because of the different text variation.
-                    inputType = InputType.TYPE_CLASS_TEXT
-                            | InputType.TYPE_TEXT_VARIATION_WEB_EMAIL_ADDRESS;
-                    imeOptions |= EditorInfo.IME_ACTION_GO;
-                    break;
-                case WebTextView.NUMBER:
-                    // inputType needs to be overwritten because of the different class.
-                    inputType = InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_VARIATION_NORMAL
-                            | InputType.TYPE_NUMBER_FLAG_SIGNED | InputType.TYPE_NUMBER_FLAG_DECIMAL;
-                    // Number and telephone do not have both a Tab key and an
-                    // action, so set the action to NEXT
-                    imeOptions |= EditorInfo.IME_ACTION_NEXT;
-                    break;
-                case WebTextView.TELEPHONE:
-                    // inputType needs to be overwritten because of the different class.
-                    inputType = InputType.TYPE_CLASS_PHONE;
-                    imeOptions |= EditorInfo.IME_ACTION_NEXT;
-                    break;
-                case WebTextView.URL:
-                    // TYPE_TEXT_VARIATION_URI prevents Tab key from showing, so
-                    // exclude it for now.
-                    imeOptions |= EditorInfo.IME_ACTION_GO;
-                    inputType |= InputType.TYPE_TEXT_VARIATION_URI;
-                    break;
-                default:
-                    imeOptions |= EditorInfo.IME_ACTION_GO;
-                    break;
-            }
-            mHint = initData.mLabel;
-            mInputType = inputType;
-            mImeOptions = imeOptions;
-            mMaxLength = initData.mMaxLength;
-        }
-
-        public void setupEditorInfo(EditorInfo outAttrs) {
-            outAttrs.inputType = mInputType;
-            outAttrs.imeOptions = mImeOptions;
-            outAttrs.hintText = mHint;
-            outAttrs.initialCapsMode = getCursorCapsMode(InputType.TYPE_CLASS_TEXT);
-        }
-
-        /**
-         * Sends a text change to webkit indirectly. If it is a single-
-         * character add or delete, it sends it as a key stroke. If it cannot
-         * be represented as a key stroke, it sends it as a field change.
-         * @param start The start offset (inclusive) of the text being changed.
-         * @param end The end offset (exclusive) of the text being changed.
-         * @param text The new text to replace the changed text.
-         */
-        private void setNewText(int start, int end, CharSequence text) {
-            mIsKeySentByMe = true;
-            Editable editable = getEditable();
-            CharSequence original = editable.subSequence(start, end);
-            boolean isCharacterAdd = false;
-            boolean isCharacterDelete = false;
-            int textLength = text.length();
-            int originalLength = original.length();
-            if (textLength > originalLength) {
-                isCharacterAdd = (textLength == originalLength + 1)
-                        && TextUtils.regionMatches(text, 0, original, 0,
-                                originalLength);
-            } else if (originalLength > textLength) {
-                isCharacterDelete = (textLength == originalLength - 1)
-                        && TextUtils.regionMatches(text, 0, original, 0,
-                                textLength);
-            }
-            if (isCharacterAdd) {
-                sendCharacter(text.charAt(textLength - 1));
-            } else if (isCharacterDelete) {
-                sendKey(KeyEvent.KEYCODE_DEL);
-            } else if ((textLength != originalLength) ||
-                    !TextUtils.regionMatches(text, 0, original, 0,
-                            textLength)) {
-                // Send a message so that key strokes and text replacement
-                // do not come out of order.
-                Message replaceMessage = mPrivateHandler.obtainMessage(
-                        REPLACE_TEXT, start,  end, text.toString());
-                mPrivateHandler.sendMessage(replaceMessage);
-            }
-            mIsKeySentByMe = false;
-        }
-
-        /**
-         * Send a single character to the WebView as a key down and up event.
-         * @param c The character to be sent.
-         */
-        private void sendCharacter(char c) {
-            if (mKeyCharacterMap == null) {
-                mKeyCharacterMap = KeyCharacterMap.load(KeyCharacterMap.VIRTUAL_KEYBOARD);
-            }
-            char[] chars = new char[1];
-            chars[0] = c;
-            KeyEvent[] events = mKeyCharacterMap.getEvents(chars);
-            if (events != null) {
-                for (KeyEvent event : events) {
-                    sendKeyEvent(event);
-                }
-            } else {
-                Message msg = mPrivateHandler.obtainMessage(KEY_PRESS, (int) c, 0);
-                mPrivateHandler.sendMessage(msg);
-            }
-        }
-
-        /**
-         * Send a key event for a specific key code, not a standard
-         * unicode character.
-         * @param keyCode The key code to send.
-         */
-        private void sendKey(int keyCode) {
-            long eventTime = SystemClock.uptimeMillis();
-            sendKeyEvent(new KeyEvent(eventTime, eventTime,
-                    KeyEvent.ACTION_DOWN, keyCode, 0, 0,
-                    KeyCharacterMap.VIRTUAL_KEYBOARD, 0,
-                    KeyEvent.FLAG_SOFT_KEYBOARD));
-            sendKeyEvent(new KeyEvent(SystemClock.uptimeMillis(), eventTime,
-                    KeyEvent.ACTION_UP, keyCode, 0, 0,
-                    KeyCharacterMap.VIRTUAL_KEYBOARD, 0,
-                    KeyEvent.FLAG_SOFT_KEYBOARD));
-        }
-
-        private CharSequence limitReplaceTextByMaxLength(CharSequence text,
-                int numReplaced) {
-            if (mMaxLength > 0) {
-                Editable editable = getEditable();
-                int maxReplace = mMaxLength - editable.length() + numReplaced;
-                if (maxReplace < text.length()) {
-                    maxReplace = Math.max(maxReplace, 0);
-                    // New length is greater than the maximum. trim it down.
-                    text = text.subSequence(0, maxReplace);
-                }
-            }
-            return text;
-        }
-
-        private void restartInput() {
-            InputMethodManager imm = InputMethodManager.peekInstance();
-            if (imm != null) {
-                // Since the text has changed, do not allow the IME to replace the
-                // existing text as though it were a completion.
-                imm.restartInput(WebView.this);
-            }
-        }
-    }
-
-    private class PastePopupWindow extends PopupWindow implements OnClickListener {
-        private ViewGroup mContentView;
-        private TextView mPasteTextView;
-
-        public PastePopupWindow() {
-            super(WebView.this.mContext, null,
-                    com.android.internal.R.attr.textSelectHandleWindowStyle);
-            setClippingEnabled(true);
-            LinearLayout linearLayout = new LinearLayout(WebView.this.getContext());
-            linearLayout.setOrientation(LinearLayout.HORIZONTAL);
-            mContentView = linearLayout;
-            mContentView.setBackgroundResource(
-                    com.android.internal.R.drawable.text_edit_paste_window);
-
-            LayoutInflater inflater = (LayoutInflater)WebView.this.mContext.
-                    getSystemService(Context.LAYOUT_INFLATER_SERVICE);
-
-            ViewGroup.LayoutParams wrapContent = new ViewGroup.LayoutParams(
-                    ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
-
-            mPasteTextView = (TextView) inflater.inflate(
-                    com.android.internal.R.layout.text_edit_action_popup_text, null);
-            mPasteTextView.setLayoutParams(wrapContent);
-            mContentView.addView(mPasteTextView);
-            mPasteTextView.setText(com.android.internal.R.string.paste);
-            mPasteTextView.setOnClickListener(this);
-            this.setContentView(mContentView);
-        }
-
-        public void show(Rect cursorRect, int windowLeft, int windowTop) {
-            measureContent();
-
-            int width = mContentView.getMeasuredWidth();
-            int height = mContentView.getMeasuredHeight();
-            int y = cursorRect.top - height;
-            if (y < windowTop) {
-                // There's not enough room vertically, move it below the
-                // handle.
-                // The selection handle is vertically offset by 1/4 of the
-                // line height.
-                y = cursorRect.bottom - (cursorRect.height() / 4) +
-                        mSelectHandleCenter.getIntrinsicHeight();
-            }
-            int x = cursorRect.centerX() - (width / 2);
-            if (x < windowLeft) {
-                x = windowLeft;
-            }
-            if (!isShowing()) {
-                showAtLocation(WebView.this, Gravity.NO_GRAVITY, x, y);
-            }
-            update(x, y, width, height);
-        }
-
-        public void hide() {
-            dismiss();
-        }
-
-        @Override
-        public void onClick(View view) {
-            pasteFromClipboard();
-            selectionDone();
-        }
-
-        protected void measureContent() {
-            final DisplayMetrics displayMetrics = mContext.getResources().getDisplayMetrics();
-            mContentView.measure(
-                    View.MeasureSpec.makeMeasureSpec(displayMetrics.widthPixels,
-                            View.MeasureSpec.AT_MOST),
-                    View.MeasureSpec.makeMeasureSpec(displayMetrics.heightPixels,
-                            View.MeasureSpec.AT_MOST));
-        }
-    }
-
-    // The listener to capture global layout change event.
-    private InnerGlobalLayoutListener mGlobalLayoutListener = null;
-
-    // The listener to capture scroll event.
-    private InnerScrollChangedListener mScrollChangedListener = null;
-
-    // if AUTO_REDRAW_HACK is true, then the CALL key will toggle redrawing
-    // the screen all-the-time. Good for profiling our drawing code
-    static private final boolean AUTO_REDRAW_HACK = false;
-    // true means redraw the screen all-the-time. Only with AUTO_REDRAW_HACK
-    private boolean mAutoRedraw;
-
-    // Reference to the AlertDialog displayed by InvokeListBox.
-    // It's used to dismiss the dialog in destroy if not done before.
-    private AlertDialog mListBoxDialog = null;
-
-    static final String LOGTAG = "webview";
-
-    private ZoomManager mZoomManager;
-
-    private final Rect mGLRectViewport = new Rect();
-    private final Rect mViewRectViewport = new Rect();
-    private final RectF mVisibleContentRect = new RectF();
-    private boolean mGLViewportEmpty = false;
-    WebViewInputConnection mInputConnection = null;
-    private int mFieldPointer;
-    private PastePopupWindow mPasteWindow;
+    private static final String LOGTAG = "webview_proxy";
+    // TODO: flip DEBUG to always be disabled.
+    private static final boolean DEBUG = true;
 
     /**
      *  Transportation object for returning WebView across thread boundaries.
@@ -815,531 +297,6 @@
         }
     }
 
-    private static class OnTrimMemoryListener implements ComponentCallbacks2 {
-        private static OnTrimMemoryListener sInstance = null;
-
-        static void init(Context c) {
-            if (sInstance == null) {
-                sInstance = new OnTrimMemoryListener(c.getApplicationContext());
-            }
-        }
-
-        private OnTrimMemoryListener(Context c) {
-            c.registerComponentCallbacks(this);
-        }
-
-        @Override
-        public void onConfigurationChanged(Configuration newConfig) {
-            // Ignore
-        }
-
-        @Override
-        public void onLowMemory() {
-            // Ignore
-        }
-
-        @Override
-        public void onTrimMemory(int level) {
-            if (DebugFlags.WEB_VIEW) {
-                Log.d("WebView", "onTrimMemory: " + level);
-            }
-            // When framework reset EGL context during high memory pressure, all
-            // the existing GL resources for the html5 video will be destroyed
-            // at native side.
-            // Here we just need to clean up the Surface Texture which is static.
-            HTML5VideoInline.cleanupSurfaceTexture();
-            WebView.nativeOnTrimMemory(level);
-        }
-
-    }
-
-    // A final CallbackProxy shared by WebViewCore and BrowserFrame.
-    private final CallbackProxy mCallbackProxy;
-
-    private final WebViewDatabase mDatabase;
-
-    // SSL certificate for the main top-level page (if secure)
-    private SslCertificate mCertificate;
-
-    // Native WebView pointer that is 0 until the native object has been
-    // created.
-    private int mNativeClass;
-    // This would be final but it needs to be set to null when the WebView is
-    // destroyed.
-    private WebViewCore mWebViewCore;
-    // Handler for dispatching UI messages.
-    /* package */ final Handler mPrivateHandler = new PrivateHandler();
-    private WebTextView mWebTextView;
-    // Used to ignore changes to webkit text that arrives to the UI side after
-    // more key events.
-    private int mTextGeneration;
-
-    /* package */ void incrementTextGeneration() { mTextGeneration++; }
-
-    // Used by WebViewCore to create child views.
-    /* package */ final ViewManager mViewManager;
-
-    // Used to display in full screen mode
-    PluginFullScreenHolder mFullScreenHolder;
-
-    /**
-     * Position of the last touch event in pixels.
-     * Use integer to prevent loss of dragging delta calculation accuracy;
-     * which was done in float and converted to integer, and resulted in gradual
-     * and compounding touch position and view dragging mismatch.
-     */
-    private int mLastTouchX;
-    private int mLastTouchY;
-    private int mStartTouchX;
-    private int mStartTouchY;
-    private float mAverageAngle;
-
-    /**
-     * Time of the last touch event.
-     */
-    private long mLastTouchTime;
-
-    /**
-     * Time of the last time sending touch event to WebViewCore
-     */
-    private long mLastSentTouchTime;
-
-    /**
-     * The minimum elapsed time before sending another ACTION_MOVE event to
-     * WebViewCore. This really should be tuned for each type of the devices.
-     * For example in Google Map api test case, it takes Dream device at least
-     * 150ms to do a full cycle in the WebViewCore by processing a touch event,
-     * triggering the layout and drawing the picture. While the same process
-     * takes 60+ms on the current high speed device. If we make
-     * TOUCH_SENT_INTERVAL too small, there will be multiple touch events sent
-     * to WebViewCore queue and the real layout and draw events will be pushed
-     * to further, which slows down the refresh rate. Choose 50 to favor the
-     * current high speed devices. For Dream like devices, 100 is a better
-     * choice. Maybe make this in the buildspec later.
-     * (Update 12/14/2010: changed to 0 since current device should be able to
-     * handle the raw events and Map team voted to have the raw events too.
-     */
-    private static final int TOUCH_SENT_INTERVAL = 0;
-    private int mCurrentTouchInterval = TOUCH_SENT_INTERVAL;
-
-    /**
-     * Helper class to get velocity for fling
-     */
-    VelocityTracker mVelocityTracker;
-    private int mMaximumFling;
-    private float mLastVelocity;
-    private float mLastVelX;
-    private float mLastVelY;
-
-    // The id of the native layer being scrolled.
-    private int mCurrentScrollingLayerId;
-    private Rect mScrollingLayerRect = new Rect();
-
-    // only trigger accelerated fling if the new velocity is at least
-    // MINIMUM_VELOCITY_RATIO_FOR_ACCELERATION times of the previous velocity
-    private static final float MINIMUM_VELOCITY_RATIO_FOR_ACCELERATION = 0.2f;
-
-    /**
-     * Touch mode
-     */
-    private int mTouchMode = TOUCH_DONE_MODE;
-    private static final int TOUCH_INIT_MODE = 1;
-    private static final int TOUCH_DRAG_START_MODE = 2;
-    private static final int TOUCH_DRAG_MODE = 3;
-    private static final int TOUCH_SHORTPRESS_START_MODE = 4;
-    private static final int TOUCH_SHORTPRESS_MODE = 5;
-    private static final int TOUCH_DOUBLE_TAP_MODE = 6;
-    private static final int TOUCH_DONE_MODE = 7;
-    private static final int TOUCH_PINCH_DRAG = 8;
-    private static final int TOUCH_DRAG_LAYER_MODE = 9;
-
-    // Whether to forward the touch events to WebCore
-    // Can only be set by WebKit via JNI.
-    private boolean mForwardTouchEvents = false;
-
-    // Whether to prevent default during touch. The initial value depends on
-    // mForwardTouchEvents. If WebCore wants all the touch events, it says yes
-    // for touch down. Otherwise UI will wait for the answer of the first
-    // confirmed move before taking over the control.
-    private static final int PREVENT_DEFAULT_NO = 0;
-    private static final int PREVENT_DEFAULT_MAYBE_YES = 1;
-    private static final int PREVENT_DEFAULT_NO_FROM_TOUCH_DOWN = 2;
-    private static final int PREVENT_DEFAULT_YES = 3;
-    private static final int PREVENT_DEFAULT_IGNORE = 4;
-    private int mPreventDefault = PREVENT_DEFAULT_IGNORE;
-
-    // true when the touch movement exceeds the slop
-    private boolean mConfirmMove;
-
-    // if true, touch events will be first processed by WebCore, if prevent
-    // default is not set, the UI will continue handle them.
-    private boolean mDeferTouchProcess;
-
-    // to avoid interfering with the current touch events, track them
-    // separately. Currently no snapping or fling in the deferred process mode
-    private int mDeferTouchMode = TOUCH_DONE_MODE;
-    private float mLastDeferTouchX;
-    private float mLastDeferTouchY;
-
-    // To keep track of whether the current drag was initiated by a WebTextView,
-    // so that we know not to hide the cursor
-    boolean mDragFromTextInput;
-
-    // Whether or not to draw the cursor ring.
-    private boolean mDrawCursorRing = true;
-
-    // true if onPause has been called (and not onResume)
-    private boolean mIsPaused;
-
-    private HitTestResult mInitialHitTestResult;
-    private WebKitHitTest mFocusedNode;
-
-    /**
-     * Customizable constant
-     */
-    // pre-computed square of ViewConfiguration.getScaledTouchSlop()
-    private int mTouchSlopSquare;
-    // pre-computed square of ViewConfiguration.getScaledDoubleTapSlop()
-    private int mDoubleTapSlopSquare;
-    // pre-computed density adjusted navigation slop
-    private int mNavSlop;
-    // This should be ViewConfiguration.getTapTimeout()
-    // But system time out is 100ms, which is too short for the browser.
-    // In the browser, if it switches out of tap too soon, jump tap won't work.
-    // In addition, a double tap on a trackpad will always have a duration of
-    // 300ms, so this value must be at least that (otherwise we will timeout the
-    // first tap and convert it to a long press).
-    private static final int TAP_TIMEOUT = 300;
-    // This should be ViewConfiguration.getLongPressTimeout()
-    // But system time out is 500ms, which is too short for the browser.
-    // With a short timeout, it's difficult to treat trigger a short press.
-    private static final int LONG_PRESS_TIMEOUT = 1000;
-    // needed to avoid flinging after a pause of no movement
-    private static final int MIN_FLING_TIME = 250;
-    // draw unfiltered after drag is held without movement
-    private static final int MOTIONLESS_TIME = 100;
-    // The amount of content to overlap between two screens when going through
-    // pages with the space bar, in pixels.
-    private static final int PAGE_SCROLL_OVERLAP = 24;
-
-    /**
-     * These prevent calling requestLayout if either dimension is fixed. This
-     * depends on the layout parameters and the measure specs.
-     */
-    boolean mWidthCanMeasure;
-    boolean mHeightCanMeasure;
-
-    // Remember the last dimensions we sent to the native side so we can avoid
-    // sending the same dimensions more than once.
-    int mLastWidthSent;
-    int mLastHeightSent;
-    // Since view height sent to webkit could be fixed to avoid relayout, this
-    // value records the last sent actual view height.
-    int mLastActualHeightSent;
-
-    private int mContentWidth;   // cache of value from WebViewCore
-    private int mContentHeight;  // cache of value from WebViewCore
-
-    // Need to have the separate control for horizontal and vertical scrollbar
-    // style than the View's single scrollbar style
-    private boolean mOverlayHorizontalScrollbar = true;
-    private boolean mOverlayVerticalScrollbar = false;
-
-    // our standard speed. this way small distances will be traversed in less
-    // time than large distances, but we cap the duration, so that very large
-    // distances won't take too long to get there.
-    private static final int STD_SPEED = 480;  // pixels per second
-    // time for the longest scroll animation
-    private static final int MAX_DURATION = 750;   // milliseconds
-    private static final int SLIDE_TITLE_DURATION = 500;   // milliseconds
-
-    // Used by OverScrollGlow
-    OverScroller mScroller;
-
-    private boolean mInOverScrollMode = false;
-    private static Paint mOverScrollBackground;
-    private static Paint mOverScrollBorder;
-
-    private boolean mWrapContent;
-    private static final int MOTIONLESS_FALSE           = 0;
-    private static final int MOTIONLESS_PENDING         = 1;
-    private static final int MOTIONLESS_TRUE            = 2;
-    private static final int MOTIONLESS_IGNORE          = 3;
-    private int mHeldMotionless;
-
-    // An instance for injecting accessibility in WebViews with disabled
-    // JavaScript or ones for which no accessibility script exists
-    private AccessibilityInjector mAccessibilityInjector;
-
-    // flag indicating if accessibility script is injected so we
-    // know to handle Shift and arrows natively first
-    private boolean mAccessibilityScriptInjected;
-
-
-    /**
-     * How long the caret handle will last without being touched.
-     */
-    private static final long CARET_HANDLE_STAMINA_MS = 3000;
-
-    private Drawable mSelectHandleLeft;
-    private Drawable mSelectHandleRight;
-    private Drawable mSelectHandleCenter;
-    private Rect mSelectCursorBase = new Rect();
-    private int mSelectCursorBaseLayerId;
-    private Rect mSelectCursorExtent = new Rect();
-    private int mSelectCursorExtentLayerId;
-    private Rect mSelectDraggingCursor;
-    private Point mSelectDraggingOffset = new Point();
-    private boolean mIsCaretSelection;
-    static final int HANDLE_ID_START = 0;
-    static final int HANDLE_ID_END = 1;
-    static final int HANDLE_ID_BASE = 2;
-    static final int HANDLE_ID_EXTENT = 3;
-
-    static boolean sDisableNavcache = false;
-    static boolean sEnableWebTextView = false;
-    // the color used to highlight the touch rectangles
-    static final int HIGHLIGHT_COLOR = 0x6633b5e5;
-    // the region indicating where the user touched on the screen
-    private Region mTouchHighlightRegion = new Region();
-    // the paint for the touch highlight
-    private Paint mTouchHightlightPaint = new Paint();
-    // debug only
-    private static final boolean DEBUG_TOUCH_HIGHLIGHT = true;
-    private static final int TOUCH_HIGHLIGHT_ELAPSE_TIME = 2000;
-    private Paint mTouchCrossHairColor;
-    private int mTouchHighlightX;
-    private int mTouchHighlightY;
-    private long mTouchHighlightRequested;
-
-    // Basically this proxy is used to tell the Video to update layer tree at
-    // SetBaseLayer time and to pause when WebView paused.
-    private HTML5VideoViewProxy mHTML5VideoViewProxy;
-
-    // If we are using a set picture, don't send view updates to webkit
-    private boolean mBlockWebkitViewMessages = false;
-
-    // cached value used to determine if we need to switch drawing models
-    private boolean mHardwareAccelSkia = false;
-
-    /*
-     * Private message ids
-     */
-    private static final int REMEMBER_PASSWORD          = 1;
-    private static final int NEVER_REMEMBER_PASSWORD    = 2;
-    private static final int SWITCH_TO_SHORTPRESS       = 3;
-    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 DRAG_HELD_MOTIONLESS       = 8;
-    private static final int AWAKEN_SCROLL_BARS         = 9;
-    private static final int PREVENT_DEFAULT_TIMEOUT    = 10;
-    private static final int SCROLL_SELECT_TEXT         = 11;
-
-
-    private static final int FIRST_PRIVATE_MSG_ID = REMEMBER_PASSWORD;
-    private static final int LAST_PRIVATE_MSG_ID = SCROLL_SELECT_TEXT;
-
-    /*
-     * Package message ids
-     */
-    static final int SCROLL_TO_MSG_ID                   = 101;
-    static final int NEW_PICTURE_MSG_ID                 = 105;
-    static final int UPDATE_TEXT_ENTRY_MSG_ID           = 106;
-    static final int WEBCORE_INITIALIZED_MSG_ID         = 107;
-    static final int UPDATE_TEXTFIELD_TEXT_MSG_ID       = 108;
-    static final int UPDATE_ZOOM_RANGE                  = 109;
-    static final int UNHANDLED_NAV_KEY                  = 110;
-    static final int CLEAR_TEXT_ENTRY                   = 111;
-    static final int UPDATE_TEXT_SELECTION_MSG_ID       = 112;
-    static final int SHOW_RECT_MSG_ID                   = 113;
-    static final int LONG_PRESS_CENTER                  = 114;
-    static final int PREVENT_TOUCH_ID                   = 115;
-    static final int WEBCORE_NEED_TOUCH_EVENTS          = 116;
-    // obj=Rect in doc coordinates
-    static final int INVAL_RECT_MSG_ID                  = 117;
-    static final int REQUEST_KEYBOARD                   = 118;
-    static final int DO_MOTION_UP                       = 119;
-    static final int SHOW_FULLSCREEN                    = 120;
-    static final int HIDE_FULLSCREEN                    = 121;
-    static final int DOM_FOCUS_CHANGED                  = 122;
-    static final int REPLACE_BASE_CONTENT               = 123;
-    static final int FORM_DID_BLUR                      = 124;
-    static final int RETURN_LABEL                       = 125;
-    static final int UPDATE_MATCH_COUNT                 = 126;
-    static final int CENTER_FIT_RECT                    = 127;
-    static final int REQUEST_KEYBOARD_WITH_SELECTION_MSG_ID = 128;
-    static final int SET_SCROLLBAR_MODES                = 129;
-    static final int SELECTION_STRING_CHANGED           = 130;
-    static final int HIT_TEST_RESULT                    = 131;
-    static final int SAVE_WEBARCHIVE_FINISHED           = 132;
-
-    static final int SET_AUTOFILLABLE                   = 133;
-    static final int AUTOFILL_COMPLETE                  = 134;
-
-    static final int SELECT_AT                          = 135;
-    static final int SCREEN_ON                          = 136;
-    static final int ENTER_FULLSCREEN_VIDEO             = 137;
-    static final int UPDATE_SELECTION                   = 138;
-    static final int UPDATE_ZOOM_DENSITY                = 139;
-    static final int EXIT_FULLSCREEN_VIDEO              = 140;
-
-    static final int COPY_TO_CLIPBOARD                  = 141;
-    static final int INIT_EDIT_FIELD                    = 142;
-    static final int REPLACE_TEXT                       = 143;
-    static final int CLEAR_CARET_HANDLE                 = 144;
-    static final int KEY_PRESS                          = 145;
-
-    private static final int FIRST_PACKAGE_MSG_ID = SCROLL_TO_MSG_ID;
-    private static final int LAST_PACKAGE_MSG_ID = HIT_TEST_RESULT;
-
-    static final String[] HandlerPrivateDebugString = {
-        "REMEMBER_PASSWORD", //              = 1;
-        "NEVER_REMEMBER_PASSWORD", //        = 2;
-        "SWITCH_TO_SHORTPRESS", //           = 3;
-        "SWITCH_TO_LONGPRESS", //            = 4;
-        "RELEASE_SINGLE_TAP", //             = 5;
-        "REQUEST_FORM_DATA", //              = 6;
-        "RESUME_WEBCORE_PRIORITY", //        = 7;
-        "DRAG_HELD_MOTIONLESS", //           = 8;
-        "AWAKEN_SCROLL_BARS", //             = 9;
-        "PREVENT_DEFAULT_TIMEOUT", //        = 10;
-        "SCROLL_SELECT_TEXT" //              = 11;
-    };
-
-    static final String[] HandlerPackageDebugString = {
-        "SCROLL_TO_MSG_ID", //               = 101;
-        "102", //                            = 102;
-        "103", //                            = 103;
-        "104", //                            = 104;
-        "NEW_PICTURE_MSG_ID", //             = 105;
-        "UPDATE_TEXT_ENTRY_MSG_ID", //       = 106;
-        "WEBCORE_INITIALIZED_MSG_ID", //     = 107;
-        "UPDATE_TEXTFIELD_TEXT_MSG_ID", //   = 108;
-        "UPDATE_ZOOM_RANGE", //              = 109;
-        "UNHANDLED_NAV_KEY", //              = 110;
-        "CLEAR_TEXT_ENTRY", //               = 111;
-        "UPDATE_TEXT_SELECTION_MSG_ID", //   = 112;
-        "SHOW_RECT_MSG_ID", //               = 113;
-        "LONG_PRESS_CENTER", //              = 114;
-        "PREVENT_TOUCH_ID", //               = 115;
-        "WEBCORE_NEED_TOUCH_EVENTS", //      = 116;
-        "INVAL_RECT_MSG_ID", //              = 117;
-        "REQUEST_KEYBOARD", //               = 118;
-        "DO_MOTION_UP", //                   = 119;
-        "SHOW_FULLSCREEN", //                = 120;
-        "HIDE_FULLSCREEN", //                = 121;
-        "DOM_FOCUS_CHANGED", //              = 122;
-        "REPLACE_BASE_CONTENT", //           = 123;
-        "FORM_DID_BLUR", //                  = 124;
-        "RETURN_LABEL", //                   = 125;
-        "UPDATE_MATCH_COUNT", //             = 126;
-        "CENTER_FIT_RECT", //                = 127;
-        "REQUEST_KEYBOARD_WITH_SELECTION_MSG_ID", // = 128;
-        "SET_SCROLLBAR_MODES", //            = 129;
-        "SELECTION_STRING_CHANGED", //       = 130;
-        "SET_TOUCH_HIGHLIGHT_RECTS", //      = 131;
-        "SAVE_WEBARCHIVE_FINISHED", //       = 132;
-        "SET_AUTOFILLABLE", //               = 133;
-        "AUTOFILL_COMPLETE", //              = 134;
-        "SELECT_AT", //                      = 135;
-        "SCREEN_ON", //                      = 136;
-        "ENTER_FULLSCREEN_VIDEO", //         = 137;
-        "UPDATE_SELECTION", //               = 138;
-        "UPDATE_ZOOM_DENSITY" //             = 139;
-    };
-
-    // If the site doesn't use the viewport meta tag to specify the viewport,
-    // use DEFAULT_VIEWPORT_WIDTH as the default viewport width
-    static final int DEFAULT_VIEWPORT_WIDTH = 980;
-
-    // normally we try to fit the content to the minimum preferred width
-    // calculated by the Webkit. To avoid the bad behavior when some site's
-    // minimum preferred width keeps growing when changing the viewport width or
-    // the minimum preferred width is huge, an upper limit is needed.
-    static int sMaxViewportWidth = DEFAULT_VIEWPORT_WIDTH;
-
-    // initial scale in percent. 0 means using default.
-    private int mInitialScaleInPercent = 0;
-
-    // Whether or not a scroll event should be sent to webkit.  This is only set
-    // to false when restoring the scroll position.
-    private boolean mSendScrollEvent = true;
-
-    private int mSnapScrollMode = SNAP_NONE;
-    private static final int SNAP_NONE = 0;
-    private static final int SNAP_LOCK = 1; // not a separate state
-    private static final int SNAP_X = 2; // may be combined with SNAP_LOCK
-    private static final int SNAP_Y = 4; // may be combined with SNAP_LOCK
-    private boolean mSnapPositive;
-
-    // keep these in sync with their counterparts in WebView.cpp
-    private static final int DRAW_EXTRAS_NONE = 0;
-    private static final int DRAW_EXTRAS_SELECTION = 1;
-    private static final int DRAW_EXTRAS_CURSOR_RING = 2;
-
-    // keep this in sync with WebCore:ScrollbarMode in WebKit
-    private static final int SCROLLBAR_AUTO = 0;
-    private static final int SCROLLBAR_ALWAYSOFF = 1;
-    // as we auto fade scrollbar, this is ignored.
-    private static final int SCROLLBAR_ALWAYSON = 2;
-    private int mHorizontalScrollBarMode = SCROLLBAR_AUTO;
-    private int mVerticalScrollBarMode = SCROLLBAR_AUTO;
-
-    // constants for determining script injection strategy
-    private static final int ACCESSIBILITY_SCRIPT_INJECTION_UNDEFINED = -1;
-    private static final int ACCESSIBILITY_SCRIPT_INJECTION_OPTED_OUT = 0;
-    private static final int ACCESSIBILITY_SCRIPT_INJECTION_PROVIDED = 1;
-
-    // the alias via which accessibility JavaScript interface is exposed
-    private static final String ALIAS_ACCESSIBILITY_JS_INTERFACE = "accessibility";
-
-    // Template for JavaScript that injects a screen-reader.
-    private static final String ACCESSIBILITY_SCREEN_READER_JAVASCRIPT_TEMPLATE =
-        "javascript:(function() {" +
-        "    var chooser = document.createElement('script');" +
-        "    chooser.type = 'text/javascript';" +
-        "    chooser.src = '%1s';" +
-        "    document.getElementsByTagName('head')[0].appendChild(chooser);" +
-        "  })();";
-
-    // Regular expression that matches the "axs" URL parameter.
-    // The value of 0 means the accessibility script is opted out
-    // The value of 1 means the accessibility script is already injected
-    private static final String PATTERN_MATCH_AXS_URL_PARAMETER = "(\\?axs=(0|1))|(&axs=(0|1))";
-
-    // TextToSpeech instance exposed to JavaScript to the injected screenreader.
-    private TextToSpeech mTextToSpeech;
-
-    // variable to cache the above pattern in case accessibility is enabled.
-    private Pattern mMatchAxsUrlParameterPattern;
-
-    /**
-     * Max distance to overscroll by in pixels.
-     * This how far content can be pulled beyond its normal bounds by the user.
-     */
-    private int mOverscrollDistance;
-
-    /**
-     * Max distance to overfling by in pixels.
-     * This is how far flinged content can move beyond the end of its normal bounds.
-     */
-    private int mOverflingDistance;
-
-    private OverScrollGlow mOverScrollGlow;
-
-    // Used to match key downs and key ups
-    private Vector<Integer> mKeysPressed;
-
-    /* package */ static boolean mLogEvent = true;
-
-    // for event log
-    private long mLastTouchUpTime = 0;
-
-    private WebViewCore.AutoFillData mAutoFillData;
-
-    private static boolean sNotificationsEnabled = true;
-
     /**
      * URI scheme for telephone number
      */
@@ -1353,26 +310,6 @@
      */
     public static final String SCHEME_GEO = "geo:0,0?q=";
 
-    private int mBackgroundColor = Color.WHITE;
-
-    private static final long SELECT_SCROLL_INTERVAL = 1000 / 60; // 60 / second
-    private int mAutoScrollX = 0;
-    private int mAutoScrollY = 0;
-    private int mMinAutoScrollX = 0;
-    private int mMaxAutoScrollX = 0;
-    private int mMinAutoScrollY = 0;
-    private int mMaxAutoScrollY = 0;
-    private Rect mScrollingLayerBounds = new Rect();
-    private boolean mSentAutoScrollMessage = false;
-
-    // used for serializing asynchronously handled touch events.
-    private final TouchEventQueue mTouchEventQueue = new TouchEventQueue();
-
-    // Used to track whether picture updating was paused due to a window focus change.
-    private boolean mPictureUpdatePausedForFocusChange = false;
-
-    // Used to notify listeners of a new picture.
-    private PictureListener mPictureListener;
     /**
      * Interface to listen for new pictures as they change.
      * @deprecated This interface is now obsolete.
@@ -1440,15 +377,24 @@
         private int mType;
         private String mExtra;
 
-        HitTestResult() {
+        /**
+         * @hide Only for use by WebViewProvider implementations
+         */
+        public HitTestResult() {
             mType = UNKNOWN_TYPE;
         }
 
-        private void setType(int type) {
+        /**
+         * @hide Only for use by WebViewProvider implementations
+         */
+        public void setType(int type) {
             mType = type;
         }
 
-        private void setExtra(String extra) {
+        /**
+         * @hide Only for use by WebViewProvider implementations
+         */
+        public void setExtra(String extra) {
             mExtra = extra;
         }
 
@@ -1471,15 +417,6 @@
     }
 
     /**
-     * Refer to {@link WebView#requestFocusNodeHref(Message)} for more information
-     */
-    static class FocusNodeHref {
-        static final String TITLE = "title";
-        static final String URL = "url";
-        static final String SRC = "src";
-    }
-
-    /**
      * Construct a new WebView with a Context object.
      * @param context A Context object used to access application assets.
      */
@@ -1529,418 +466,20 @@
      * @param javaScriptInterfaces is a Map of interface names, as keys, and
      * object implementing those interfaces, as values.
      * @param privateBrowsing If true the web view will be initialized in private mode.
-     * @hide This is an implementation detail.
+     * @hide This is used internally by dumprendertree, as it requires the javaScript interfaces to
+     * be added synchronously, before a subsequent loadUrl call takes effect.
      */
+    @SuppressWarnings("deprecation")  // for super() call into deprecated base class constructor.
     protected WebView(Context context, AttributeSet attrs, int defStyle,
             Map<String, Object> javaScriptInterfaces, boolean privateBrowsing) {
         super(context, attrs, defStyle);
-        checkThread();
-
         if (context == null) {
             throw new IllegalArgumentException("Invalid context argument");
         }
+        checkThread();
 
-        // Used by the chrome stack to find application paths
-        JniUtil.setContext(context);
-
-        mCallbackProxy = new CallbackProxy(context, this);
-        mViewManager = new ViewManager(this);
-        L10nUtils.setApplicationContext(context.getApplicationContext());
-        mWebViewCore = new WebViewCore(context, this, mCallbackProxy, javaScriptInterfaces);
-        mDatabase = WebViewDatabase.getInstance(context);
-        mScroller = new OverScroller(context, null, 0, 0, false); //TODO Use OverScroller's flywheel
-        mZoomManager = new ZoomManager(this, mCallbackProxy);
-
-        /* The init method must follow the creation of certain member variables,
-         * such as the mZoomManager.
-         */
-        init();
-        setupPackageListener(context);
-        setupProxyListener(context);
-        setupTrustStorageListener(context);
-        updateMultiTouchSupport(context);
-
-        if (privateBrowsing) {
-            startPrivateBrowsing();
-        }
-
-        mAutoFillData = new WebViewCore.AutoFillData();
-    }
-
-    private static class TrustStorageListener extends BroadcastReceiver {
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            if (intent.getAction().equals(KeyChain.ACTION_STORAGE_CHANGED)) {
-                handleCertTrustChanged();
-            }
-        }
-    }
-    private static TrustStorageListener sTrustStorageListener;
-
-    /**
-     * Handles update to the trust storage.
-     */
-    private static void handleCertTrustChanged() {
-        // send a message for indicating trust storage change
-        WebViewCore.sendStaticMessage(EventHub.TRUST_STORAGE_UPDATED, null);
-    }
-
-    /*
-     * @param context This method expects this to be a valid context.
-     */
-    private static void setupTrustStorageListener(Context context) {
-        if (sTrustStorageListener != null ) {
-            return;
-        }
-        IntentFilter filter = new IntentFilter();
-        filter.addAction(KeyChain.ACTION_STORAGE_CHANGED);
-        sTrustStorageListener = new TrustStorageListener();
-        Intent current =
-            context.getApplicationContext().registerReceiver(sTrustStorageListener, filter);
-        if (current != null) {
-            handleCertTrustChanged();
-        }
-    }
-
-    private static class ProxyReceiver extends BroadcastReceiver {
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            if (intent.getAction().equals(Proxy.PROXY_CHANGE_ACTION)) {
-                handleProxyBroadcast(intent);
-            }
-        }
-    }
-
-    /*
-     * Receiver for PROXY_CHANGE_ACTION, will be null when it is not added handling broadcasts.
-     */
-    private static ProxyReceiver sProxyReceiver;
-
-    /*
-     * @param context This method expects this to be a valid context
-     */
-    private static synchronized void setupProxyListener(Context context) {
-        if (sProxyReceiver != null || sNotificationsEnabled == false) {
-            return;
-        }
-        IntentFilter filter = new IntentFilter();
-        filter.addAction(Proxy.PROXY_CHANGE_ACTION);
-        sProxyReceiver = new ProxyReceiver();
-        Intent currentProxy = context.getApplicationContext().registerReceiver(
-                sProxyReceiver, filter);
-        if (currentProxy != null) {
-            handleProxyBroadcast(currentProxy);
-        }
-    }
-
-    /*
-     * @param context This method expects this to be a valid context
-     */
-    private static synchronized void disableProxyListener(Context context) {
-        if (sProxyReceiver == null)
-            return;
-
-        context.getApplicationContext().unregisterReceiver(sProxyReceiver);
-        sProxyReceiver = null;
-    }
-
-    private static void handleProxyBroadcast(Intent intent) {
-        ProxyProperties proxyProperties = (ProxyProperties)intent.getExtra(Proxy.EXTRA_PROXY_INFO);
-        if (proxyProperties == null || proxyProperties.getHost() == null) {
-            WebViewCore.sendStaticMessage(EventHub.PROXY_CHANGED, null);
-            return;
-        }
-        WebViewCore.sendStaticMessage(EventHub.PROXY_CHANGED, proxyProperties);
-    }
-
-    /*
-     * A variable to track if there is a receiver added for ACTION_PACKAGE_ADDED
-     * or ACTION_PACKAGE_REMOVED.
-     */
-    private static boolean sPackageInstallationReceiverAdded = false;
-
-    /*
-     * A set of Google packages we monitor for the
-     * navigator.isApplicationInstalled() API. Add additional packages as
-     * needed.
-     */
-    private static Set<String> sGoogleApps;
-    static {
-        sGoogleApps = new HashSet<String>();
-        sGoogleApps.add("com.google.android.youtube");
-    }
-
-    private static class PackageListener extends BroadcastReceiver {
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            final String action = intent.getAction();
-            final String packageName = intent.getData().getSchemeSpecificPart();
-            final boolean replacing = intent.getBooleanExtra(Intent.EXTRA_REPLACING, false);
-            if (Intent.ACTION_PACKAGE_REMOVED.equals(action) && replacing) {
-                // if it is replacing, refreshPlugins() when adding
-                return;
-            }
-
-            if (sGoogleApps.contains(packageName)) {
-                if (Intent.ACTION_PACKAGE_ADDED.equals(action)) {
-                    WebViewCore.sendStaticMessage(EventHub.ADD_PACKAGE_NAME, packageName);
-                } else {
-                    WebViewCore.sendStaticMessage(EventHub.REMOVE_PACKAGE_NAME, packageName);
-                }
-            }
-
-            PluginManager pm = PluginManager.getInstance(context);
-            if (pm.containsPluginPermissionAndSignatures(packageName)) {
-                pm.refreshPlugins(Intent.ACTION_PACKAGE_ADDED.equals(action));
-            }
-        }
-    }
-
-    private void setupPackageListener(Context context) {
-
-        /*
-         * we must synchronize the instance check and the creation of the
-         * receiver to ensure that only ONE receiver exists for all WebView
-         * instances.
-         */
-        synchronized (WebView.class) {
-
-            // if the receiver already exists then we do not need to register it
-            // again
-            if (sPackageInstallationReceiverAdded) {
-                return;
-            }
-
-            IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);
-            filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
-            filter.addDataScheme("package");
-            BroadcastReceiver packageListener = new PackageListener();
-            context.getApplicationContext().registerReceiver(packageListener, filter);
-            sPackageInstallationReceiverAdded = true;
-        }
-
-        // check if any of the monitored apps are already installed
-        AsyncTask<Void, Void, Set<String>> task = new AsyncTask<Void, Void, Set<String>>() {
-
-            @Override
-            protected Set<String> doInBackground(Void... unused) {
-                Set<String> installedPackages = new HashSet<String>();
-                PackageManager pm = mContext.getPackageManager();
-                for (String name : sGoogleApps) {
-                    try {
-                        pm.getPackageInfo(name,
-                                PackageManager.GET_ACTIVITIES | PackageManager.GET_SERVICES);
-                        installedPackages.add(name);
-                    } catch (PackageManager.NameNotFoundException e) {
-                        // package not found
-                    }
-                }
-                return installedPackages;
-            }
-
-            // Executes on the UI thread
-            @Override
-            protected void onPostExecute(Set<String> installedPackages) {
-                if (mWebViewCore != null) {
-                    mWebViewCore.sendMessage(EventHub.ADD_PACKAGE_NAMES, installedPackages);
-                }
-            }
-        };
-        task.execute();
-    }
-
-    void updateMultiTouchSupport(Context context) {
-        mZoomManager.updateMultiTouchSupport(context);
-    }
-
-    private void init() {
-        OnTrimMemoryListener.init(getContext());
-        sDisableNavcache = nativeDisableNavcache();
-        setWillNotDraw(false);
-        setFocusable(true);
-        setFocusableInTouchMode(true);
-        setClickable(true);
-        setLongClickable(true);
-
-        final ViewConfiguration configuration = ViewConfiguration.get(getContext());
-        int slop = configuration.getScaledTouchSlop();
-        mTouchSlopSquare = slop * slop;
-        slop = configuration.getScaledDoubleTapSlop();
-        mDoubleTapSlopSquare = slop * slop;
-        final float density = getContext().getResources().getDisplayMetrics().density;
-        // use one line height, 16 based on our current default font, for how
-        // far we allow a touch be away from the edge of a link
-        mNavSlop = (int) (16 * density);
-        mZoomManager.init(density);
-        mMaximumFling = configuration.getScaledMaximumFlingVelocity();
-
-        // Compute the inverse of the density squared.
-        DRAG_LAYER_INVERSE_DENSITY_SQUARED = 1 / (density * density);
-
-        mOverscrollDistance = configuration.getScaledOverscrollDistance();
-        mOverflingDistance = configuration.getScaledOverflingDistance();
-
-        setScrollBarStyle(super.getScrollBarStyle());
-        // Initially use a size of two, since the user is likely to only hold
-        // down two keys at a time (shift + another key)
-        mKeysPressed = new Vector<Integer>(2);
-        mHTML5VideoViewProxy = null ;
-    }
-
-    @Override
-    public boolean shouldDelayChildPressedState() {
-        return true;
-    }
-
-    /**
-     * Adds accessibility APIs to JavaScript.
-     *
-     * Note: This method is responsible to performing the necessary
-     *       check if the accessibility APIs should be exposed.
-     */
-    private void addAccessibilityApisToJavaScript() {
-        if (AccessibilityManager.getInstance(mContext).isEnabled()
-                && getSettings().getJavaScriptEnabled()) {
-            // exposing the TTS for now ...
-            final Context ctx = getContext();
-            if (ctx != null) {
-                final String packageName = ctx.getPackageName();
-                if (packageName != null) {
-                    mTextToSpeech = new TextToSpeech(getContext(), null, null,
-                            packageName + ".**webview**", true);
-                    addJavascriptInterface(mTextToSpeech, ALIAS_ACCESSIBILITY_JS_INTERFACE);
-                }
-            }
-        }
-    }
-
-    /**
-     * Removes accessibility APIs from JavaScript.
-     */
-    private void removeAccessibilityApisFromJavaScript() {
-        // exposing the TTS for now ...
-        if (mTextToSpeech != null) {
-            removeJavascriptInterface(ALIAS_ACCESSIBILITY_JS_INTERFACE);
-            mTextToSpeech.shutdown();
-            mTextToSpeech = null;
-        }
-    }
-
-    @Override
-    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
-        super.onInitializeAccessibilityNodeInfo(info);
-        info.setScrollable(isScrollableForAccessibility());
-    }
-
-    @Override
-    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
-        super.onInitializeAccessibilityEvent(event);
-        event.setScrollable(isScrollableForAccessibility());
-        event.setScrollX(mScrollX);
-        event.setScrollY(mScrollY);
-        final int convertedContentWidth = contentToViewX(getContentWidth());
-        final int adjustedViewWidth = getWidth() - mPaddingLeft - mPaddingRight;
-        event.setMaxScrollX(Math.max(convertedContentWidth - adjustedViewWidth, 0));
-        final int convertedContentHeight = contentToViewY(getContentHeight());
-        final int adjustedViewHeight = getHeight() - mPaddingTop - mPaddingBottom;
-        event.setMaxScrollY(Math.max(convertedContentHeight - adjustedViewHeight, 0));
-    }
-
-    private boolean isScrollableForAccessibility() {
-        return (contentToViewX(getContentWidth()) > getWidth() - mPaddingLeft - mPaddingRight
-                || contentToViewY(getContentHeight()) > getHeight() - mPaddingTop - mPaddingBottom);
-    }
-
-    @Override
-    public void setOverScrollMode(int mode) {
-        super.setOverScrollMode(mode);
-        if (mode != OVER_SCROLL_NEVER) {
-            if (mOverScrollGlow == null) {
-                mOverScrollGlow = new OverScrollGlow(this);
-            }
-        } else {
-            mOverScrollGlow = null;
-        }
-    }
-
-    /* package */ void adjustDefaultZoomDensity(int zoomDensity) {
-        final float density = mContext.getResources().getDisplayMetrics().density
-                * 100 / zoomDensity;
-        updateDefaultZoomDensity(density);
-    }
-
-    /* package */ void updateDefaultZoomDensity(float density) {
-        mNavSlop = (int) (16 * density);
-        mZoomManager.updateDefaultZoomDensity(density);
-    }
-
-    /* package */ boolean onSavePassword(String schemePlusHost, String username,
-            String password, final Message resumeMsg) {
-       boolean rVal = false;
-       if (resumeMsg == null) {
-           // null resumeMsg implies saving password silently
-           mDatabase.setUsernamePassword(schemePlusHost, username, password);
-       } else {
-            final Message remember = mPrivateHandler.obtainMessage(
-                    REMEMBER_PASSWORD);
-            remember.getData().putString("host", schemePlusHost);
-            remember.getData().putString("username", username);
-            remember.getData().putString("password", password);
-            remember.obj = resumeMsg;
-
-            final Message neverRemember = mPrivateHandler.obtainMessage(
-                    NEVER_REMEMBER_PASSWORD);
-            neverRemember.getData().putString("host", schemePlusHost);
-            neverRemember.getData().putString("username", username);
-            neverRemember.getData().putString("password", password);
-            neverRemember.obj = resumeMsg;
-
-            new AlertDialog.Builder(getContext())
-                    .setTitle(com.android.internal.R.string.save_password_label)
-                    .setMessage(com.android.internal.R.string.save_password_message)
-                    .setPositiveButton(com.android.internal.R.string.save_password_notnow,
-                    new DialogInterface.OnClickListener() {
-                        @Override
-                        public void onClick(DialogInterface dialog, int which) {
-                            resumeMsg.sendToTarget();
-                        }
-                    })
-                    .setNeutralButton(com.android.internal.R.string.save_password_remember,
-                    new DialogInterface.OnClickListener() {
-                        @Override
-                        public void onClick(DialogInterface dialog, int which) {
-                            remember.sendToTarget();
-                        }
-                    })
-                    .setNegativeButton(com.android.internal.R.string.save_password_never,
-                    new DialogInterface.OnClickListener() {
-                        @Override
-                        public void onClick(DialogInterface dialog, int which) {
-                            neverRemember.sendToTarget();
-                        }
-                    })
-                    .setOnCancelListener(new OnCancelListener() {
-                        @Override
-                        public void onCancel(DialogInterface dialog) {
-                            resumeMsg.sendToTarget();
-                        }
-                    }).show();
-            // Return true so that WebViewCore will pause while the dialog is
-            // up.
-            rVal = true;
-        }
-       return rVal;
-    }
-
-    @Override
-    public void setScrollBarStyle(int style) {
-        if (style == View.SCROLLBARS_INSIDE_INSET
-                || style == View.SCROLLBARS_OUTSIDE_INSET) {
-            mOverlayHorizontalScrollbar = mOverlayVerticalScrollbar = false;
-        } else {
-            mOverlayHorizontalScrollbar = mOverlayVerticalScrollbar = true;
-        }
-        super.setScrollBarStyle(style);
+        ensureProviderCreated();
+        mProvider.init(javaScriptInterfaces, privateBrowsing);
     }
 
     /**
@@ -1949,7 +488,7 @@
      */
     public void setHorizontalScrollbarOverlay(boolean overlay) {
         checkThread();
-        mOverlayHorizontalScrollbar = overlay;
+        mProvider.setHorizontalScrollbarOverlay(overlay);
     }
 
     /**
@@ -1958,7 +497,7 @@
      */
     public void setVerticalScrollbarOverlay(boolean overlay) {
         checkThread();
-        mOverlayVerticalScrollbar = overlay;
+        mProvider.setVerticalScrollbarOverlay(overlay);
     }
 
     /**
@@ -1967,7 +506,7 @@
      */
     public boolean overlayHorizontalScrollbar() {
         checkThread();
-        return mOverlayHorizontalScrollbar;
+        return mProvider.overlayHorizontalScrollbar();
     }
 
     /**
@@ -1976,80 +515,17 @@
      */
     public boolean overlayVerticalScrollbar() {
         checkThread();
-        return mOverlayVerticalScrollbar;
-    }
-
-    /*
-     * Return the width of the view where the content of WebView should render
-     * to.
-     * Note: this can be called from WebCoreThread.
-     */
-    /* package */ int getViewWidth() {
-        if (!isVerticalScrollBarEnabled() || mOverlayVerticalScrollbar) {
-            return getWidth();
-        } else {
-            return Math.max(0, getWidth() - getVerticalScrollbarWidth());
-        }
-    }
-
-    /**
-     * Returns the height (in pixels) of the embedded title bar (if any). Does not care about
-     * scrolling
-     * @hide
-     */
-    protected int getTitleHeight() {
-        return mTitleBar != null ? mTitleBar.getHeight() : 0;
+        return mProvider.overlayVerticalScrollbar();
     }
 
     /**
      * Return the visible height (in pixels) of the embedded title bar (if any).
      *
-     * @return This method is obsolete and always returns 0.
      * @deprecated This method is now obsolete.
      */
-    @Deprecated
     public int getVisibleTitleHeight() {
-        // Actually, this method returns the height of the embedded title bar if one is set via the
-        // hidden setEmbeddedTitleBar method.
         checkThread();
-        return getVisibleTitleHeightImpl();
-    }
-
-    private int getVisibleTitleHeightImpl() {
-        // need to restrict mScrollY due to over scroll
-        return Math.max(getTitleHeight() - Math.max(0, mScrollY),
-                getOverlappingActionModeHeight());
-    }
-
-    private int mCachedOverlappingActionModeHeight = -1;
-
-    private int getOverlappingActionModeHeight() {
-        if (mFindCallback == null) {
-            return 0;
-        }
-        if (mCachedOverlappingActionModeHeight < 0) {
-            getGlobalVisibleRect(mGlobalVisibleRect, mGlobalVisibleOffset);
-            mCachedOverlappingActionModeHeight = Math.max(0,
-                    mFindCallback.getActionModeGlobalBottom() - mGlobalVisibleRect.top);
-        }
-        return mCachedOverlappingActionModeHeight;
-    }
-
-    /*
-     * Return the height of the view where the content of WebView should render
-     * to.  Note that this excludes mTitleBar, if there is one.
-     * Note: this can be called from WebCoreThread.
-     */
-    /* package */ int getViewHeight() {
-        return getViewHeightWithTitle() - getVisibleTitleHeightImpl();
-    }
-
-    int getViewHeightWithTitle() {
-        int height = getHeight();
-        if (isHorizontalScrollBarEnabled() && !mOverlayHorizontalScrollbar) {
-            height -= getHorizontalScrollbarHeight();
-        }
-        return height;
+        return mProvider.getVisibleTitleHeight();
     }
 
     /**
@@ -2058,7 +534,7 @@
      */
     public SslCertificate getCertificate() {
         checkThread();
-        return mCertificate;
+        return mProvider.getCertificate();
     }
 
     /**
@@ -2066,11 +542,7 @@
      */
     public void setCertificate(SslCertificate certificate) {
         checkThread();
-        if (DebugFlags.WEB_VIEW) {
-            Log.v(LOGTAG, "setCertificate=" + certificate);
-        }
-        // here, the certificate can be null (if the site is not secure)
-        mCertificate = certificate;
+        mProvider.setCertificate(certificate);
     }
 
     //-------------------------------------------------------------------------
@@ -2086,7 +558,7 @@
      */
     public void savePassword(String host, String username, String password) {
         checkThread();
-        mDatabase.setUsernamePassword(host, username, password);
+        mProvider.savePassword(host, username, password);
     }
 
     /**
@@ -2101,7 +573,7 @@
     public void setHttpAuthUsernamePassword(String host, String realm,
             String username, String password) {
         checkThread();
-        mDatabase.setHttpAuthUsernamePassword(host, realm, username, password);
+        mProvider.setHttpAuthUsernamePassword(host, realm, username, password);
     }
 
     /**
@@ -2115,38 +587,7 @@
      */
     public String[] getHttpAuthUsernamePassword(String host, String realm) {
         checkThread();
-        return mDatabase.getHttpAuthUsernamePassword(host, realm);
-    }
-
-    /**
-     * Remove Find or Select ActionModes, if active.
-     */
-    private void clearActionModes() {
-        if (mSelectCallback != null) {
-            mSelectCallback.finish();
-        }
-        if (mFindCallback != null) {
-            mFindCallback.finish();
-        }
-    }
-
-    /**
-     * Called to clear state when moving from one page to another, or changing
-     * in some other way that makes elements associated with the current page
-     * (such as WebTextView or ActionModes) no longer relevant.
-     */
-    private void clearHelpers() {
-        clearTextEntry();
-        clearActionModes();
-        dismissFullScreenMode();
-        cancelSelectDialog();
-    }
-
-    private void cancelSelectDialog() {
-        if (mListBoxDialog != null) {
-            mListBoxDialog.cancel();
-            mListBoxDialog = null;
-        }
+        return mProvider.getHttpAuthUsernamePassword(host, realm);
     }
 
     /**
@@ -2156,45 +597,7 @@
      */
     public void destroy() {
         checkThread();
-        destroyImpl();
-    }
-
-    private void destroyImpl() {
-        clearHelpers();
-        if (mListBoxDialog != null) {
-            mListBoxDialog.dismiss();
-            mListBoxDialog = null;
-        }
-        // remove so that it doesn't cause events
-        if (mWebTextView != null) {
-            mWebTextView.remove();
-            mWebTextView = null;
-        }
-        if (mNativeClass != 0) nativeStopGL();
-        if (mWebViewCore != null) {
-            // Set the handlers to null before destroying WebViewCore so no
-            // more messages will be posted.
-            mCallbackProxy.setWebViewClient(null);
-            mCallbackProxy.setWebChromeClient(null);
-            // Tell WebViewCore to destroy itself
-            synchronized (this) {
-                WebViewCore webViewCore = mWebViewCore;
-                mWebViewCore = null; // prevent using partial webViewCore
-                webViewCore.destroy();
-            }
-            // Remove any pending messages that might not be serviced yet.
-            mPrivateHandler.removeCallbacksAndMessages(null);
-            mCallbackProxy.removeCallbacksAndMessages(null);
-            // Wake up the WebCore thread just in case it is waiting for a
-            // JavaScript dialog.
-            synchronized (mCallbackProxy) {
-                mCallbackProxy.notify();
-            }
-        }
-        if (mNativeClass != 0) {
-            nativeDestroy();
-            mNativeClass = 0;
-        }
+        mProvider.destroy();
     }
 
     /**
@@ -2206,12 +609,7 @@
     @Deprecated
     public static void enablePlatformNotifications() {
         checkThread();
-        synchronized (WebView.class) {
-            sNotificationsEnabled = true;
-            Context context = JniUtil.getContext();
-            if (context != null)
-                setupProxyListener(context);
-        }
+        getFactory().getStatics().setPlatformNotificationsEnabled(true);
     }
 
     /**
@@ -2223,24 +621,7 @@
     @Deprecated
     public static void disablePlatformNotifications() {
         checkThread();
-        synchronized (WebView.class) {
-            sNotificationsEnabled = false;
-            Context context = JniUtil.getContext();
-            if (context != null)
-                disableProxyListener(context);
-        }
-    }
-
-    /**
-     * Sets JavaScript engine flags.
-     *
-     * @param flags JS engine flags in a String
-     *
-     * @hide This is an implementation detail.
-     */
-    public void setJsFlags(String flags) {
-        checkThread();
-        mWebViewCore.sendMessage(EventHub.SET_JS_FLAGS, flags);
+        getFactory().getStatics().setPlatformNotificationsEnabled(false);
     }
 
     /**
@@ -2251,22 +632,10 @@
      */
     public void setNetworkAvailable(boolean networkUp) {
         checkThread();
-        mWebViewCore.sendMessage(EventHub.SET_NETWORK_STATE,
-                networkUp ? 1 : 0, 0);
+        mProvider.setNetworkAvailable(networkUp);
     }
 
     /**
-     * Inform WebView about the current network type.
-     * {@hide}
-     */
-    public void setNetworkType(String type, String subtype) {
-        checkThread();
-        Map<String, String> map = new HashMap<String, String>();
-        map.put("type", type);
-        map.put("subtype", subtype);
-        mWebViewCore.sendMessage(EventHub.SET_NETWORK_TYPE, map);
-    }
-    /**
      * Save the state of this WebView used in
      * {@link android.app.Activity#onSaveInstanceState}. Please note that this
      * method no longer stores the display data for this WebView. The previous
@@ -2281,49 +650,7 @@
      */
     public WebBackForwardList saveState(Bundle outState) {
         checkThread();
-        if (outState == null) {
-            return null;
-        }
-        // We grab a copy of the back/forward list because a client of WebView
-        // may have invalidated the history list by calling clearHistory.
-        WebBackForwardList list = copyBackForwardList();
-        final int currentIndex = list.getCurrentIndex();
-        final int size = list.getSize();
-        // We should fail saving the state if the list is empty or the index is
-        // not in a valid range.
-        if (currentIndex < 0 || currentIndex >= size || size == 0) {
-            return null;
-        }
-        outState.putInt("index", currentIndex);
-        // FIXME: This should just be a byte[][] instead of ArrayList but
-        // Parcel.java does not have the code to handle multi-dimensional
-        // arrays.
-        ArrayList<byte[]> history = new ArrayList<byte[]>(size);
-        for (int i = 0; i < size; i++) {
-            WebHistoryItem item = list.getItemAtIndex(i);
-            if (null == item) {
-                // FIXME: this shouldn't happen
-                // need to determine how item got set to null
-                Log.w(LOGTAG, "saveState: Unexpected null history item.");
-                return null;
-            }
-            byte[] data = item.getFlattenedData();
-            if (data == null) {
-                // It would be very odd to not have any data for a given history
-                // item. And we will fail to rebuild the history list without
-                // flattened data.
-                return null;
-            }
-            history.add(data);
-        }
-        outState.putSerializable("history", history);
-        if (mCertificate != null) {
-            outState.putBundle("certificate",
-                               SslCertificate.saveState(mCertificate));
-        }
-        outState.putBoolean("privateBrowsingEnabled", isPrivateBrowsingEnabled());
-        mZoomManager.saveZoomState(outState);
-        return list;
+        return mProvider.saveState(outState);
     }
 
     /**
@@ -2338,59 +665,7 @@
     @Deprecated
     public boolean savePicture(Bundle b, final File dest) {
         checkThread();
-        if (dest == null || b == null) {
-            return false;
-        }
-        final Picture p = capturePicture();
-        // Use a temporary file while writing to ensure the destination file
-        // contains valid data.
-        final File temp = new File(dest.getPath() + ".writing");
-        new Thread(new Runnable() {
-            @Override
-            public void run() {
-                FileOutputStream out = null;
-                try {
-                    out = new FileOutputStream(temp);
-                    p.writeToStream(out);
-                    // Writing the picture succeeded, rename the temporary file
-                    // to the destination.
-                    temp.renameTo(dest);
-                } catch (Exception e) {
-                    // too late to do anything about it.
-                } finally {
-                    if (out != null) {
-                        try {
-                            out.close();
-                        } catch (Exception e) {
-                            // Can't do anything about that
-                        }
-                    }
-                    temp.delete();
-                }
-            }
-        }).start();
-        // now update the bundle
-        b.putInt("scrollX", mScrollX);
-        b.putInt("scrollY", mScrollY);
-        mZoomManager.saveZoomState(b);
-        return true;
-    }
-
-    private void restoreHistoryPictureFields(Picture p, Bundle b) {
-        int sx = b.getInt("scrollX", 0);
-        int sy = b.getInt("scrollY", 0);
-
-        mDrawHistory = true;
-        mHistoryPicture = p;
-
-        mScrollX = sx;
-        mScrollY = sy;
-        mZoomManager.restoreZoomState(b);
-        final float scale = mZoomManager.getScale();
-        mHistoryWidth = Math.round(p.getWidth() * scale);
-        mHistoryHeight = Math.round(p.getHeight() * scale);
-
-        invalidate();
+        return mProvider.savePicture(b, dest);
     }
 
     /**
@@ -2406,91 +681,7 @@
     @Deprecated
     public boolean restorePicture(Bundle b, File src) {
         checkThread();
-        if (src == null || b == null) {
-            return false;
-        }
-        if (!src.exists()) {
-            return false;
-        }
-        try {
-            final FileInputStream in = new FileInputStream(src);
-            final Bundle copy = new Bundle(b);
-            new Thread(new Runnable() {
-                @Override
-                public void run() {
-                    try {
-                        final Picture p = Picture.createFromStream(in);
-                        if (p != null) {
-                            // Post a runnable on the main thread to update the
-                            // history picture fields.
-                            mPrivateHandler.post(new Runnable() {
-                                @Override
-                                public void run() {
-                                    restoreHistoryPictureFields(p, copy);
-                                }
-                            });
-                        }
-                    } finally {
-                        try {
-                            in.close();
-                        } catch (Exception e) {
-                            // Nothing we can do now.
-                        }
-                    }
-                }
-            }).start();
-        } catch (FileNotFoundException e){
-            e.printStackTrace();
-        }
-        return true;
-    }
-
-    /**
-     * Saves the view data to the output stream. The output is highly
-     * version specific, and may not be able to be loaded by newer versions
-     * of WebView.
-     * @param stream The {@link OutputStream} to save to
-     * @return True if saved successfully
-     * @hide
-     */
-    public boolean saveViewState(OutputStream stream) {
-        try {
-            return ViewStateSerializer.serializeViewState(stream, this);
-        } catch (IOException e) {
-            Log.w(LOGTAG, "Failed to saveViewState", e);
-        }
-        return false;
-    }
-
-    /**
-     * Loads the view data from the input stream. See
-     * {@link #saveViewState(OutputStream)} for more information.
-     * @param stream The {@link InputStream} to load from
-     * @return True if loaded successfully
-     * @hide
-     */
-    public boolean loadViewState(InputStream stream) {
-        try {
-            mLoadedPicture = ViewStateSerializer.deserializeViewState(stream, this);
-            mBlockWebkitViewMessages = true;
-            setNewPicture(mLoadedPicture, true);
-            mLoadedPicture.mViewState = null;
-            return true;
-        } catch (IOException e) {
-            Log.w(LOGTAG, "Failed to loadViewState", e);
-        }
-        return false;
-    }
-
-    /**
-     * Clears the view state set with {@link #loadViewState(InputStream)}.
-     * This WebView will then switch to showing the content from webkit
-     * @hide
-     */
-    public void clearViewState() {
-        mBlockWebkitViewMessages = false;
-        mLoadedPicture = null;
-        invalidate();
+        return mProvider.restorePicture(b, src);
     }
 
     /**
@@ -2509,55 +700,7 @@
      */
     public WebBackForwardList restoreState(Bundle inState) {
         checkThread();
-        WebBackForwardList returnList = null;
-        if (inState == null) {
-            return returnList;
-        }
-        if (inState.containsKey("index") && inState.containsKey("history")) {
-            mCertificate = SslCertificate.restoreState(
-                inState.getBundle("certificate"));
-
-            final WebBackForwardList list = mCallbackProxy.getBackForwardList();
-            final int index = inState.getInt("index");
-            // We can't use a clone of the list because we need to modify the
-            // shared copy, so synchronize instead to prevent concurrent
-            // modifications.
-            synchronized (list) {
-                final List<byte[]> history =
-                        (List<byte[]>) inState.getSerializable("history");
-                final int size = history.size();
-                // Check the index bounds so we don't crash in native code while
-                // restoring the history index.
-                if (index < 0 || index >= size) {
-                    return null;
-                }
-                for (int i = 0; i < size; i++) {
-                    byte[] data = history.remove(0);
-                    if (data == null) {
-                        // If we somehow have null data, we cannot reconstruct
-                        // the item and thus our history list cannot be rebuilt.
-                        return null;
-                    }
-                    WebHistoryItem item = new WebHistoryItem(data);
-                    list.addHistoryItem(item);
-                }
-                // Grab the most recent copy to return to the caller.
-                returnList = copyBackForwardList();
-                // Update the copy to have the correct index.
-                returnList.setCurrentIndex(index);
-            }
-            // Restore private browsing setting.
-            if (inState.getBoolean("privateBrowsingEnabled")) {
-                getSettings().setPrivateBrowsingEnabled(true);
-            }
-            mZoomManager.restoreZoomState(inState);
-            // Remove all pending messages because we are restoring previous
-            // state.
-            mWebViewCore.removeMessages();
-            // Send a restore state message.
-            mWebViewCore.sendMessage(EventHub.RESTORE_STATE, index);
-        }
-        return returnList;
+        return mProvider.restoreState(inState);
     }
 
     /**
@@ -2572,16 +715,7 @@
      */
     public void loadUrl(String url, Map<String, String> additionalHttpHeaders) {
         checkThread();
-        loadUrlImpl(url, additionalHttpHeaders);
-    }
-
-    private void loadUrlImpl(String url, Map<String, String> extraHeaders) {
-        switchOutDrawHistory();
-        WebViewCore.GetUrlData arg = new WebViewCore.GetUrlData();
-        arg.mUrl = url;
-        arg.mExtraHeaders = extraHeaders;
-        mWebViewCore.sendMessage(EventHub.LOAD_URL, arg);
-        clearHelpers();
+        mProvider.loadUrl(url, additionalHttpHeaders);
     }
 
     /**
@@ -2590,14 +724,7 @@
      */
     public void loadUrl(String url) {
         checkThread();
-        loadUrlImpl(url);
-    }
-
-    private void loadUrlImpl(String url) {
-        if (url == null) {
-            return;
-        }
-        loadUrlImpl(url, null);
+        mProvider.loadUrl(url);
     }
 
     /**
@@ -2610,16 +737,7 @@
      */
     public void postUrl(String url, byte[] postData) {
         checkThread();
-        if (URLUtil.isNetworkUrl(url)) {
-            switchOutDrawHistory();
-            WebViewCore.PostUrlData arg = new WebViewCore.PostUrlData();
-            arg.mUrl = url;
-            arg.mPostData = postData;
-            mWebViewCore.sendMessage(EventHub.POST_URL, arg);
-            clearHelpers();
-        } else {
-            loadUrlImpl(url);
-        }
+        mProvider.postUrl(url, postData);
     }
 
     /**
@@ -2650,18 +768,7 @@
      */
     public void loadData(String data, String mimeType, String encoding) {
         checkThread();
-        loadDataImpl(data, mimeType, encoding);
-    }
-
-    private void loadDataImpl(String data, String mimeType, String encoding) {
-        StringBuilder dataUrl = new StringBuilder("data:");
-        dataUrl.append(mimeType);
-        if ("base64".equals(encoding)) {
-            dataUrl.append(";base64");
-        }
-        dataUrl.append(",");
-        dataUrl.append(data);
-        loadUrlImpl(dataUrl.toString());
+        mProvider.loadData(data, mimeType, encoding);
     }
 
     /**
@@ -2689,20 +796,7 @@
     public void loadDataWithBaseURL(String baseUrl, String data,
             String mimeType, String encoding, String historyUrl) {
         checkThread();
-
-        if (baseUrl != null && baseUrl.toLowerCase().startsWith("data:")) {
-            loadDataImpl(data, mimeType, encoding);
-            return;
-        }
-        switchOutDrawHistory();
-        WebViewCore.BaseUrlData arg = new WebViewCore.BaseUrlData();
-        arg.mBaseUrl = baseUrl;
-        arg.mData = data;
-        arg.mMimeType = mimeType;
-        arg.mEncoding = encoding;
-        arg.mHistoryUrl = historyUrl;
-        mWebViewCore.sendMessage(EventHub.LOAD_DATA, arg);
-        clearHelpers();
+        mProvider.loadDataWithBaseURL(baseUrl, data, mimeType, encoding, historyUrl);
     }
 
     /**
@@ -2712,20 +806,7 @@
      */
     public void saveWebArchive(String filename) {
         checkThread();
-        saveWebArchiveImpl(filename, false, null);
-    }
-
-    /* package */ static class SaveWebArchiveMessage {
-        SaveWebArchiveMessage (String basename, boolean autoname, ValueCallback<String> callback) {
-            mBasename = basename;
-            mAutoname = autoname;
-            mCallback = callback;
-        }
-
-        /* package */ final String mBasename;
-        /* package */ final boolean mAutoname;
-        /* package */ final ValueCallback<String> mCallback;
-        /* package */ String mResultFile;
+        mProvider.saveWebArchive(filename);
     }
 
     /**
@@ -2742,13 +823,7 @@
      */
     public void saveWebArchive(String basename, boolean autoname, ValueCallback<String> callback) {
         checkThread();
-        saveWebArchiveImpl(basename, autoname, callback);
-    }
-
-    private void saveWebArchiveImpl(String basename, boolean autoname,
-            ValueCallback<String> callback) {
-        mWebViewCore.sendMessage(EventHub.SAVE_WEBARCHIVE,
-            new SaveWebArchiveMessage(basename, autoname, callback));
+        mProvider.saveWebArchive(basename, autoname, callback);
     }
 
     /**
@@ -2756,10 +831,7 @@
      */
     public void stopLoading() {
         checkThread();
-        // TODO: should we clear all the messages in the queue before sending
-        // STOP_LOADING?
-        switchOutDrawHistory();
-        mWebViewCore.sendMessage(EventHub.STOP_LOADING);
+        mProvider.stopLoading();
     }
 
     /**
@@ -2767,9 +839,7 @@
      */
     public void reload() {
         checkThread();
-        clearHelpers();
-        switchOutDrawHistory();
-        mWebViewCore.sendMessage(EventHub.RELOAD);
+        mProvider.reload();
     }
 
     /**
@@ -2778,14 +848,7 @@
      */
     public boolean canGoBack() {
         checkThread();
-        WebBackForwardList l = mCallbackProxy.getBackForwardList();
-        synchronized (l) {
-            if (l.getClearPending()) {
-                return false;
-            } else {
-                return l.getCurrentIndex() > 0;
-            }
-        }
+        return mProvider.canGoBack();
     }
 
     /**
@@ -2793,7 +856,7 @@
      */
     public void goBack() {
         checkThread();
-        goBackOrForwardImpl(-1);
+        mProvider.goBack();
     }
 
     /**
@@ -2802,14 +865,7 @@
      */
     public boolean canGoForward() {
         checkThread();
-        WebBackForwardList l = mCallbackProxy.getBackForwardList();
-        synchronized (l) {
-            if (l.getClearPending()) {
-                return false;
-            } else {
-                return l.getCurrentIndex() < l.getSize() - 1;
-            }
-        }
+        return mProvider.canGoForward();
     }
 
     /**
@@ -2817,7 +873,7 @@
      */
     public void goForward() {
         checkThread();
-        goBackOrForwardImpl(1);
+        mProvider.goForward();
     }
 
     /**
@@ -2828,15 +884,7 @@
      */
     public boolean canGoBackOrForward(int steps) {
         checkThread();
-        WebBackForwardList l = mCallbackProxy.getBackForwardList();
-        synchronized (l) {
-            if (l.getClearPending()) {
-                return false;
-            } else {
-                int newIndex = l.getCurrentIndex() + steps;
-                return newIndex >= 0 && newIndex < l.getSize();
-            }
-        }
+        return mProvider.canGoBackOrForward(steps);
     }
 
     /**
@@ -2848,19 +896,7 @@
      */
     public void goBackOrForward(int steps) {
         checkThread();
-        goBackOrForwardImpl(steps);
-    }
-
-    private void goBackOrForwardImpl(int steps) {
-        goBackOrForward(steps, false);
-    }
-
-    private void goBackOrForward(int steps, boolean ignoreSnapshot) {
-        if (steps != 0) {
-            clearHelpers();
-            mWebViewCore.sendMessage(EventHub.GO_BACK_FORWARD, steps,
-                    ignoreSnapshot ? 1 : 0);
-        }
+        mProvider.goBackOrForward(steps);
     }
 
     /**
@@ -2868,20 +904,7 @@
      */
     public boolean isPrivateBrowsingEnabled() {
         checkThread();
-        return getSettings().isPrivateBrowsingEnabled();
-    }
-
-    private void startPrivateBrowsing() {
-        getSettings().setPrivateBrowsingEnabled(true);
-    }
-
-    private boolean extendScroll(int y) {
-        int finalY = mScroller.getFinalY();
-        int newY = pinLocY(finalY + y);
-        if (newY == finalY) return false;
-        mScroller.setFinalY(newY);
-        mScroller.extendDuration(computeDuration(0, y));
-        return true;
+        return mProvider.isPrivateBrowsingEnabled();
     }
 
     /**
@@ -2891,24 +914,7 @@
      */
     public boolean pageUp(boolean top) {
         checkThread();
-        if (mNativeClass == 0) {
-            return false;
-        }
-        nativeClearCursor(); // start next trackball movement from page edge
-        if (top) {
-            // go to the top of the document
-            return pinScrollTo(mScrollX, 0, true, 0);
-        }
-        // Page up
-        int h = getHeight();
-        int y;
-        if (h > 2 * PAGE_SCROLL_OVERLAP) {
-            y = -h + PAGE_SCROLL_OVERLAP;
-        } else {
-            y = -h / 2;
-        }
-        return mScroller.isFinished() ? pinScrollBy(0, y, true, 0)
-                : extendScroll(y);
+        return mProvider.pageUp(top);
     }
 
     /**
@@ -2918,23 +924,7 @@
      */
     public boolean pageDown(boolean bottom) {
         checkThread();
-        if (mNativeClass == 0) {
-            return false;
-        }
-        nativeClearCursor(); // start next trackball movement from page edge
-        if (bottom) {
-            return pinScrollTo(mScrollX, computeRealVerticalScrollRange(), true, 0);
-        }
-        // Page down.
-        int h = getHeight();
-        int y;
-        if (h > 2 * PAGE_SCROLL_OVERLAP) {
-            y = h - PAGE_SCROLL_OVERLAP;
-        } else {
-            y = h / 2;
-        }
-        return mScroller.isFinished() ? pinScrollBy(0, y, true, 0)
-                : extendScroll(y);
+        return mProvider.pageDown(bottom);
     }
 
     /**
@@ -2943,10 +933,7 @@
      */
     public void clearView() {
         checkThread();
-        mContentWidth = 0;
-        mContentHeight = 0;
-        setBaseLayer(0, null, false, false);
-        mWebViewCore.sendMessage(EventHub.CLEAR_CONTENT);
+        mProvider.clearView();
     }
 
     /**
@@ -2960,29 +947,7 @@
      */
     public Picture capturePicture() {
         checkThread();
-        if (mNativeClass == 0) return null;
-        Picture result = new Picture();
-        nativeCopyBaseContentToPicture(result);
-        return result;
-    }
-
-    /**
-     *  Return true if the browser is displaying a TextView for text input.
-     */
-    private boolean inEditingMode() {
-        return mWebTextView != null && mWebTextView.getParent() != null;
-    }
-
-    /**
-     * Remove the WebTextView.
-     */
-    private void clearTextEntry() {
-        if (inEditingMode()) {
-            mWebTextView.remove();
-        } else {
-            // The keyboard may be open with the WebView as the served view
-            hideSoftKeyboard();
-        }
+        return mProvider.capturePicture();
     }
 
     /**
@@ -2991,16 +956,7 @@
      */
     public float getScale() {
         checkThread();
-        return mZoomManager.getScale();
-    }
-
-    /**
-     * Compute the reading level scale of the WebView
-     * @param scale The current scale.
-     * @return The reading level scale.
-     */
-    /*package*/ float computeReadingLevelScale(float scale) {
-        return mZoomManager.computeReadingLevelScale(scale);
+        return mProvider.getScale();
     }
 
     /**
@@ -3015,7 +971,7 @@
      */
     public void setInitialScale(int scaleInPercent) {
         checkThread();
-        mZoomManager.setInitialScaleInPercent(scaleInPercent);
+        mProvider.setInitialScale(scaleInPercent);
     }
 
     /**
@@ -3025,12 +981,7 @@
      */
     public void invokeZoomPicker() {
         checkThread();
-        if (!getSettings().supportZoom()) {
-            Log.w(LOGTAG, "This WebView doesn't support zoom.");
-            return;
-        }
-        clearHelpers();
-        mZoomManager.invokeZoomPicker();
+        mProvider.invokeZoomPicker();
     }
 
     /**
@@ -3053,101 +1004,9 @@
      */
     public HitTestResult getHitTestResult() {
         checkThread();
-        return hitTestResult(mInitialHitTestResult);
+        return mProvider.getHitTestResult();
     }
 
-    private HitTestResult hitTestResult(HitTestResult fallback) {
-        if (mNativeClass == 0 || sDisableNavcache) {
-            return fallback;
-        }
-
-        HitTestResult result = new HitTestResult();
-        if (nativeHasCursorNode()) {
-            if (nativeCursorIsTextInput()) {
-                result.setType(HitTestResult.EDIT_TEXT_TYPE);
-            } else {
-                String text = nativeCursorText();
-                if (text != null) {
-                    if (text.startsWith(SCHEME_TEL)) {
-                        result.setType(HitTestResult.PHONE_TYPE);
-                        result.setExtra(URLDecoder.decode(text
-                                .substring(SCHEME_TEL.length())));
-                    } else if (text.startsWith(SCHEME_MAILTO)) {
-                        result.setType(HitTestResult.EMAIL_TYPE);
-                        result.setExtra(text.substring(SCHEME_MAILTO.length()));
-                    } else if (text.startsWith(SCHEME_GEO)) {
-                        result.setType(HitTestResult.GEO_TYPE);
-                        result.setExtra(URLDecoder.decode(text
-                                .substring(SCHEME_GEO.length())));
-                    } else if (nativeCursorIsAnchor()) {
-                        result.setType(HitTestResult.SRC_ANCHOR_TYPE);
-                        result.setExtra(text);
-                    }
-                }
-            }
-        } else if (fallback != null) {
-            /* If webkit causes a rebuild while the long press is in progress,
-             * the cursor node may be reset, even if it is still around. This
-             * uses the cursor node saved when the touch began. Since the
-             * nativeImageURI below only changes the result if it is successful,
-             * this uses the data beneath the touch if available or the original
-             * tap data otherwise.
-             */
-            Log.v(LOGTAG, "hitTestResult use fallback");
-            result = fallback;
-        }
-        int type = result.getType();
-        if (type == HitTestResult.UNKNOWN_TYPE
-                || type == HitTestResult.SRC_ANCHOR_TYPE) {
-            // Now check to see if it is an image.
-            int contentX = viewToContentX(mLastTouchX + mScrollX);
-            int contentY = viewToContentY(mLastTouchY + mScrollY);
-            String text = nativeImageURI(contentX, contentY);
-            if (text != null) {
-                result.setType(type == HitTestResult.UNKNOWN_TYPE ?
-                        HitTestResult.IMAGE_TYPE :
-                        HitTestResult.SRC_IMAGE_ANCHOR_TYPE);
-                result.setExtra(text);
-            }
-        }
-        return result;
-    }
-
-    int getBlockLeftEdge(int x, int y, float readingScale) {
-        if (!sDisableNavcache) {
-            return nativeGetBlockLeftEdge(x, y, readingScale);
-        }
-
-        float invReadingScale = 1.0f / readingScale;
-        int readingWidth = (int) (getViewWidth() * invReadingScale);
-        int left = NO_LEFTEDGE;
-        if (mFocusedNode != null) {
-            final int length = mFocusedNode.mEnclosingParentRects.length;
-            for (int i = 0; i < length; i++) {
-                Rect rect = mFocusedNode.mEnclosingParentRects[i];
-                if (rect.width() < mFocusedNode.mHitTestSlop) {
-                    // ignore bounding boxes that are too small
-                    continue;
-                } else if (left != NO_LEFTEDGE && rect.width() > readingWidth) {
-                    // stop when bounding box doesn't fit the screen width
-                    // at reading scale
-                    break;
-                }
-
-                left = rect.left;
-            }
-        }
-
-        return left;
-    }
-
-    // Called by JNI when the DOM has changed the focus.  Clear the focus so
-    // that new keys will go to the newly focused field
-    private void domChangedFocus() {
-        if (inEditingMode()) {
-            mPrivateHandler.obtainMessage(DOM_FOCUS_CHANGED).sendToTarget();
-        }
-    }
     /**
      * Request the anchor or image element URL at the last tapped point.
      * If hrefMsg is null, this method returns immediately and does not
@@ -3164,32 +1023,7 @@
      */
     public void requestFocusNodeHref(Message hrefMsg) {
         checkThread();
-        if (hrefMsg == null) {
-            return;
-        }
-        int contentX = viewToContentX(mLastTouchX + mScrollX);
-        int contentY = viewToContentY(mLastTouchY + mScrollY);
-        if (mFocusedNode != null && mFocusedNode.mHitTestX == contentX
-                && mFocusedNode.mHitTestY == contentY) {
-            hrefMsg.getData().putString(FocusNodeHref.URL, mFocusedNode.mLinkUrl);
-            hrefMsg.getData().putString(FocusNodeHref.TITLE, mFocusedNode.mAnchorText);
-            hrefMsg.getData().putString(FocusNodeHref.SRC, mFocusedNode.mImageUrl);
-            hrefMsg.sendToTarget();
-            return;
-        }
-        if (nativeHasCursorNode()) {
-            Rect cursorBounds = cursorRingBounds();
-            if (!cursorBounds.contains(contentX, contentY)) {
-                int slop = viewToContentDimension(mNavSlop);
-                cursorBounds.inset(-slop, -slop);
-                if (cursorBounds.contains(contentX, contentY)) {
-                    contentX = cursorBounds.centerX();
-                    contentY = cursorBounds.centerY();
-                }
-            }
-        }
-        mWebViewCore.sendMessage(EventHub.REQUEST_CURSOR_HREF,
-                contentX, contentY, hrefMsg);
+        mProvider.requestFocusNodeHref(hrefMsg);
     }
 
     /**
@@ -3201,503 +1035,7 @@
      */
     public void requestImageRef(Message msg) {
         checkThread();
-        if (0 == mNativeClass) return; // client isn't initialized
-        int contentX = viewToContentX(mLastTouchX + mScrollX);
-        int contentY = viewToContentY(mLastTouchY + mScrollY);
-        String ref = nativeImageURI(contentX, contentY);
-        Bundle data = msg.getData();
-        data.putString("url", ref);
-        msg.setData(data);
-        msg.sendToTarget();
-    }
-
-    static int pinLoc(int x, int viewMax, int docMax) {
-//        Log.d(LOGTAG, "-- pinLoc " + x + " " + viewMax + " " + docMax);
-        if (docMax < viewMax) {   // the doc has room on the sides for "blank"
-            // pin the short document to the top/left of the screen
-            x = 0;
-//            Log.d(LOGTAG, "--- center " + x);
-        } else if (x < 0) {
-            x = 0;
-//            Log.d(LOGTAG, "--- zero");
-        } else if (x + viewMax > docMax) {
-            x = docMax - viewMax;
-//            Log.d(LOGTAG, "--- pin " + x);
-        }
-        return x;
-    }
-
-    // Expects x in view coordinates
-    int pinLocX(int x) {
-        if (mInOverScrollMode) return x;
-        return pinLoc(x, getViewWidth(), computeRealHorizontalScrollRange());
-    }
-
-    // Expects y in view coordinates
-    int pinLocY(int y) {
-        if (mInOverScrollMode) return y;
-        return pinLoc(y, getViewHeightWithTitle(),
-                      computeRealVerticalScrollRange() + getTitleHeight());
-    }
-
-    /**
-     * A title bar which is embedded in this WebView, and scrolls along with it
-     * vertically, but not horizontally.
-     */
-    private View mTitleBar;
-
-    /**
-     * the title bar rendering gravity
-     */
-    private int mTitleGravity;
-
-    /**
-     * Add or remove a title bar to be embedded into the WebView, and scroll
-     * along with it vertically, while remaining in view horizontally. Pass
-     * null to remove the title bar from the WebView, and return to drawing
-     * the WebView normally without translating to account for the title bar.
-     * @hide
-     */
-    public void setEmbeddedTitleBar(View v) {
-        if (mTitleBar == v) return;
-        if (mTitleBar != null) {
-            removeView(mTitleBar);
-        }
-        if (null != v) {
-            addView(v, new AbsoluteLayout.LayoutParams(
-                    ViewGroup.LayoutParams.MATCH_PARENT,
-                    ViewGroup.LayoutParams.WRAP_CONTENT, 0, 0));
-        }
-        mTitleBar = v;
-    }
-
-    /**
-     * Set where to render the embedded title bar
-     * NO_GRAVITY at the top of the page
-     * TOP        at the top of the screen
-     * @hide
-     */
-    public void setTitleBarGravity(int gravity) {
-        mTitleGravity = gravity;
-        // force refresh
-        invalidate();
-    }
-
-    /**
-     * Given a distance in view space, convert it to content space. Note: this
-     * does not reflect translation, just scaling, so this should not be called
-     * with coordinates, but should be called for dimensions like width or
-     * height.
-     */
-    private int viewToContentDimension(int d) {
-        return Math.round(d * mZoomManager.getInvScale());
-    }
-
-    /**
-     * Given an x coordinate in view space, convert it to content space.  Also
-     * may be used for absolute heights (such as for the WebTextView's
-     * textSize, which is unaffected by the height of the title bar).
-     */
-    /*package*/ int viewToContentX(int x) {
-        return viewToContentDimension(x);
-    }
-
-    /**
-     * Given a y coordinate in view space, convert it to content space.
-     * Takes into account the height of the title bar if there is one
-     * embedded into the WebView.
-     */
-    /*package*/ int viewToContentY(int y) {
-        return viewToContentDimension(y - getTitleHeight());
-    }
-
-    /**
-     * Given a x coordinate in view space, convert it to content space.
-     * Returns the result as a float.
-     */
-    private float viewToContentXf(int x) {
-        return x * mZoomManager.getInvScale();
-    }
-
-    /**
-     * Given a y coordinate in view space, convert it to content space.
-     * Takes into account the height of the title bar if there is one
-     * embedded into the WebView. Returns the result as a float.
-     */
-    private float viewToContentYf(int y) {
-        return (y - getTitleHeight()) * mZoomManager.getInvScale();
-    }
-
-    /**
-     * Given a distance in content space, convert it to view space. Note: this
-     * does not reflect translation, just scaling, so this should not be called
-     * with coordinates, but should be called for dimensions like width or
-     * height.
-     */
-    /*package*/ int contentToViewDimension(int d) {
-        return Math.round(d * mZoomManager.getScale());
-    }
-
-    /**
-     * Given an x coordinate in content space, convert it to view
-     * space.
-     */
-    /*package*/ int contentToViewX(int x) {
-        return contentToViewDimension(x);
-    }
-
-    /**
-     * Given a y coordinate in content space, convert it to view
-     * space.  Takes into account the height of the title bar.
-     */
-    /*package*/ int contentToViewY(int y) {
-        return contentToViewDimension(y) + getTitleHeight();
-    }
-
-    private Rect contentToViewRect(Rect x) {
-        return new Rect(contentToViewX(x.left), contentToViewY(x.top),
-                        contentToViewX(x.right), contentToViewY(x.bottom));
-    }
-
-    /*  To invalidate a rectangle in content coordinates, we need to transform
-        the rect into view coordinates, so we can then call invalidate(...).
-
-        Normally, we would just call contentToView[XY](...), which eventually
-        calls Math.round(coordinate * mActualScale). However, for invalidates,
-        we need to account for the slop that occurs with antialiasing. To
-        address that, we are a little more liberal in the size of the rect that
-        we invalidate.
-
-        This liberal calculation calls floor() for the top/left, and ceil() for
-        the bottom/right coordinates. This catches the possible extra pixels of
-        antialiasing that we might have missed with just round().
-     */
-
-    // Called by JNI to invalidate the View, given rectangle coordinates in
-    // content space
-    private void viewInvalidate(int l, int t, int r, int b) {
-        final float scale = mZoomManager.getScale();
-        final int dy = getTitleHeight();
-        invalidate((int)Math.floor(l * scale),
-                   (int)Math.floor(t * scale) + dy,
-                   (int)Math.ceil(r * scale),
-                   (int)Math.ceil(b * scale) + dy);
-    }
-
-    // Called by JNI to invalidate the View after a delay, given rectangle
-    // coordinates in content space
-    private void viewInvalidateDelayed(long delay, int l, int t, int r, int b) {
-        final float scale = mZoomManager.getScale();
-        final int dy = getTitleHeight();
-        postInvalidateDelayed(delay,
-                              (int)Math.floor(l * scale),
-                              (int)Math.floor(t * scale) + dy,
-                              (int)Math.ceil(r * scale),
-                              (int)Math.ceil(b * scale) + dy);
-    }
-
-    private void invalidateContentRect(Rect r) {
-        viewInvalidate(r.left, r.top, r.right, r.bottom);
-    }
-
-    // stop the scroll animation, and don't let a subsequent fling add
-    // to the existing velocity
-    private void abortAnimation() {
-        mScroller.abortAnimation();
-        mLastVelocity = 0;
-    }
-
-    /* call from webcoreview.draw(), so we're still executing in the UI thread
-    */
-    private void recordNewContentSize(int w, int h, boolean updateLayout) {
-
-        // premature data from webkit, ignore
-        if ((w | h) == 0) {
-            return;
-        }
-
-        // don't abort a scroll animation if we didn't change anything
-        if (mContentWidth != w || mContentHeight != h) {
-            // record new dimensions
-            mContentWidth = w;
-            mContentHeight = h;
-            // If history Picture is drawn, don't update scroll. They will be
-            // updated when we get out of that mode.
-            if (!mDrawHistory) {
-                // repin our scroll, taking into account the new content size
-                updateScrollCoordinates(pinLocX(mScrollX), pinLocY(mScrollY));
-                if (!mScroller.isFinished()) {
-                    // We are in the middle of a scroll.  Repin the final scroll
-                    // position.
-                    mScroller.setFinalX(pinLocX(mScroller.getFinalX()));
-                    mScroller.setFinalY(pinLocY(mScroller.getFinalY()));
-                }
-            }
-        }
-        contentSizeChanged(updateLayout);
-    }
-
-    // Used to avoid sending many visible rect messages.
-    private Rect mLastVisibleRectSent = new Rect();
-    private Rect mLastGlobalRect = new Rect();
-    private Rect mVisibleRect = new Rect();
-    private Rect mGlobalVisibleRect = new Rect();
-    private Point mScrollOffset = new Point();
-
-    Rect sendOurVisibleRect() {
-        if (mZoomManager.isPreventingWebkitUpdates()) return mLastVisibleRectSent;
-        calcOurContentVisibleRect(mVisibleRect);
-        // Rect.equals() checks for null input.
-        if (!mVisibleRect.equals(mLastVisibleRectSent)) {
-            if (!mBlockWebkitViewMessages) {
-                mScrollOffset.set(mVisibleRect.left, mVisibleRect.top);
-                mWebViewCore.removeMessages(EventHub.SET_SCROLL_OFFSET);
-                mWebViewCore.sendMessage(EventHub.SET_SCROLL_OFFSET,
-                        nativeMoveGeneration(), mSendScrollEvent ? 1 : 0, mScrollOffset);
-            }
-            mLastVisibleRectSent.set(mVisibleRect);
-            mPrivateHandler.removeMessages(SWITCH_TO_LONGPRESS);
-        }
-        if (getGlobalVisibleRect(mGlobalVisibleRect)
-                && !mGlobalVisibleRect.equals(mLastGlobalRect)) {
-            if (DebugFlags.WEB_VIEW) {
-                Log.v(LOGTAG, "sendOurVisibleRect=(" + mGlobalVisibleRect.left + ","
-                        + mGlobalVisibleRect.top + ",r=" + mGlobalVisibleRect.right + ",b="
-                        + mGlobalVisibleRect.bottom);
-            }
-            // TODO: the global offset is only used by windowRect()
-            // in ChromeClientAndroid ; other clients such as touch
-            // and mouse events could return view + screen relative points.
-            if (!mBlockWebkitViewMessages) {
-                mWebViewCore.sendMessage(EventHub.SET_GLOBAL_BOUNDS, mGlobalVisibleRect);
-            }
-            mLastGlobalRect.set(mGlobalVisibleRect);
-        }
-        return mVisibleRect;
-    }
-
-    private Point mGlobalVisibleOffset = new Point();
-    // Sets r to be the visible rectangle of our webview in view coordinates
-    private void calcOurVisibleRect(Rect r) {
-        getGlobalVisibleRect(r, mGlobalVisibleOffset);
-        r.offset(-mGlobalVisibleOffset.x, -mGlobalVisibleOffset.y);
-    }
-
-    // Sets r to be our visible rectangle in content coordinates
-    private void calcOurContentVisibleRect(Rect r) {
-        calcOurVisibleRect(r);
-        r.left = viewToContentX(r.left);
-        // viewToContentY will remove the total height of the title bar.  Add
-        // the visible height back in to account for the fact that if the title
-        // bar is partially visible, the part of the visible rect which is
-        // displaying our content is displaced by that amount.
-        r.top = viewToContentY(r.top + getVisibleTitleHeightImpl());
-        r.right = viewToContentX(r.right);
-        r.bottom = viewToContentY(r.bottom);
-    }
-
-    private Rect mContentVisibleRect = new Rect();
-    // Sets r to be our visible rectangle in content coordinates. We use this
-    // method on the native side to compute the position of the fixed layers.
-    // Uses floating coordinates (necessary to correctly place elements when
-    // the scale factor is not 1)
-    private void calcOurContentVisibleRectF(RectF r) {
-        calcOurVisibleRect(mContentVisibleRect);
-        r.left = viewToContentXf(mContentVisibleRect.left);
-        // viewToContentY will remove the total height of the title bar.  Add
-        // the visible height back in to account for the fact that if the title
-        // bar is partially visible, the part of the visible rect which is
-        // displaying our content is displaced by that amount.
-        r.top = viewToContentYf(mContentVisibleRect.top + getVisibleTitleHeightImpl());
-        r.right = viewToContentXf(mContentVisibleRect.right);
-        r.bottom = viewToContentYf(mContentVisibleRect.bottom);
-    }
-
-    static class ViewSizeData {
-        int mWidth;
-        int mHeight;
-        float mHeightWidthRatio;
-        int mActualViewHeight;
-        int mTextWrapWidth;
-        int mAnchorX;
-        int mAnchorY;
-        float mScale;
-        boolean mIgnoreHeight;
-    }
-
-    /**
-     * Compute unzoomed width and height, and if they differ from the last
-     * values we sent, send them to webkit (to be used as new viewport)
-     *
-     * @param force ensures that the message is sent to webkit even if the width
-     * or height has not changed since the last message
-     *
-     * @return true if new values were sent
-     */
-    boolean sendViewSizeZoom(boolean force) {
-        if (mBlockWebkitViewMessages) return false;
-        if (mZoomManager.isPreventingWebkitUpdates()) return false;
-
-        int viewWidth = getViewWidth();
-        int newWidth = Math.round(viewWidth * mZoomManager.getInvScale());
-        // This height could be fixed and be different from actual visible height.
-        int viewHeight = getViewHeightWithTitle() - getTitleHeight();
-        int newHeight = Math.round(viewHeight * mZoomManager.getInvScale());
-        // Make the ratio more accurate than (newHeight / newWidth), since the
-        // latter both are calculated and rounded.
-        float heightWidthRatio = (float) viewHeight / viewWidth;
-        /*
-         * Because the native side may have already done a layout before the
-         * View system was able to measure us, we have to send a height of 0 to
-         * remove excess whitespace when we grow our width. This will trigger a
-         * layout and a change in content size. This content size change will
-         * mean that contentSizeChanged will either call this method directly or
-         * indirectly from onSizeChanged.
-         */
-        if (newWidth > mLastWidthSent && mWrapContent) {
-            newHeight = 0;
-            heightWidthRatio = 0;
-        }
-        // Actual visible content height.
-        int actualViewHeight = Math.round(getViewHeight() * mZoomManager.getInvScale());
-        // Avoid sending another message if the dimensions have not changed.
-        if (newWidth != mLastWidthSent || newHeight != mLastHeightSent || force ||
-                actualViewHeight != mLastActualHeightSent) {
-            ViewSizeData data = new ViewSizeData();
-            data.mWidth = newWidth;
-            data.mHeight = newHeight;
-            data.mHeightWidthRatio = heightWidthRatio;
-            data.mActualViewHeight = actualViewHeight;
-            data.mTextWrapWidth = Math.round(viewWidth / mZoomManager.getTextWrapScale());
-            data.mScale = mZoomManager.getScale();
-            data.mIgnoreHeight = mZoomManager.isFixedLengthAnimationInProgress()
-                    && !mHeightCanMeasure;
-            data.mAnchorX = mZoomManager.getDocumentAnchorX();
-            data.mAnchorY = mZoomManager.getDocumentAnchorY();
-            mWebViewCore.sendMessage(EventHub.VIEW_SIZE_CHANGED, data);
-            mLastWidthSent = newWidth;
-            mLastHeightSent = newHeight;
-            mLastActualHeightSent = actualViewHeight;
-            mZoomManager.clearDocumentAnchor();
-            return true;
-        }
-        return false;
-    }
-
-    /**
-     * Update the double-tap zoom.
-     */
-    /* package */ void updateDoubleTapZoom(int doubleTapZoom) {
-        mZoomManager.updateDoubleTapZoom(doubleTapZoom);
-    }
-
-    private int computeRealHorizontalScrollRange() {
-        if (mDrawHistory) {
-            return mHistoryWidth;
-        } else {
-            // to avoid rounding error caused unnecessary scrollbar, use floor
-            return (int) Math.floor(mContentWidth * mZoomManager.getScale());
-        }
-    }
-
-    @Override
-    protected int computeHorizontalScrollRange() {
-        int range = computeRealHorizontalScrollRange();
-
-        // Adjust reported range if overscrolled to compress the scroll bars
-        final int scrollX = mScrollX;
-        final int overscrollRight = computeMaxScrollX();
-        if (scrollX < 0) {
-            range -= scrollX;
-        } else if (scrollX > overscrollRight) {
-            range += scrollX - overscrollRight;
-        }
-
-        return range;
-    }
-
-    @Override
-    protected int computeHorizontalScrollOffset() {
-        return Math.max(mScrollX, 0);
-    }
-
-    private int computeRealVerticalScrollRange() {
-        if (mDrawHistory) {
-            return mHistoryHeight;
-        } else {
-            // to avoid rounding error caused unnecessary scrollbar, use floor
-            return (int) Math.floor(mContentHeight * mZoomManager.getScale());
-        }
-    }
-
-    @Override
-    protected int computeVerticalScrollRange() {
-        int range = computeRealVerticalScrollRange();
-
-        // Adjust reported range if overscrolled to compress the scroll bars
-        final int scrollY = mScrollY;
-        final int overscrollBottom = computeMaxScrollY();
-        if (scrollY < 0) {
-            range -= scrollY;
-        } else if (scrollY > overscrollBottom) {
-            range += scrollY - overscrollBottom;
-        }
-
-        return range;
-    }
-
-    @Override
-    protected int computeVerticalScrollOffset() {
-        return Math.max(mScrollY - getTitleHeight(), 0);
-    }
-
-    @Override
-    protected int computeVerticalScrollExtent() {
-        return getViewHeight();
-    }
-
-    /** @hide */
-    @Override
-    protected void onDrawVerticalScrollBar(Canvas canvas,
-                                           Drawable scrollBar,
-                                           int l, int t, int r, int b) {
-        if (mScrollY < 0) {
-            t -= mScrollY;
-        }
-        scrollBar.setBounds(l, t + getVisibleTitleHeightImpl(), r, b);
-        scrollBar.draw(canvas);
-    }
-
-    @Override
-    protected void onOverScrolled(int scrollX, int scrollY, boolean clampedX,
-            boolean clampedY) {
-        // Special-case layer scrolling so that we do not trigger normal scroll
-        // updating.
-        if (mTouchMode == TOUCH_DRAG_LAYER_MODE) {
-            scrollLayerTo(scrollX, scrollY);
-            return;
-        }
-        mInOverScrollMode = false;
-        int maxX = computeMaxScrollX();
-        int maxY = computeMaxScrollY();
-        if (maxX == 0) {
-            // do not over scroll x if the page just fits the screen
-            scrollX = pinLocX(scrollX);
-        } else if (scrollX < 0 || scrollX > maxX) {
-            mInOverScrollMode = true;
-        }
-        if (scrollY < 0 || scrollY > maxY) {
-            mInOverScrollMode = true;
-        }
-
-        int oldX = mScrollX;
-        int oldY = mScrollY;
-
-        super.scrollTo(scrollX, scrollY);
-
-        if (mOverScrollGlow != null) {
-            mOverScrollGlow.pullGlow(mScrollX, mScrollY, oldX, oldY, maxX, maxY);
-        }
+        mProvider.requestImageRef(msg);
     }
 
     /**
@@ -3708,8 +1046,7 @@
      */
     public String getUrl() {
         checkThread();
-        WebHistoryItem h = mCallbackProxy.getBackForwardList().getCurrentItem();
-        return h != null ? h.getUrl() : null;
+        return mProvider.getUrl();
     }
 
     /**
@@ -3722,8 +1059,7 @@
      */
     public String getOriginalUrl() {
         checkThread();
-        WebHistoryItem h = mCallbackProxy.getBackForwardList().getCurrentItem();
-        return h != null ? h.getOriginalUrl() : null;
+        return mProvider.getOriginalUrl();
     }
 
     /**
@@ -3733,8 +1069,7 @@
      */
     public String getTitle() {
         checkThread();
-        WebHistoryItem h = mCallbackProxy.getBackForwardList().getCurrentItem();
-        return h != null ? h.getTitle() : null;
+        return mProvider.getTitle();
     }
 
     /**
@@ -3744,8 +1079,7 @@
      */
     public Bitmap getFavicon() {
         checkThread();
-        WebHistoryItem h = mCallbackProxy.getBackForwardList().getCurrentItem();
-        return h != null ? h.getFavicon() : null;
+        return mProvider.getFavicon();
     }
 
     /**
@@ -3755,8 +1089,7 @@
      * @hide
      */
     public String getTouchIconUrl() {
-        WebHistoryItem h = mCallbackProxy.getBackForwardList().getCurrentItem();
-        return h != null ? h.getTouchIconUrl() : null;
+        return mProvider.getTouchIconUrl();
     }
 
     /**
@@ -3765,7 +1098,7 @@
      */
     public int getProgress() {
         checkThread();
-        return mCallbackProxy.getProgress();
+        return mProvider.getProgress();
     }
 
     /**
@@ -3773,7 +1106,7 @@
      */
     public int getContentHeight() {
         checkThread();
-        return mContentHeight;
+        return mProvider.getContentHeight();
     }
 
     /**
@@ -3781,14 +1114,7 @@
      * @hide
      */
     public int getContentWidth() {
-        return mContentWidth;
-    }
-
-    /**
-     * @hide
-     */
-    public int getPageBackgroundColor() {
-        return nativeGetBackgroundColor();
+        return mProvider.getContentWidth();
     }
 
     /**
@@ -3798,7 +1124,7 @@
      */
     public void pauseTimers() {
         checkThread();
-        mWebViewCore.sendMessage(EventHub.PAUSE_TIMERS);
+        mProvider.pauseTimers();
     }
 
     /**
@@ -3807,7 +1133,7 @@
      */
     public void resumeTimers() {
         checkThread();
-        mWebViewCore.sendMessage(EventHub.RESUME_TIMERS);
+        mProvider.resumeTimers();
     }
 
     /**
@@ -3820,38 +1146,7 @@
      */
     public void onPause() {
         checkThread();
-        if (!mIsPaused) {
-            mIsPaused = true;
-            mWebViewCore.sendMessage(EventHub.ON_PAUSE);
-            // We want to pause the current playing video when switching out
-            // from the current WebView/tab.
-            if (mHTML5VideoViewProxy != null) {
-                mHTML5VideoViewProxy.pauseAndDispatch();
-            }
-            if (mNativeClass != 0) {
-                nativeSetPauseDrawing(mNativeClass, true);
-            }
-
-            cancelSelectDialog();
-            WebCoreThreadWatchdog.pause();
-        }
-    }
-
-    @Override
-    protected void onWindowVisibilityChanged(int visibility) {
-        super.onWindowVisibilityChanged(visibility);
-        updateDrawingState();
-    }
-
-    void updateDrawingState() {
-        if (mNativeClass == 0 || mIsPaused) return;
-        if (getWindowVisibility() != VISIBLE) {
-            nativeSetPauseDrawing(mNativeClass, true);
-        } else if (getVisibility() != VISIBLE) {
-            nativeSetPauseDrawing(mNativeClass, true);
-        } else {
-            nativeSetPauseDrawing(mNativeClass, false);
-        }
+        mProvider.onPause();
     }
 
     /**
@@ -3859,22 +1154,7 @@
      */
     public void onResume() {
         checkThread();
-        if (mIsPaused) {
-            mIsPaused = false;
-            mWebViewCore.sendMessage(EventHub.ON_RESUME);
-            if (mNativeClass != 0) {
-                nativeSetPauseDrawing(mNativeClass, false);
-            }
-        }
-        // Ensure that the watchdog has a currently valid Context to be able to display
-        // a prompt dialog. For example, if the Activity was finished whilst the WebCore
-        // thread was blocked and the Activity is started again, we may reuse the blocked
-        // thread, but we'll have a new Activity.
-        WebCoreThreadWatchdog.updateContext(mContext);
-        // We get a call to onResume for new WebViews (i.e. mIsPaused will be false). We need
-        // to ensure that the Watchdog thread is running for the new WebView, so call
-        // it outside the if block above.
-        WebCoreThreadWatchdog.resume();
+        mProvider.onResume();
     }
 
     /**
@@ -3883,7 +1163,7 @@
      * @hide
      */
     public boolean isPaused() {
-        return mIsPaused;
+        return mProvider.isPaused();
     }
 
     /**
@@ -3892,7 +1172,7 @@
      */
     public void freeMemory() {
         checkThread();
-        mWebViewCore.sendMessage(EventHub.FREE_MEMORY);
+        mProvider.freeMemory();
     }
 
     /**
@@ -3903,11 +1183,7 @@
      */
     public void clearCache(boolean includeDiskFiles) {
         checkThread();
-        // Note: this really needs to be a static method as it clears cache for all
-        // WebView. But we need mWebViewCore to send message to WebCore thread, so
-        // we can't make this static.
-        mWebViewCore.sendMessage(EventHub.CLEAR_CACHE,
-                includeDiskFiles ? 1 : 0, 0);
+        mProvider.clearCache(includeDiskFiles);
     }
 
     /**
@@ -3916,9 +1192,7 @@
      */
     public void clearFormData() {
         checkThread();
-        if (inEditingMode()) {
-            mWebTextView.setAdapterCustom(null);
-        }
+        mProvider.clearFormData();
     }
 
     /**
@@ -3926,8 +1200,7 @@
      */
     public void clearHistory() {
         checkThread();
-        mCallbackProxy.getBackForwardList().setClearPending();
-        mWebViewCore.sendMessage(EventHub.CLEAR_HISTORY);
+        mProvider.clearHistory();
     }
 
     /**
@@ -3936,7 +1209,7 @@
      */
     public void clearSslPreferences() {
         checkThread();
-        mWebViewCore.sendMessage(EventHub.CLEAR_SSL_PREF_TABLE);
+        mProvider.clearSslPreferences();
     }
 
     /**
@@ -3949,7 +1222,8 @@
      */
     public WebBackForwardList copyBackForwardList() {
         checkThread();
-        return mCallbackProxy.getBackForwardList().clone();
+        return mProvider.copyBackForwardList();
+
     }
 
     /*
@@ -3961,8 +1235,7 @@
      */
     public void findNext(boolean forward) {
         checkThread();
-        if (0 == mNativeClass) return; // client isn't initialized
-        mWebViewCore.sendMessage(EventHub.FIND_NEXT, forward ? 1 : 0);
+        mProvider.findNext(forward);
     }
 
     /*
@@ -3972,40 +1245,8 @@
      *              that were found.
      */
     public int findAll(String find) {
-        return findAllBody(find, false);
-    }
-
-    /**
-     * @hide
-     */
-    public void findAllAsync(String find) {
-        findAllBody(find, true);
-    }
-
-    private int findAllBody(String find, boolean isAsync) {
         checkThread();
-        if (0 == mNativeClass) return 0; // client isn't initialized
-        mLastFind = find;
-        mWebViewCore.removeMessages(EventHub.FIND_ALL);
-        WebViewCore.FindAllRequest request = new
-            WebViewCore.FindAllRequest(find);
-        if (isAsync) {
-            mWebViewCore.sendMessage(EventHub.FIND_ALL, request);
-            return 0; // no need to wait for response
-        }
-        synchronized(request) {
-            try {
-                mWebViewCore.sendMessageAtFrontOfQueue(EventHub.FIND_ALL,
-                    request);
-                while (request.mMatchCount == -1) {
-                    request.wait();
-                }
-            }
-            catch (InterruptedException e) {
-                return 0;
-            }
-        }
-        return request.mMatchCount;
+        return mProvider.findAll(find);
     }
 
     /**
@@ -4020,56 +1261,10 @@
      */
     public boolean showFindDialog(String text, boolean showIme) {
         checkThread();
-        FindActionModeCallback callback = new FindActionModeCallback(mContext);
-        if (getParent() == null || startActionMode(callback) == null) {
-            // Could not start the action mode, so end Find on page
-            return false;
-        }
-        mCachedOverlappingActionModeHeight = -1;
-        mFindCallback = callback;
-        setFindIsUp(true);
-        mFindCallback.setWebView(this);
-        if (showIme) {
-            mFindCallback.showSoftInput();
-        } else if (text != null) {
-            mFindCallback.setText(text);
-            mFindCallback.findAll();
-            return true;
-        }
-        if (text == null) {
-            text = mLastFind;
-        }
-        if (text != null) {
-            mFindCallback.setText(text);
-            mFindCallback.findAll();
-        }
-        return true;
+        return mProvider.showFindDialog(text, showIme);
     }
 
     /**
-     * Keep track of the find callback so that we can remove its titlebar if
-     * necessary.
-     */
-    private FindActionModeCallback mFindCallback;
-
-    /**
-     * Toggle whether the find dialog is showing, for both native and Java.
-     */
-    private void setFindIsUp(boolean isUp) {
-        mFindIsUp = isUp;
-        if (0 == mNativeClass) return; // client isn't initialized
-        nativeSetFindIsUp(isUp);
-    }
-
-    // Used to know whether the find dialog is open.  Affects whether
-    // or not we draw the highlights for matches.
-    private boolean mFindIsUp;
-
-    // Keep track of the last string sent, so we can search again when find is
-    // reopened.
-    private String mLastFind;
-
-    /**
      * Return the first substring consisting of the address of a physical
      * location. Currently, only addresses in the United States are detected,
      * and consist of:
@@ -4091,33 +1286,7 @@
      */
     public static String findAddress(String addr) {
         checkThread();
-        return findAddress(addr, false);
-    }
-
-    /**
-     * @hide
-     * Return the first substring consisting of the address of a physical
-     * location. Currently, only addresses in the United States are detected,
-     * and consist of:
-     * - a house number
-     * - a street name
-     * - a street type (Road, Circle, etc), either spelled out or abbreviated
-     * - a city name
-     * - a state or territory, either spelled out or two-letter abbr.
-     * - an optional 5 digit or 9 digit zip code.
-     *
-     * Names are optionally capitalized, and the zip code, if present,
-     * must be valid for the state. The street type must be a standard USPS
-     * spelling or abbreviation. The state or territory must also be spelled
-     * or abbreviated using USPS standards. The house number may not exceed
-     * five digits.
-     * @param addr The string to search for addresses.
-     * @param caseInsensitive addr Set to true to make search ignore case.
-     *
-     * @return the address, or if no address is found, return null.
-     */
-    public static String findAddress(String addr, boolean caseInsensitive) {
-        return WebViewCore.nativeFindAddress(addr, caseInsensitive);
+        return getFactory().getStatics().findAddress(addr);
     }
 
     /*
@@ -4125,28 +1294,7 @@
      */
     public void clearMatches() {
         checkThread();
-        if (mNativeClass == 0)
-            return;
-        mWebViewCore.removeMessages(EventHub.FIND_ALL);
-        mWebViewCore.sendMessage(EventHub.FIND_ALL, null);
-    }
-
-
-    /**
-     * Called when the find ActionMode ends.
-     */
-    void notifyFindDialogDismissed() {
-        mFindCallback = null;
-        mCachedOverlappingActionModeHeight = -1;
-        if (mWebViewCore == null) {
-            return;
-        }
-        clearMatches();
-        setFindIsUp(false);
-        // Now that the dialog has been removed, ensure that we scroll to a
-        // location that is not beyond the end of the page.
-        pinScrollTo(mScrollX, mScrollY, false, 0);
-        invalidate();
+        mProvider.clearMatches();
     }
 
     /**
@@ -4157,427 +1305,7 @@
      */
     public void documentHasImages(Message response) {
         checkThread();
-        if (response == null) {
-            return;
-        }
-        mWebViewCore.sendMessage(EventHub.DOC_HAS_IMAGES, response);
-    }
-
-    /**
-     * Request the scroller to abort any ongoing animation
-     *
-     * @hide
-     */
-    public void stopScroll() {
-        mScroller.forceFinished(true);
-        mLastVelocity = 0;
-    }
-
-    @Override
-    public void computeScroll() {
-        if (mScroller.computeScrollOffset()) {
-            int oldX = mScrollX;
-            int oldY = mScrollY;
-            int x = mScroller.getCurrX();
-            int y = mScroller.getCurrY();
-            invalidate();  // So we draw again
-
-            if (!mScroller.isFinished()) {
-                int rangeX = computeMaxScrollX();
-                int rangeY = computeMaxScrollY();
-                int overflingDistance = mOverflingDistance;
-
-                // Use the layer's scroll data if needed.
-                if (mTouchMode == TOUCH_DRAG_LAYER_MODE) {
-                    oldX = mScrollingLayerRect.left;
-                    oldY = mScrollingLayerRect.top;
-                    rangeX = mScrollingLayerRect.right;
-                    rangeY = mScrollingLayerRect.bottom;
-                    // No overscrolling for layers.
-                    overflingDistance = 0;
-                }
-
-                overScrollBy(x - oldX, y - oldY, oldX, oldY,
-                        rangeX, rangeY,
-                        overflingDistance, overflingDistance, false);
-
-                if (mOverScrollGlow != null) {
-                    mOverScrollGlow.absorbGlow(x, y, oldX, oldY, rangeX, rangeY);
-                }
-            } else {
-                if (mTouchMode != TOUCH_DRAG_LAYER_MODE) {
-                    mScrollX = x;
-                    mScrollY = y;
-                } else {
-                    // Update the layer position instead of WebView.
-                    scrollLayerTo(x, y);
-                }
-                abortAnimation();
-                nativeSetIsScrolling(false);
-                if (!mBlockWebkitViewMessages) {
-                    WebViewCore.resumePriority();
-                    if (!mSelectingText) {
-                        WebViewCore.resumeUpdatePicture(mWebViewCore);
-                    }
-                }
-                if (oldX != mScrollX || oldY != mScrollY) {
-                    sendOurVisibleRect();
-                }
-            }
-        } else {
-            super.computeScroll();
-        }
-    }
-
-    private void scrollLayerTo(int x, int y) {
-        if (x == mScrollingLayerRect.left && y == mScrollingLayerRect.top) {
-            return;
-        }
-        if (mSelectingText) {
-            int dx = mScrollingLayerRect.left - x;
-            int dy = mScrollingLayerRect.top - y;
-            if (mSelectCursorBaseLayerId == mCurrentScrollingLayerId) {
-                mSelectCursorBase.offset(dx, dy);
-            }
-            if (mSelectCursorExtentLayerId == mCurrentScrollingLayerId) {
-                mSelectCursorExtent.offset(dx, dy);
-            }
-        }
-        nativeScrollLayer(mCurrentScrollingLayerId, x, y);
-        mScrollingLayerRect.left = x;
-        mScrollingLayerRect.top = y;
-        mWebViewCore.sendMessage(WebViewCore.EventHub.SCROLL_LAYER, mCurrentScrollingLayerId,
-                mScrollingLayerRect);
-        onScrollChanged(mScrollX, mScrollY, mScrollX, mScrollY);
-        invalidate();
-    }
-
-    private static int computeDuration(int dx, int dy) {
-        int distance = Math.max(Math.abs(dx), Math.abs(dy));
-        int duration = distance * 1000 / STD_SPEED;
-        return Math.min(duration, MAX_DURATION);
-    }
-
-    // helper to pin the scrollBy parameters (already in view coordinates)
-    // returns true if the scroll was changed
-    private boolean pinScrollBy(int dx, int dy, boolean animate, int animationDuration) {
-        return pinScrollTo(mScrollX + dx, mScrollY + dy, animate, animationDuration);
-    }
-    // helper to pin the scrollTo parameters (already in view coordinates)
-    // returns true if the scroll was changed
-    private boolean pinScrollTo(int x, int y, boolean animate, int animationDuration) {
-        x = pinLocX(x);
-        y = pinLocY(y);
-        int dx = x - mScrollX;
-        int dy = y - mScrollY;
-
-        if ((dx | dy) == 0) {
-            return false;
-        }
-        abortAnimation();
-        if (animate) {
-            //        Log.d(LOGTAG, "startScroll: " + dx + " " + dy);
-            mScroller.startScroll(mScrollX, mScrollY, dx, dy,
-                    animationDuration > 0 ? animationDuration : computeDuration(dx, dy));
-            awakenScrollBars(mScroller.getDuration());
-            invalidate();
-        } else {
-            scrollTo(x, y);
-        }
-        return true;
-    }
-
-    // Scale from content to view coordinates, and pin.
-    // Also called by jni webview.cpp
-    private boolean setContentScrollBy(int cx, int cy, boolean animate) {
-        if (mDrawHistory) {
-            // disallow WebView to change the scroll position as History Picture
-            // is used in the view system.
-            // TODO: as we switchOutDrawHistory when trackball or navigation
-            // keys are hit, this should be safe. Right?
-            return false;
-        }
-        cx = contentToViewDimension(cx);
-        cy = contentToViewDimension(cy);
-        if (mHeightCanMeasure) {
-            // move our visible rect according to scroll request
-            if (cy != 0) {
-                Rect tempRect = new Rect();
-                calcOurVisibleRect(tempRect);
-                tempRect.offset(cx, cy);
-                requestRectangleOnScreen(tempRect);
-            }
-            // FIXME: We scroll horizontally no matter what because currently
-            // ScrollView and ListView will not scroll horizontally.
-            // FIXME: Why do we only scroll horizontally if there is no
-            // vertical scroll?
-//                Log.d(LOGTAG, "setContentScrollBy cy=" + cy);
-            return cy == 0 && cx != 0 && pinScrollBy(cx, 0, animate, 0);
-        } else {
-            return pinScrollBy(cx, cy, animate, 0);
-        }
-    }
-
-    /**
-     * Called by CallbackProxy when the page starts loading.
-     * @param url The URL of the page which has started loading.
-     */
-    /* package */ void onPageStarted(String url) {
-        // every time we start a new page, we want to reset the
-        // WebView certificate:  if the new site is secure, we
-        // will reload it and get a new certificate set;
-        // if the new site is not secure, the certificate must be
-        // null, and that will be the case
-        setCertificate(null);
-
-        // reset the flag since we set to true in if need after
-        // loading is see onPageFinished(Url)
-        mAccessibilityScriptInjected = false;
-    }
-
-    /**
-     * Called by CallbackProxy when the page finishes loading.
-     * @param url The URL of the page which has finished loading.
-     */
-    /* package */ void onPageFinished(String url) {
-        if (mPageThatNeedsToSlideTitleBarOffScreen != null) {
-            // If the user is now on a different page, or has scrolled the page
-            // past the point where the title bar is offscreen, ignore the
-            // scroll request.
-            if (mPageThatNeedsToSlideTitleBarOffScreen.equals(url)
-                    && mScrollX == 0 && mScrollY == 0) {
-                pinScrollTo(0, mYDistanceToSlideTitleOffScreen, true,
-                        SLIDE_TITLE_DURATION);
-            }
-            mPageThatNeedsToSlideTitleBarOffScreen = null;
-        }
-        mZoomManager.onPageFinished(url);
-        injectAccessibilityForUrl(url);
-    }
-
-    /**
-     * This method injects accessibility in the loaded document if accessibility
-     * is enabled. If JavaScript is enabled we try to inject a URL specific script.
-     * If no URL specific script is found or JavaScript is disabled we fallback to
-     * the default {@link AccessibilityInjector} implementation.
-     * </p>
-     * If the URL has the "axs" paramter set to 1 it has already done the
-     * script injection so we do nothing. If the parameter is set to 0
-     * the URL opts out accessibility script injection so we fall back to
-     * the default {@link AccessibilityInjector}.
-     * </p>
-     * Note: If the user has not opted-in the accessibility script injection no scripts
-     * are injected rather the default {@link AccessibilityInjector} implementation
-     * is used.
-     *
-     * @param url The URL loaded by this {@link WebView}.
-     */
-    private void injectAccessibilityForUrl(String url) {
-        if (mWebViewCore == null) {
-            return;
-        }
-        AccessibilityManager accessibilityManager = AccessibilityManager.getInstance(mContext);
-
-        if (!accessibilityManager.isEnabled()) {
-            // it is possible that accessibility was turned off between reloads
-            ensureAccessibilityScriptInjectorInstance(false);
-            return;
-        }
-
-        if (!getSettings().getJavaScriptEnabled()) {
-            // no JS so we fallback to the basic buil-in support
-            ensureAccessibilityScriptInjectorInstance(true);
-            return;
-        }
-
-        // check the URL "axs" parameter to choose appropriate action
-        int axsParameterValue = getAxsUrlParameterValue(url);
-        if (axsParameterValue == ACCESSIBILITY_SCRIPT_INJECTION_UNDEFINED) {
-            boolean onDeviceScriptInjectionEnabled = (Settings.Secure.getInt(mContext
-                    .getContentResolver(), Settings.Secure.ACCESSIBILITY_SCRIPT_INJECTION, 0) == 1);
-            if (onDeviceScriptInjectionEnabled) {
-                ensureAccessibilityScriptInjectorInstance(false);
-                // neither script injected nor script injection opted out => we inject
-                loadUrl(getScreenReaderInjectingJs());
-                // TODO: Set this flag after successfull script injection. Maybe upon injection
-                // the chooser should update the meta tag and we check it to declare success
-                mAccessibilityScriptInjected = true;
-            } else {
-                // injection disabled so we fallback to the basic built-in support
-                ensureAccessibilityScriptInjectorInstance(true);
-            }
-        } else if (axsParameterValue == ACCESSIBILITY_SCRIPT_INJECTION_OPTED_OUT) {
-            // injection opted out so we fallback to the basic buil-in support
-            ensureAccessibilityScriptInjectorInstance(true);
-        } else if (axsParameterValue == ACCESSIBILITY_SCRIPT_INJECTION_PROVIDED) {
-            ensureAccessibilityScriptInjectorInstance(false);
-            // the URL provides accessibility but we still need to add our generic script
-            loadUrl(getScreenReaderInjectingJs());
-        } else {
-            Log.e(LOGTAG, "Unknown URL value for the \"axs\" URL parameter: " + axsParameterValue);
-        }
-    }
-
-    /**
-     * Ensures the instance of the {@link AccessibilityInjector} to be present ot not.
-     *
-     * @param present True to ensure an insance, false to ensure no instance.
-     */
-    private void ensureAccessibilityScriptInjectorInstance(boolean present) {
-        if (present) {
-            if (mAccessibilityInjector == null) {
-                mAccessibilityInjector = new AccessibilityInjector(this);
-            }
-        } else {
-            mAccessibilityInjector = null;
-        }
-    }
-
-    /**
-     * Gets JavaScript that injects a screen-reader.
-     *
-     * @return The JavaScript snippet.
-     */
-    private String getScreenReaderInjectingJs() {
-        String screenReaderUrl = Settings.Secure.getString(mContext.getContentResolver(),
-                Settings.Secure.ACCESSIBILITY_SCREEN_READER_URL);
-        return String.format(ACCESSIBILITY_SCREEN_READER_JAVASCRIPT_TEMPLATE, screenReaderUrl);
-    }
-
-    /**
-     * Gets the "axs" URL parameter value.
-     *
-     * @param url A url to fetch the paramter from.
-     * @return The parameter value if such, -1 otherwise.
-     */
-    private int getAxsUrlParameterValue(String url) {
-        if (mMatchAxsUrlParameterPattern == null) {
-            mMatchAxsUrlParameterPattern = Pattern.compile(PATTERN_MATCH_AXS_URL_PARAMETER);
-        }
-        Matcher matcher = mMatchAxsUrlParameterPattern.matcher(url);
-        if (matcher.find()) {
-            String keyValuePair = url.substring(matcher.start(), matcher.end());
-            return Integer.parseInt(keyValuePair.split("=")[1]);
-        }
-        return -1;
-    }
-
-    /**
-     * The URL of a page that sent a message to scroll the title bar off screen.
-     *
-     * Many mobile sites tell the page to scroll to (0,1) in order to scroll the
-     * title bar off the screen.  Sometimes, the scroll position is set before
-     * the page finishes loading.  Rather than scrolling while the page is still
-     * loading, keep track of the URL and new scroll position so we can perform
-     * the scroll once the page finishes loading.
-     */
-    private String mPageThatNeedsToSlideTitleBarOffScreen;
-
-    /**
-     * The destination Y scroll position to be used when the page finishes
-     * loading.  See mPageThatNeedsToSlideTitleBarOffScreen.
-     */
-    private int mYDistanceToSlideTitleOffScreen;
-
-    // scale from content to view coordinates, and pin
-    // return true if pin caused the final x/y different than the request cx/cy,
-    // and a future scroll may reach the request cx/cy after our size has
-    // changed
-    // return false if the view scroll to the exact position as it is requested,
-    // where negative numbers are taken to mean 0
-    private boolean setContentScrollTo(int cx, int cy) {
-        if (mDrawHistory) {
-            // disallow WebView to change the scroll position as History Picture
-            // is used in the view system.
-            // One known case where this is called is that WebCore tries to
-            // restore the scroll position. As history Picture already uses the
-            // saved scroll position, it is ok to skip this.
-            return false;
-        }
-        int vx;
-        int vy;
-        if ((cx | cy) == 0) {
-            // If the page is being scrolled to (0,0), do not add in the title
-            // bar's height, and simply scroll to (0,0). (The only other work
-            // in contentToView_ is to multiply, so this would not change 0.)
-            vx = 0;
-            vy = 0;
-        } else {
-            vx = contentToViewX(cx);
-            vy = contentToViewY(cy);
-        }
-//        Log.d(LOGTAG, "content scrollTo [" + cx + " " + cy + "] view=[" +
-//                      vx + " " + vy + "]");
-        // Some mobile sites attempt to scroll the title bar off the page by
-        // scrolling to (0,1).  If we are at the top left corner of the
-        // page, assume this is an attempt to scroll off the title bar, and
-        // animate the title bar off screen slowly enough that the user can see
-        // it.
-        if (cx == 0 && cy == 1 && mScrollX == 0 && mScrollY == 0
-                && mTitleBar != null) {
-            // FIXME: 100 should be defined somewhere as our max progress.
-            if (getProgress() < 100) {
-                // Wait to scroll the title bar off screen until the page has
-                // finished loading.  Keep track of the URL and the destination
-                // Y position
-                mPageThatNeedsToSlideTitleBarOffScreen = getUrl();
-                mYDistanceToSlideTitleOffScreen = vy;
-            } else {
-                pinScrollTo(vx, vy, true, SLIDE_TITLE_DURATION);
-            }
-            // Since we are animating, we have not yet reached the desired
-            // scroll position.  Do not return true to request another attempt
-            return false;
-        }
-        pinScrollTo(vx, vy, false, 0);
-        // If the request was to scroll to a negative coordinate, treat it as if
-        // it was a request to scroll to 0
-        if ((mScrollX != vx && cx >= 0) || (mScrollY != vy && cy >= 0)) {
-            return true;
-        } else {
-            return false;
-        }
-    }
-
-    // scale from content to view coordinates, and pin
-    private void spawnContentScrollTo(int cx, int cy) {
-        if (mDrawHistory) {
-            // disallow WebView to change the scroll position as History Picture
-            // is used in the view system.
-            return;
-        }
-        int vx = contentToViewX(cx);
-        int vy = contentToViewY(cy);
-        pinScrollTo(vx, vy, true, 0);
-    }
-
-    /**
-     * These are from webkit, and are in content coordinate system (unzoomed)
-     */
-    private void contentSizeChanged(boolean updateLayout) {
-        // suppress 0,0 since we usually see real dimensions soon after
-        // this avoids drawing the prev content in a funny place. If we find a
-        // way to consolidate these notifications, this check may become
-        // obsolete
-        if ((mContentWidth | mContentHeight) == 0) {
-            return;
-        }
-
-        if (mHeightCanMeasure) {
-            if (getMeasuredHeight() != contentToViewDimension(mContentHeight)
-                    || updateLayout) {
-                requestLayout();
-            }
-        } else if (mWidthCanMeasure) {
-            if (getMeasuredWidth() != contentToViewDimension(mContentWidth)
-                    || updateLayout) {
-                requestLayout();
-            }
-        } else {
-            // If we don't request a layout, try to send our view size to the
-            // native side to ensure that WebCore has the correct dimensions.
-            sendViewSizeZoom(false);
-        }
+        mProvider.documentHasImages(response);
     }
 
     /**
@@ -4587,17 +1315,7 @@
      */
     public void setWebViewClient(WebViewClient client) {
         checkThread();
-        mCallbackProxy.setWebViewClient(client);
-    }
-
-    /**
-     * Gets the WebViewClient
-     * @return the current WebViewClient instance.
-     *
-     * @hide This is an implementation detail.
-     */
-    public WebViewClient getWebViewClient() {
-        return mCallbackProxy.getWebViewClient();
+        mProvider.setWebViewClient(client);
     }
 
     /**
@@ -4608,7 +1326,7 @@
      */
     public void setDownloadListener(DownloadListener listener) {
         checkThread();
-        mCallbackProxy.setDownloadListener(listener);
+        mProvider.setDownloadListener(listener);
     }
 
     /**
@@ -4619,36 +1337,7 @@
      */
     public void setWebChromeClient(WebChromeClient client) {
         checkThread();
-        mCallbackProxy.setWebChromeClient(client);
-    }
-
-    /**
-     * Gets the chrome handler.
-     * @return the current WebChromeClient instance.
-     *
-     * @hide This is an implementation detail.
-     */
-    public WebChromeClient getWebChromeClient() {
-        return mCallbackProxy.getWebChromeClient();
-    }
-
-    /**
-     * Set the back/forward list client. This is an implementation of
-     * WebBackForwardListClient for handling new items and changes in the
-     * history index.
-     * @param client An implementation of WebBackForwardListClient.
-     * {@hide}
-     */
-    public void setWebBackForwardListClient(WebBackForwardListClient client) {
-        mCallbackProxy.setWebBackForwardListClient(client);
-    }
-
-    /**
-     * Gets the WebBackForwardListClient.
-     * {@hide}
-     */
-    public WebBackForwardListClient getWebBackForwardListClient() {
-        return mCallbackProxy.getWebBackForwardListClient();
+        mProvider.setWebChromeClient(client);
     }
 
     /**
@@ -4660,23 +1349,7 @@
     @Deprecated
     public void setPictureListener(PictureListener listener) {
         checkThread();
-        mPictureListener = listener;
-    }
-
-    /**
-     * {@hide}
-     */
-    /* FIXME: Debug only! Remove for SDK! */
-    public void externalRepresentation(Message callback) {
-        mWebViewCore.sendMessage(EventHub.REQUEST_EXT_REPRESENTATION, callback);
-    }
-
-    /**
-     * {@hide}
-     */
-    /* FIXME: Debug only! Remove for SDK! */
-    public void documentAsText(Message callback) {
-        mWebViewCore.sendMessage(EventHub.REQUEST_DOC_AS_TEXT, callback);
+        mProvider.setPictureListener(listener);
     }
 
     /**
@@ -4707,13 +1380,7 @@
      */
     public void addJavascriptInterface(Object object, String name) {
         checkThread();
-        if (object == null) {
-            return;
-        }
-        WebViewCore.JSInterfaceData arg = new WebViewCore.JSInterfaceData();
-        arg.mObject = object;
-        arg.mInterfaceName = name;
-        mWebViewCore.sendMessage(EventHub.ADD_JS_INTERFACE, arg);
+        mProvider.addJavascriptInterface(object, name);
     }
 
     /**
@@ -4722,11 +1389,7 @@
      */
     public void removeJavascriptInterface(String interfaceName) {
         checkThread();
-        if (mWebViewCore != null) {
-            WebViewCore.JSInterfaceData arg = new WebViewCore.JSInterfaceData();
-            arg.mInterfaceName = interfaceName;
-            mWebViewCore.sendMessage(EventHub.REMOVE_JS_INTERFACE, arg);
-        }
+        mProvider.removeJavascriptInterface(interfaceName);
     }
 
     /**
@@ -4737,1410 +1400,31 @@
      */
     public WebSettings getSettings() {
         checkThread();
-        return (mWebViewCore != null) ? mWebViewCore.getSettings() : null;
+        return mProvider.getSettings();
     }
 
-   /**
-    * Return the list of currently loaded plugins.
-    * @return The list of currently loaded plugins.
-    *
-    * @hide
-    * @deprecated This was used for Gears, which has been deprecated.
-    */
+    /**
+     * Return the list of currently loaded plugins.
+     * @return The list of currently loaded plugins.
+     *
+     * @hide
+     * @deprecated This was used for Gears, which has been deprecated.
+     */
     @Deprecated
     public static synchronized PluginList getPluginList() {
         checkThread();
         return new PluginList();
     }
 
-   /**
-    * @hide
-    * @deprecated This was used for Gears, which has been deprecated.
-    */
+    /**
+     * @hide
+     * @deprecated This was used for Gears, which has been deprecated.
+     */
     @Deprecated
     public void refreshPlugins(boolean reloadOpenPages) {
         checkThread();
     }
 
-    //-------------------------------------------------------------------------
-    // Override View methods
-    //-------------------------------------------------------------------------
-
-    @Override
-    protected void finalize() throws Throwable {
-        try {
-            if (mNativeClass != 0) {
-                mPrivateHandler.post(new Runnable() {
-                    @Override
-                    public void run() {
-                        destroy();
-                    }
-                });
-            }
-        } finally {
-            super.finalize();
-        }
-    }
-
-    @Override
-    protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
-        if (child == mTitleBar) {
-            // When drawing the title bar, move it horizontally to always show
-            // at the top of the WebView.
-            mTitleBar.offsetLeftAndRight(mScrollX - mTitleBar.getLeft());
-            int newTop = 0;
-            if (mTitleGravity == Gravity.NO_GRAVITY) {
-                newTop = Math.min(0, mScrollY);
-            } else if (mTitleGravity == Gravity.TOP) {
-                newTop = mScrollY;
-            }
-            mTitleBar.setBottom(newTop + mTitleBar.getHeight());
-            mTitleBar.setTop(newTop);
-        }
-        return super.drawChild(canvas, child, drawingTime);
-    }
-
-    private void drawContent(Canvas canvas, boolean drawRings) {
-        drawCoreAndCursorRing(canvas, mBackgroundColor,
-                mDrawCursorRing && drawRings);
-    }
-
-    /**
-     * Draw the background when beyond bounds
-     * @param canvas Canvas to draw into
-     */
-    private void drawOverScrollBackground(Canvas canvas) {
-        if (mOverScrollBackground == null) {
-            mOverScrollBackground = new Paint();
-            Bitmap bm = BitmapFactory.decodeResource(
-                    mContext.getResources(),
-                    com.android.internal.R.drawable.status_bar_background);
-            mOverScrollBackground.setShader(new BitmapShader(bm,
-                    Shader.TileMode.REPEAT, Shader.TileMode.REPEAT));
-            mOverScrollBorder = new Paint();
-            mOverScrollBorder.setStyle(Paint.Style.STROKE);
-            mOverScrollBorder.setStrokeWidth(0);
-            mOverScrollBorder.setColor(0xffbbbbbb);
-        }
-
-        int top = 0;
-        int right = computeRealHorizontalScrollRange();
-        int bottom = top + computeRealVerticalScrollRange();
-        // first draw the background and anchor to the top of the view
-        canvas.save();
-        canvas.translate(mScrollX, mScrollY);
-        canvas.clipRect(-mScrollX, top - mScrollY, right - mScrollX, bottom
-                - mScrollY, Region.Op.DIFFERENCE);
-        canvas.drawPaint(mOverScrollBackground);
-        canvas.restore();
-        // then draw the border
-        canvas.drawRect(-1, top - 1, right, bottom, mOverScrollBorder);
-        // next clip the region for the content
-        canvas.clipRect(0, top, right, bottom);
-    }
-
-    @Override
-    protected void onDraw(Canvas canvas) {
-        if (inFullScreenMode()) {
-            return; // no need to draw anything if we aren't visible.
-        }
-        // if mNativeClass is 0, the WebView is either destroyed or not
-        // initialized. In either case, just draw the background color and return
-        if (mNativeClass == 0) {
-            canvas.drawColor(mBackgroundColor);
-            return;
-        }
-
-        // if both mContentWidth and mContentHeight are 0, it means there is no
-        // valid Picture passed to WebView yet. This can happen when WebView
-        // just starts. Draw the background and return.
-        if ((mContentWidth | mContentHeight) == 0 && mHistoryPicture == null) {
-            canvas.drawColor(mBackgroundColor);
-            return;
-        }
-
-        if (canvas.isHardwareAccelerated()) {
-            mZoomManager.setHardwareAccelerated();
-        } else {
-            mWebViewCore.resumeWebKitDraw();
-        }
-
-        int saveCount = canvas.save();
-        if (mInOverScrollMode && !getSettings()
-                .getUseWebViewBackgroundForOverscrollBackground()) {
-            drawOverScrollBackground(canvas);
-        }
-        if (mTitleBar != null) {
-            canvas.translate(0, getTitleHeight());
-        }
-        boolean drawNativeRings = !sDisableNavcache;
-        drawContent(canvas, drawNativeRings);
-        canvas.restoreToCount(saveCount);
-
-        if (AUTO_REDRAW_HACK && mAutoRedraw) {
-            invalidate();
-        }
-        mWebViewCore.signalRepaintDone();
-
-        if (mOverScrollGlow != null && mOverScrollGlow.drawEdgeGlows(canvas)) {
-            invalidate();
-        }
-
-        if (mFocusTransition != null) {
-            mFocusTransition.draw(canvas);
-        } else if (shouldDrawHighlightRect()) {
-            RegionIterator iter = new RegionIterator(mTouchHighlightRegion);
-            Rect r = new Rect();
-            while (iter.next(r)) {
-                canvas.drawRect(r, mTouchHightlightPaint);
-            }
-        }
-        if (DEBUG_TOUCH_HIGHLIGHT) {
-            if (getSettings().getNavDump()) {
-                if ((mTouchHighlightX | mTouchHighlightY) != 0) {
-                    if (mTouchCrossHairColor == null) {
-                        mTouchCrossHairColor = new Paint();
-                        mTouchCrossHairColor.setColor(Color.RED);
-                    }
-                    canvas.drawLine(mTouchHighlightX - mNavSlop,
-                            mTouchHighlightY - mNavSlop, mTouchHighlightX
-                                    + mNavSlop + 1, mTouchHighlightY + mNavSlop
-                                    + 1, mTouchCrossHairColor);
-                    canvas.drawLine(mTouchHighlightX + mNavSlop + 1,
-                            mTouchHighlightY - mNavSlop, mTouchHighlightX
-                                    - mNavSlop,
-                            mTouchHighlightY + mNavSlop + 1,
-                            mTouchCrossHairColor);
-                }
-            }
-        }
-    }
-
-    private void removeTouchHighlight() {
-        mWebViewCore.removeMessages(EventHub.HIT_TEST);
-        mPrivateHandler.removeMessages(HIT_TEST_RESULT);
-        setTouchHighlightRects(null);
-    }
-
-    @Override
-    public void setLayoutParams(ViewGroup.LayoutParams params) {
-        if (params.height == LayoutParams.WRAP_CONTENT) {
-            mWrapContent = true;
-        }
-        super.setLayoutParams(params);
-    }
-
-    @Override
-    public boolean performLongClick() {
-        // performLongClick() is the result of a delayed message. If we switch
-        // to windows overview, the WebView will be temporarily removed from the
-        // view system. In that case, do nothing.
-        if (getParent() == null) return false;
-
-        // A multi-finger gesture can look like a long press; make sure we don't take
-        // long press actions if we're scaling.
-        final ScaleGestureDetector detector = mZoomManager.getMultiTouchGestureDetector();
-        if (detector != null && detector.isInProgress()) {
-            return false;
-        }
-
-        if (mNativeClass != 0 && nativeCursorIsTextInput()) {
-            // Send the click so that the textfield is in focus
-            centerKeyPressOnTextField();
-            rebuildWebTextView();
-        } else {
-            clearTextEntry();
-        }
-        if (inEditingMode()) {
-            // Since we just called rebuildWebTextView, the layout is not set
-            // properly.  Update it so it can correctly find the word to select.
-            mWebTextView.ensureLayout();
-            // Provide a touch down event to WebTextView, which will allow it
-            // to store the location to use in performLongClick.
-            AbsoluteLayout.LayoutParams params
-                    = (AbsoluteLayout.LayoutParams) mWebTextView.getLayoutParams();
-            MotionEvent fake = MotionEvent.obtain(mLastTouchTime,
-                    mLastTouchTime, MotionEvent.ACTION_DOWN,
-                    mLastTouchX - params.x + mScrollX,
-                    mLastTouchY - params.y + mScrollY, 0);
-            mWebTextView.dispatchTouchEvent(fake);
-            return mWebTextView.performLongClick();
-        }
-        if (mSelectingText) return false; // long click does nothing on selection
-        /* if long click brings up a context menu, the super function
-         * returns true and we're done. Otherwise, nothing happened when
-         * the user clicked. */
-        if (super.performLongClick()) {
-            return true;
-        }
-        /* In the case where the application hasn't already handled the long
-         * click action, look for a word under the  click. If one is found,
-         * animate the text selection into view.
-         * FIXME: no animation code yet */
-        final boolean isSelecting = selectText();
-        if (isSelecting) {
-            performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
-        } else if (focusCandidateIsEditableText()) {
-            mSelectCallback = new SelectActionModeCallback();
-            mSelectCallback.setWebView(this);
-            mSelectCallback.setTextSelected(false);
-            startActionMode(mSelectCallback);
-        }
-        return isSelecting;
-    }
-
-    /**
-     * Select the word at the last click point.
-     *
-     * @hide This is an implementation detail.
-     */
-    public boolean selectText() {
-        int x = viewToContentX(mLastTouchX + mScrollX);
-        int y = viewToContentY(mLastTouchY + mScrollY);
-        return selectText(x, y);
-    }
-
-    /**
-     * Select the word at the indicated content coordinates.
-     */
-    boolean selectText(int x, int y) {
-        mWebViewCore.sendMessage(EventHub.SELECT_WORD_AT, x, y);
-        return true;
-    }
-
-    private int mOrientation = Configuration.ORIENTATION_UNDEFINED;
-
-    @Override
-    protected void onConfigurationChanged(Configuration newConfig) {
-        mCachedOverlappingActionModeHeight = -1;
-        if (mSelectingText && mOrientation != newConfig.orientation) {
-            selectionDone();
-        }
-        mOrientation = newConfig.orientation;
-        if (mWebViewCore != null && !mBlockWebkitViewMessages) {
-            mWebViewCore.sendMessage(EventHub.CLEAR_CONTENT);
-        }
-    }
-
-    /**
-     * Keep track of the Callback so we can end its ActionMode or remove its
-     * titlebar.
-     */
-    private SelectActionModeCallback mSelectCallback;
-
-    // These values are possible options for didUpdateWebTextViewDimensions.
-    private static final int FULLY_ON_SCREEN = 0;
-    private static final int INTERSECTS_SCREEN = 1;
-    private static final int ANYWHERE = 2;
-
-    /**
-     * Check to see if the focused textfield/textarea is still on screen.  If it
-     * is, update the the dimensions and location of WebTextView.  Otherwise,
-     * remove the WebTextView.  Should be called when the zoom level changes.
-     * @param intersection How to determine whether the textfield/textarea is
-     *        still on screen.
-     * @return boolean True if the textfield/textarea is still on screen and the
-     *         dimensions/location of WebTextView have been updated.
-     */
-    private boolean didUpdateWebTextViewDimensions(int intersection) {
-        Rect contentBounds = nativeFocusCandidateNodeBounds();
-        Rect vBox = contentToViewRect(contentBounds);
-        Rect visibleRect = new Rect();
-        calcOurVisibleRect(visibleRect);
-        offsetByLayerScrollPosition(vBox);
-        // If the textfield is on screen, place the WebTextView in
-        // its new place, accounting for our new scroll/zoom values,
-        // and adjust its textsize.
-        boolean onScreen;
-        switch (intersection) {
-            case FULLY_ON_SCREEN:
-                onScreen = visibleRect.contains(vBox);
-                break;
-            case INTERSECTS_SCREEN:
-                onScreen = Rect.intersects(visibleRect, vBox);
-                break;
-            case ANYWHERE:
-                onScreen = true;
-                break;
-            default:
-                throw new AssertionError(
-                        "invalid parameter passed to didUpdateWebTextViewDimensions");
-        }
-        if (onScreen) {
-            mWebTextView.setRect(vBox.left, vBox.top, vBox.width(),
-                    vBox.height());
-            mWebTextView.updateTextSize();
-            updateWebTextViewPadding();
-            return true;
-        } else {
-            // The textfield is now off screen.  The user probably
-            // was not zooming to see the textfield better.  Remove
-            // the WebTextView.  If the user types a key, and the
-            // textfield is still in focus, we will reconstruct
-            // the WebTextView and scroll it back on screen.
-            mWebTextView.remove();
-            return false;
-        }
-    }
-
-    private void offsetByLayerScrollPosition(Rect box) {
-        if ((mCurrentScrollingLayerId != 0)
-                && (mCurrentScrollingLayerId == nativeFocusCandidateLayerId())) {
-            box.offsetTo(box.left - mScrollingLayerRect.left,
-                    box.top - mScrollingLayerRect.top);
-        }
-    }
-
-    void setBaseLayer(int layer, Region invalRegion, boolean showVisualIndicator,
-            boolean isPictureAfterFirstLayout) {
-        if (mNativeClass == 0)
-            return;
-        boolean queueFull;
-        queueFull = nativeSetBaseLayer(mNativeClass, layer, invalRegion,
-                                       showVisualIndicator, isPictureAfterFirstLayout);
-
-        if (layer == 0 || isPictureAfterFirstLayout) {
-            mWebViewCore.resumeWebKitDraw();
-        } else if (queueFull) {
-            // temporarily disable webkit draw throttling
-            // TODO: re-enable
-            // mWebViewCore.pauseWebKitDraw();
-        }
-
-        if (mHTML5VideoViewProxy != null) {
-            mHTML5VideoViewProxy.setBaseLayer(layer);
-        }
-    }
-
-    int getBaseLayer() {
-        if (mNativeClass == 0) {
-            return 0;
-        }
-        return nativeGetBaseLayer();
-    }
-
-    private void onZoomAnimationStart() {
-        // If it is in password mode, turn it off so it does not draw misplaced.
-        if (inEditingMode()) {
-            mWebTextView.setVisibility(INVISIBLE);
-        }
-    }
-
-    private void onZoomAnimationEnd() {
-        // adjust the edit text view if needed
-        if (inEditingMode()
-                && didUpdateWebTextViewDimensions(FULLY_ON_SCREEN)) {
-            // If it is a password field, start drawing the WebTextView once
-            // again.
-            mWebTextView.setVisibility(VISIBLE);
-        }
-    }
-
-    void onFixedLengthZoomAnimationStart() {
-        WebViewCore.pauseUpdatePicture(getWebViewCore());
-        onZoomAnimationStart();
-    }
-
-    void onFixedLengthZoomAnimationEnd() {
-        if (!mBlockWebkitViewMessages && !mSelectingText) {
-            WebViewCore.resumeUpdatePicture(mWebViewCore);
-        }
-        onZoomAnimationEnd();
-    }
-
-    private static final int ZOOM_BITS = Paint.FILTER_BITMAP_FLAG |
-                                         Paint.DITHER_FLAG |
-                                         Paint.SUBPIXEL_TEXT_FLAG;
-    private static final int SCROLL_BITS = Paint.FILTER_BITMAP_FLAG |
-                                           Paint.DITHER_FLAG;
-
-    private final DrawFilter mZoomFilter =
-            new PaintFlagsDrawFilter(ZOOM_BITS, Paint.LINEAR_TEXT_FLAG);
-    // If we need to trade better quality for speed, set mScrollFilter to null
-    private final DrawFilter mScrollFilter =
-            new PaintFlagsDrawFilter(SCROLL_BITS, 0);
-
-    private void drawCoreAndCursorRing(Canvas canvas, int color,
-        boolean drawCursorRing) {
-        if (mDrawHistory) {
-            canvas.scale(mZoomManager.getScale(), mZoomManager.getScale());
-            canvas.drawPicture(mHistoryPicture);
-            return;
-        }
-        if (mNativeClass == 0) return;
-
-        boolean animateZoom = mZoomManager.isFixedLengthAnimationInProgress();
-        boolean animateScroll = ((!mScroller.isFinished()
-                || mVelocityTracker != null)
-                && (mTouchMode != TOUCH_DRAG_MODE ||
-                mHeldMotionless != MOTIONLESS_TRUE))
-                || mDeferTouchMode == TOUCH_DRAG_MODE;
-        if (mTouchMode == TOUCH_DRAG_MODE) {
-            if (mHeldMotionless == MOTIONLESS_PENDING) {
-                mPrivateHandler.removeMessages(DRAG_HELD_MOTIONLESS);
-                mPrivateHandler.removeMessages(AWAKEN_SCROLL_BARS);
-                mHeldMotionless = MOTIONLESS_FALSE;
-            }
-            if (mHeldMotionless == MOTIONLESS_FALSE) {
-                mPrivateHandler.sendMessageDelayed(mPrivateHandler
-                        .obtainMessage(DRAG_HELD_MOTIONLESS), MOTIONLESS_TIME);
-                mPrivateHandler.sendMessageDelayed(mPrivateHandler
-                        .obtainMessage(AWAKEN_SCROLL_BARS),
-                            ViewConfiguration.getScrollDefaultDelay());
-                mHeldMotionless = MOTIONLESS_PENDING;
-            }
-        }
-        int saveCount = canvas.save();
-        if (animateZoom) {
-            mZoomManager.animateZoom(canvas);
-        } else if (!canvas.isHardwareAccelerated()) {
-            canvas.scale(mZoomManager.getScale(), mZoomManager.getScale());
-        }
-
-        boolean UIAnimationsRunning = false;
-        // Currently for each draw we compute the animation values;
-        // We may in the future decide to do that independently.
-        if (mNativeClass != 0 && !canvas.isHardwareAccelerated()
-                && nativeEvaluateLayersAnimations(mNativeClass)) {
-            UIAnimationsRunning = true;
-            // If we have unfinished (or unstarted) animations,
-            // we ask for a repaint. We only need to do this in software
-            // rendering (with hardware rendering we already have a different
-            // method of requesting a repaint)
-            mWebViewCore.sendMessage(EventHub.NOTIFY_ANIMATION_STARTED);
-            invalidate();
-        }
-
-        // decide which adornments to draw
-        int extras = DRAW_EXTRAS_NONE;
-        if (!mFindIsUp) {
-            if (mSelectingText) {
-                extras = DRAW_EXTRAS_SELECTION;
-            } else if (drawCursorRing) {
-                extras = DRAW_EXTRAS_CURSOR_RING;
-            }
-        }
-        if (DebugFlags.WEB_VIEW) {
-            Log.v(LOGTAG, "mFindIsUp=" + mFindIsUp
-                    + " mSelectingText=" + mSelectingText
-                    + " nativePageShouldHandleShiftAndArrows()="
-                    + nativePageShouldHandleShiftAndArrows()
-                    + " animateZoom=" + animateZoom
-                    + " extras=" + extras);
-        }
-
-        calcOurContentVisibleRectF(mVisibleContentRect);
-        if (canvas.isHardwareAccelerated()) {
-            Rect glRectViewport = mGLViewportEmpty ? null : mGLRectViewport;
-            Rect viewRectViewport = mGLViewportEmpty ? null : mViewRectViewport;
-
-            int functor = nativeGetDrawGLFunction(mNativeClass, glRectViewport,
-                    viewRectViewport, mVisibleContentRect, getScale(), extras);
-            ((HardwareCanvas) canvas).callDrawGLFunction(functor);
-            if (mHardwareAccelSkia != getSettings().getHardwareAccelSkiaEnabled()) {
-                mHardwareAccelSkia = getSettings().getHardwareAccelSkiaEnabled();
-                nativeUseHardwareAccelSkia(mHardwareAccelSkia);
-            }
-
-        } else {
-            DrawFilter df = null;
-            if (mZoomManager.isZoomAnimating() || UIAnimationsRunning) {
-                df = mZoomFilter;
-            } else if (animateScroll) {
-                df = mScrollFilter;
-            }
-            canvas.setDrawFilter(df);
-            // XXX: Revisit splitting content.  Right now it causes a
-            // synchronization problem with layers.
-            int content = nativeDraw(canvas, mVisibleContentRect, color,
-                    extras, false);
-            canvas.setDrawFilter(null);
-            if (!mBlockWebkitViewMessages && content != 0) {
-                mWebViewCore.sendMessage(EventHub.SPLIT_PICTURE_SET, content, 0);
-            }
-        }
-
-        canvas.restoreToCount(saveCount);
-        if (mSelectingText) {
-            drawTextSelectionHandles(canvas);
-        }
-
-        if (extras == DRAW_EXTRAS_CURSOR_RING) {
-            if (mTouchMode == TOUCH_SHORTPRESS_START_MODE) {
-                mTouchMode = TOUCH_SHORTPRESS_MODE;
-            }
-        }
-        if (mFocusSizeChanged) {
-            mFocusSizeChanged = false;
-            // If we are zooming, this will get handled above, when the zoom
-            // finishes.  We also do not need to do this unless the WebTextView
-            // is showing. With hardware acceleration, the pageSwapCallback()
-            // updates the WebTextView position in sync with page swapping
-            if (!canvas.isHardwareAccelerated() && !animateZoom && inEditingMode()) {
-                didUpdateWebTextViewDimensions(ANYWHERE);
-            }
-        }
-    }
-
-    private void drawTextSelectionHandles(Canvas canvas) {
-        int[] handles = new int[4];
-        getSelectionHandles(handles);
-        int start_x = contentToViewDimension(handles[0]);
-        int start_y = contentToViewDimension(handles[1]);
-        int end_x = contentToViewDimension(handles[2]);
-        int end_y = contentToViewDimension(handles[3]);
-
-        if (mIsCaretSelection) {
-            if (mSelectHandleCenter == null) {
-                mSelectHandleCenter = mContext.getResources().getDrawable(
-                        com.android.internal.R.drawable.text_select_handle_middle);
-            }
-            // Caret handle is centered
-            start_x -= (mSelectHandleCenter.getIntrinsicWidth() / 2);
-            mSelectHandleCenter.setBounds(start_x, start_y,
-                    start_x + mSelectHandleCenter.getIntrinsicWidth(),
-                    start_y + mSelectHandleCenter.getIntrinsicHeight());
-            mSelectHandleCenter.draw(canvas);
-        } else {
-            if (mSelectHandleLeft == null) {
-                mSelectHandleLeft = mContext.getResources().getDrawable(
-                        com.android.internal.R.drawable.text_select_handle_left);
-            }
-            // Magic formula copied from TextView
-            start_x -= (mSelectHandleLeft.getIntrinsicWidth() * 3) / 4;
-            mSelectHandleLeft.setBounds(start_x, start_y,
-                    start_x + mSelectHandleLeft.getIntrinsicWidth(),
-                    start_y + mSelectHandleLeft.getIntrinsicHeight());
-            if (mSelectHandleRight == null) {
-                mSelectHandleRight = mContext.getResources().getDrawable(
-                        com.android.internal.R.drawable.text_select_handle_right);
-            }
-            end_x -= mSelectHandleRight.getIntrinsicWidth() / 4;
-            mSelectHandleRight.setBounds(end_x, end_y,
-                    end_x + mSelectHandleRight.getIntrinsicWidth(),
-                    end_y + mSelectHandleRight.getIntrinsicHeight());
-            mSelectHandleLeft.draw(canvas);
-            mSelectHandleRight.draw(canvas);
-        }
-    }
-
-    /**
-     * Takes an int[4] array as an output param with the values being
-     * startX, startY, endX, endY
-     */
-    private void getSelectionHandles(int[] handles) {
-        handles[0] = mSelectCursorBase.right;
-        handles[1] = mSelectCursorBase.bottom -
-                (mSelectCursorBase.height() / 4);
-        handles[2] = mSelectCursorExtent.left;
-        handles[3] = mSelectCursorExtent.bottom
-                - (mSelectCursorExtent.height() / 4);
-        if (!nativeIsBaseFirst(mNativeClass)) {
-            int swap = handles[0];
-            handles[0] = handles[2];
-            handles[2] = swap;
-            swap = handles[1];
-            handles[1] = handles[3];
-            handles[3] = swap;
-        }
-    }
-
-    // draw history
-    private boolean mDrawHistory = false;
-    private Picture mHistoryPicture = null;
-    private int mHistoryWidth = 0;
-    private int mHistoryHeight = 0;
-
-    // Only check the flag, can be called from WebCore thread
-    boolean drawHistory() {
-        return mDrawHistory;
-    }
-
-    int getHistoryPictureWidth() {
-        return (mHistoryPicture != null) ? mHistoryPicture.getWidth() : 0;
-    }
-
-    // Should only be called in UI thread
-    void switchOutDrawHistory() {
-        if (null == mWebViewCore) return; // CallbackProxy may trigger this
-        if (mDrawHistory && (getProgress() == 100 || nativeHasContent())) {
-            mDrawHistory = false;
-            mHistoryPicture = null;
-            invalidate();
-            int oldScrollX = mScrollX;
-            int oldScrollY = mScrollY;
-            mScrollX = pinLocX(mScrollX);
-            mScrollY = pinLocY(mScrollY);
-            if (oldScrollX != mScrollX || oldScrollY != mScrollY) {
-                onScrollChanged(mScrollX, mScrollY, oldScrollX, oldScrollY);
-            } else {
-                sendOurVisibleRect();
-            }
-        }
-    }
-
-    // TODO: Remove this
-    WebViewCore.CursorData cursorData() {
-        if (sDisableNavcache) {
-            return new WebViewCore.CursorData(0, 0, 0, 0);
-        }
-        WebViewCore.CursorData result = cursorDataNoPosition();
-        Point position = nativeCursorPosition();
-        result.mX = position.x;
-        result.mY = position.y;
-        return result;
-    }
-
-    WebViewCore.CursorData cursorDataNoPosition() {
-        WebViewCore.CursorData result = new WebViewCore.CursorData();
-        result.mMoveGeneration = nativeMoveGeneration();
-        result.mFrame = nativeCursorFramePointer();
-        return result;
-    }
-
-    /**
-     *  Delete text from start to end in the focused textfield. If there is no
-     *  focus, or if start == end, silently fail.  If start and end are out of
-     *  order, swap them.
-     *  @param  start   Beginning of selection to delete.
-     *  @param  end     End of selection to delete.
-     */
-    /* package */ void deleteSelection(int start, int end) {
-        mTextGeneration++;
-        WebViewCore.TextSelectionData data
-                = new WebViewCore.TextSelectionData(start, end, 0);
-        mWebViewCore.sendMessage(EventHub.DELETE_SELECTION, mTextGeneration, 0,
-                data);
-    }
-
-    /**
-     *  Set the selection to (start, end) in the focused textfield. If start and
-     *  end are out of order, swap them.
-     *  @param  start   Beginning of selection.
-     *  @param  end     End of selection.
-     */
-    /* package */ void setSelection(int start, int end) {
-        if (mWebViewCore != null) {
-            mWebViewCore.sendMessage(EventHub.SET_SELECTION, start, end);
-        }
-    }
-
-    @Override
-    public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
-        if (mInputConnection == null) {
-            mInputConnection = new WebViewInputConnection();
-        }
-        mInputConnection.setupEditorInfo(outAttrs);
-        return mInputConnection;
-    }
-
-    /**
-     * Called in response to a message from webkit telling us that the soft
-     * keyboard should be launched.
-     */
-    private void displaySoftKeyboard(boolean isTextView) {
-        InputMethodManager imm = (InputMethodManager)
-                getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
-
-        // bring it back to the default level scale so that user can enter text
-        boolean zoom = mZoomManager.getScale() < mZoomManager.getDefaultScale();
-        if (zoom) {
-            mZoomManager.setZoomCenter(mLastTouchX, mLastTouchY);
-            mZoomManager.setZoomScale(mZoomManager.getDefaultScale(), false);
-        }
-        if (isTextView) {
-            rebuildWebTextView();
-            if (inEditingMode()) {
-                imm.showSoftInput(mWebTextView, 0, mWebTextView.getResultReceiver());
-                if (zoom) {
-                    didUpdateWebTextViewDimensions(INTERSECTS_SCREEN);
-                }
-                return;
-            }
-        }
-        // Used by plugins and contentEditable.
-        // Also used if the navigation cache is out of date, and
-        // does not recognize that a textfield is in focus.  In that
-        // case, use WebView as the targeted view.
-        // see http://b/issue?id=2457459
-        imm.showSoftInput(this, 0);
-    }
-
-    // Called by WebKit to instruct the UI to hide the keyboard
-    private void hideSoftKeyboard() {
-        InputMethodManager imm = InputMethodManager.peekInstance();
-        if (imm != null && (imm.isActive(this)
-                || (inEditingMode() && imm.isActive(mWebTextView)))) {
-            imm.hideSoftInputFromWindow(this.getWindowToken(), 0);
-        }
-    }
-
-    /*
-     * This method checks the current focus and cursor and potentially rebuilds
-     * mWebTextView to have the appropriate properties, such as password,
-     * multiline, and what text it contains.  It also removes it if necessary.
-     */
-    /* package */ void rebuildWebTextView() {
-        if (!sEnableWebTextView) {
-            return; // always use WebKit's text entry
-        }
-        // If the WebView does not have focus, do nothing until it gains focus.
-        if (!hasFocus() && (null == mWebTextView || !mWebTextView.hasFocus())) {
-            return;
-        }
-        boolean alreadyThere = inEditingMode();
-        // inEditingMode can only return true if mWebTextView is non-null,
-        // so we can safely call remove() if (alreadyThere)
-        if (0 == mNativeClass || !nativeFocusCandidateIsTextInput()) {
-            if (alreadyThere) {
-                mWebTextView.remove();
-            }
-            return;
-        }
-        // At this point, we know we have found an input field, so go ahead
-        // and create the WebTextView if necessary.
-        if (mWebTextView == null) {
-            mWebTextView = new WebTextView(mContext, WebView.this, mAutoFillData.getQueryId());
-            // Initialize our generation number.
-            mTextGeneration = 0;
-        }
-        mWebTextView.updateTextSize();
-        updateWebTextViewPosition();
-        String text = nativeFocusCandidateText();
-        int nodePointer = nativeFocusCandidatePointer();
-        // This needs to be called before setType, which may call
-        // requestFormData, and it needs to have the correct nodePointer.
-        mWebTextView.setNodePointer(nodePointer);
-        mWebTextView.setType(nativeFocusCandidateType());
-        // Gravity needs to be set after setType
-        mWebTextView.setGravityForRtl(nativeFocusCandidateIsRtlText());
-        if (null == text) {
-            if (DebugFlags.WEB_VIEW) {
-                Log.v(LOGTAG, "rebuildWebTextView null == text");
-            }
-            text = "";
-        }
-        mWebTextView.setTextAndKeepSelection(text);
-        InputMethodManager imm = InputMethodManager.peekInstance();
-        if (imm != null && imm.isActive(mWebTextView)) {
-            imm.restartInput(mWebTextView);
-            mWebTextView.clearComposingText();
-        }
-        if (isFocused()) {
-            mWebTextView.requestFocus();
-        }
-    }
-
-    private void updateWebTextViewPosition() {
-        Rect visibleRect = new Rect();
-        calcOurContentVisibleRect(visibleRect);
-        // Note that sendOurVisibleRect calls viewToContent, so the coordinates
-        // should be in content coordinates.
-        Rect bounds = nativeFocusCandidateNodeBounds();
-        Rect vBox = contentToViewRect(bounds);
-        offsetByLayerScrollPosition(vBox);
-        mWebTextView.setRect(vBox.left, vBox.top, vBox.width(), vBox.height());
-        if (!Rect.intersects(bounds, visibleRect)) {
-            revealSelection();
-        }
-        updateWebTextViewPadding();
-    }
-
-    /**
-     * Update the padding of mWebTextView based on the native textfield/textarea
-     */
-    void updateWebTextViewPadding() {
-        Rect paddingRect = nativeFocusCandidatePaddingRect();
-        if (paddingRect != null) {
-            // Use contentToViewDimension since these are the dimensions of
-            // the padding.
-            mWebTextView.setPadding(
-                    contentToViewDimension(paddingRect.left),
-                    contentToViewDimension(paddingRect.top),
-                    contentToViewDimension(paddingRect.right),
-                    contentToViewDimension(paddingRect.bottom));
-        }
-    }
-
-    /**
-     * Tell webkit to put the cursor on screen.
-     */
-    /* package */ void revealSelection() {
-        if (mWebViewCore != null) {
-            mWebViewCore.sendMessage(EventHub.REVEAL_SELECTION);
-        }
-    }
-
-    /**
-     * Called by WebTextView to find saved form data associated with the
-     * textfield
-     * @param name Name of the textfield.
-     * @param nodePointer Pointer to the node of the textfield, so it can be
-     *          compared to the currently focused textfield when the data is
-     *          retrieved.
-     * @param autoFillable true if WebKit has determined this field is part of
-     *          a form that can be auto filled.
-     * @param autoComplete true if the attribute "autocomplete" is set to true
-     *          on the textfield.
-     */
-    /* package */ void requestFormData(String name, int nodePointer,
-            boolean autoFillable, boolean autoComplete) {
-        if (mWebViewCore.getSettings().getSaveFormData()) {
-            Message update = mPrivateHandler.obtainMessage(REQUEST_FORM_DATA);
-            update.arg1 = nodePointer;
-            RequestFormData updater = new RequestFormData(name, getUrl(),
-                    update, autoFillable, autoComplete);
-            Thread t = new Thread(updater);
-            t.start();
-        }
-    }
-
-    /**
-     * Pass a message to find out the <label> associated with the <input>
-     * identified by nodePointer
-     * @param framePointer Pointer to the frame containing the <input> node
-     * @param nodePointer Pointer to the node for which a <label> is desired.
-     */
-    /* package */ void requestLabel(int framePointer, int nodePointer) {
-        mWebViewCore.sendMessage(EventHub.REQUEST_LABEL, framePointer,
-                nodePointer);
-    }
-
-    /*
-     * This class requests an Adapter for the WebTextView which shows past
-     * entries stored in the database.  It is a Runnable so that it can be done
-     * in its own thread, without slowing down the UI.
-     */
-    private class RequestFormData implements Runnable {
-        private String mName;
-        private String mUrl;
-        private Message mUpdateMessage;
-        private boolean mAutoFillable;
-        private boolean mAutoComplete;
-        private WebSettings mWebSettings;
-
-        public RequestFormData(String name, String url, Message msg,
-                boolean autoFillable, boolean autoComplete) {
-            mName = name;
-            mUrl = WebTextView.urlForAutoCompleteData(url);
-            mUpdateMessage = msg;
-            mAutoFillable = autoFillable;
-            mAutoComplete = autoComplete;
-            mWebSettings = getSettings();
-        }
-
-        @Override
-        public void run() {
-            ArrayList<String> pastEntries = new ArrayList<String>();
-
-            if (mAutoFillable) {
-                // Note that code inside the adapter click handler in WebTextView depends
-                // on the AutoFill item being at the top of the drop down list. If you change
-                // the order, make sure to do it there too!
-                if (mWebSettings != null && mWebSettings.getAutoFillProfile() != null) {
-                    pastEntries.add(getResources().getText(
-                            com.android.internal.R.string.autofill_this_form).toString() +
-                            " " +
-                            mAutoFillData.getPreviewString());
-                    mWebTextView.setAutoFillProfileIsSet(true);
-                } else {
-                    // There is no autofill profile set up yet, so add an option that
-                    // will invite the user to set their profile up.
-                    pastEntries.add(getResources().getText(
-                            com.android.internal.R.string.setup_autofill).toString());
-                    mWebTextView.setAutoFillProfileIsSet(false);
-                }
-            }
-
-            if (mAutoComplete) {
-                pastEntries.addAll(mDatabase.getFormData(mUrl, mName));
-            }
-
-            if (pastEntries.size() > 0) {
-                AutoCompleteAdapter adapter = new
-                        AutoCompleteAdapter(mContext, pastEntries);
-                mUpdateMessage.obj = adapter;
-                mUpdateMessage.sendToTarget();
-            }
-        }
-    }
-
-    /**
-     * Dump the display tree to "/sdcard/displayTree.txt"
-     *
-     * @hide debug only
-     */
-    public void dumpDisplayTree() {
-        nativeDumpDisplayTree(getUrl());
-    }
-
-    /**
-     * Dump the dom tree to adb shell if "toFile" is False, otherwise dump it to
-     * "/sdcard/domTree.txt"
-     *
-     * @hide debug only
-     */
-    public void dumpDomTree(boolean toFile) {
-        mWebViewCore.sendMessage(EventHub.DUMP_DOMTREE, toFile ? 1 : 0, 0);
-    }
-
-    /**
-     * Dump the render tree to adb shell if "toFile" is False, otherwise dump it
-     * to "/sdcard/renderTree.txt"
-     *
-     * @hide debug only
-     */
-    public void dumpRenderTree(boolean toFile) {
-        mWebViewCore.sendMessage(EventHub.DUMP_RENDERTREE, toFile ? 1 : 0, 0);
-    }
-
-    /**
-     * Called by DRT on UI thread, need to proxy to WebCore thread.
-     *
-     * @hide debug only
-     */
-    public void useMockDeviceOrientation() {
-        mWebViewCore.sendMessage(EventHub.USE_MOCK_DEVICE_ORIENTATION);
-    }
-
-    /**
-     * Called by DRT on WebCore thread.
-     *
-     * @hide debug only
-     */
-    public void setMockDeviceOrientation(boolean canProvideAlpha, double alpha,
-            boolean canProvideBeta, double beta, boolean canProvideGamma, double gamma) {
-        mWebViewCore.setMockDeviceOrientation(canProvideAlpha, alpha, canProvideBeta, beta,
-                canProvideGamma, gamma);
-    }
-
-    // This is used to determine long press with the center key.  Does not
-    // affect long press with the trackball/touch.
-    private boolean mGotCenterDown = false;
-
-    @Override
-    public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) {
-        if (mBlockWebkitViewMessages) {
-            return false;
-        }
-        // send complex characters to webkit for use by JS and plugins
-        if (keyCode == KeyEvent.KEYCODE_UNKNOWN && event.getCharacters() != null) {
-            // pass the key to DOM
-            mWebViewCore.sendMessage(EventHub.KEY_DOWN, event);
-            mWebViewCore.sendMessage(EventHub.KEY_UP, event);
-            // return true as DOM handles the key
-            return true;
-        }
-        return false;
-    }
-
-    private boolean isEnterActionKey(int keyCode) {
-        return keyCode == KeyEvent.KEYCODE_DPAD_CENTER
-                || keyCode == KeyEvent.KEYCODE_ENTER
-                || keyCode == KeyEvent.KEYCODE_NUMPAD_ENTER;
-    }
-
-    @Override
-    public boolean onKeyDown(int keyCode, KeyEvent event) {
-        if (DebugFlags.WEB_VIEW) {
-            Log.v(LOGTAG, "keyDown at " + System.currentTimeMillis()
-                    + "keyCode=" + keyCode
-                    + ", " + event + ", unicode=" + event.getUnicodeChar());
-        }
-        if (mIsCaretSelection) {
-            selectionDone();
-        }
-        if (mBlockWebkitViewMessages) {
-            return false;
-        }
-
-        // don't implement accelerator keys here; defer to host application
-        if (event.isCtrlPressed()) {
-            return false;
-        }
-
-        if (mNativeClass == 0) {
-            return false;
-        }
-
-        // do this hack up front, so it always works, regardless of touch-mode
-        if (AUTO_REDRAW_HACK && (keyCode == KeyEvent.KEYCODE_CALL)) {
-            mAutoRedraw = !mAutoRedraw;
-            if (mAutoRedraw) {
-                invalidate();
-            }
-            return true;
-        }
-
-        // Bubble up the key event if
-        // 1. it is a system key; or
-        // 2. the host application wants to handle it;
-        if (event.isSystem()
-                || mCallbackProxy.uiOverrideKeyEvent(event)) {
-            return false;
-        }
-
-        // accessibility support
-        if (accessibilityScriptInjected()) {
-            if (AccessibilityManager.getInstance(mContext).isEnabled()) {
-                // if an accessibility script is injected we delegate to it the key handling.
-                // this script is a screen reader which is a fully fledged solution for blind
-                // users to navigate in and interact with web pages.
-                mWebViewCore.sendMessage(EventHub.KEY_DOWN, event);
-                return true;
-            } else {
-                // Clean up if accessibility was disabled after loading the current URL.
-                mAccessibilityScriptInjected = false;
-            }
-        } else if (mAccessibilityInjector != null) {
-            if (AccessibilityManager.getInstance(mContext).isEnabled()) {
-                if (mAccessibilityInjector.onKeyEvent(event)) {
-                    // if an accessibility injector is present (no JavaScript enabled or the site
-                    // opts out injecting our JavaScript screen reader) we let it decide whether
-                    // to act on and consume the event.
-                    return true;
-                }
-            } else {
-                // Clean up if accessibility was disabled after loading the current URL.
-                mAccessibilityInjector = null;
-            }
-        }
-
-        if (keyCode == KeyEvent.KEYCODE_PAGE_UP) {
-            if (event.hasNoModifiers()) {
-                pageUp(false);
-                return true;
-            } else if (event.hasModifiers(KeyEvent.META_ALT_ON)) {
-                pageUp(true);
-                return true;
-            }
-        }
-
-        if (keyCode == KeyEvent.KEYCODE_PAGE_DOWN) {
-            if (event.hasNoModifiers()) {
-                pageDown(false);
-                return true;
-            } else if (event.hasModifiers(KeyEvent.META_ALT_ON)) {
-                pageDown(true);
-                return true;
-            }
-        }
-
-        if (keyCode == KeyEvent.KEYCODE_MOVE_HOME && event.hasNoModifiers()) {
-            pageUp(true);
-            return true;
-        }
-
-        if (keyCode == KeyEvent.KEYCODE_MOVE_END && event.hasNoModifiers()) {
-            pageDown(true);
-            return true;
-        }
-
-        if (keyCode >= KeyEvent.KEYCODE_DPAD_UP
-                && keyCode <= KeyEvent.KEYCODE_DPAD_RIGHT) {
-            switchOutDrawHistory();
-            if (nativePageShouldHandleShiftAndArrows()) {
-                letPageHandleNavKey(keyCode, event.getEventTime(), true, event.getMetaState());
-                return true;
-            }
-            if (event.hasModifiers(KeyEvent.META_ALT_ON)) {
-                switch (keyCode) {
-                    case KeyEvent.KEYCODE_DPAD_UP:
-                        pageUp(true);
-                        return true;
-                    case KeyEvent.KEYCODE_DPAD_DOWN:
-                        pageDown(true);
-                        return true;
-                    case KeyEvent.KEYCODE_DPAD_LEFT:
-                        nativeClearCursor(); // start next trackball movement from page edge
-                        return pinScrollTo(0, mScrollY, true, 0);
-                    case KeyEvent.KEYCODE_DPAD_RIGHT:
-                        nativeClearCursor(); // start next trackball movement from page edge
-                        return pinScrollTo(mContentWidth, mScrollY, true, 0);
-                }
-            }
-            if (navHandledKey(keyCode, 1, false, event.getEventTime())) {
-                playSoundEffect(keyCodeToSoundsEffect(keyCode));
-                return true;
-            }
-            // Bubble up the key event as WebView doesn't handle it
-            return false;
-        }
-
-        if (isEnterActionKey(keyCode)) {
-            switchOutDrawHistory();
-            boolean wantsKeyEvents = nativeCursorNodePointer() == 0
-                || nativeCursorWantsKeyEvents();
-            if (event.getRepeatCount() == 0) {
-                if (mSelectingText) {
-                    return true; // discard press if copy in progress
-                }
-                mGotCenterDown = true;
-                mPrivateHandler.sendMessageDelayed(mPrivateHandler
-                        .obtainMessage(LONG_PRESS_CENTER), LONG_PRESS_TIMEOUT);
-                if (!wantsKeyEvents) return true;
-            }
-            // Bubble up the key event as WebView doesn't handle it
-            if (!wantsKeyEvents) return false;
-        }
-
-        if (getSettings().getNavDump()) {
-            switch (keyCode) {
-                case KeyEvent.KEYCODE_4:
-                    dumpDisplayTree();
-                    break;
-                case KeyEvent.KEYCODE_5:
-                case KeyEvent.KEYCODE_6:
-                    dumpDomTree(keyCode == KeyEvent.KEYCODE_5);
-                    break;
-                case KeyEvent.KEYCODE_7:
-                case KeyEvent.KEYCODE_8:
-                    dumpRenderTree(keyCode == KeyEvent.KEYCODE_7);
-                    break;
-            }
-        }
-
-        if (nativeCursorIsTextInput()) {
-            // This message will put the node in focus, for the DOM's notion
-            // of focus.
-            mWebViewCore.sendMessage(EventHub.FAKE_CLICK, nativeCursorFramePointer(),
-                    nativeCursorNodePointer());
-            // This will bring up the WebTextView and put it in focus, for
-            // our view system's notion of focus
-            rebuildWebTextView();
-            // Now we need to pass the event to it
-            if (inEditingMode()) {
-                mWebTextView.setDefaultSelection();
-                return mWebTextView.dispatchKeyEvent(event);
-            }
-        } else if (nativeHasFocusNode()) {
-            // In this case, the cursor is not on a text input, but the focus
-            // might be.  Check it, and if so, hand over to the WebTextView.
-            rebuildWebTextView();
-            if (inEditingMode()) {
-                mWebTextView.setDefaultSelection();
-                return mWebTextView.dispatchKeyEvent(event);
-            }
-        }
-
-        // TODO: should we pass all the keys to DOM or check the meta tag
-        if (nativeCursorWantsKeyEvents() || true) {
-            // pass the key to DOM
-            mWebViewCore.sendMessage(EventHub.KEY_DOWN, event);
-            // return true as DOM handles the key
-            return true;
-        }
-
-        // Bubble up the key event as WebView doesn't handle it
-        return false;
-    }
-
-    @Override
-    public boolean onKeyUp(int keyCode, KeyEvent event) {
-        if (DebugFlags.WEB_VIEW) {
-            Log.v(LOGTAG, "keyUp at " + System.currentTimeMillis()
-                    + ", " + event + ", unicode=" + event.getUnicodeChar());
-        }
-        if (mBlockWebkitViewMessages) {
-            return false;
-        }
-
-        if (mNativeClass == 0) {
-            return false;
-        }
-
-        // special CALL handling when cursor node's href is "tel:XXX"
-        if (keyCode == KeyEvent.KEYCODE_CALL && nativeHasCursorNode()) {
-            String text = nativeCursorText();
-            if (!nativeCursorIsTextInput() && text != null
-                    && text.startsWith(SCHEME_TEL)) {
-                Intent intent = new Intent(Intent.ACTION_DIAL, Uri.parse(text));
-                getContext().startActivity(intent);
-                return true;
-            }
-        }
-
-        // Bubble up the key event if
-        // 1. it is a system key; or
-        // 2. the host application wants to handle it;
-        if (event.isSystem()
-                || mCallbackProxy.uiOverrideKeyEvent(event)) {
-            return false;
-        }
-
-        // accessibility support
-        if (accessibilityScriptInjected()) {
-            if (AccessibilityManager.getInstance(mContext).isEnabled()) {
-                // if an accessibility script is injected we delegate to it the key handling.
-                // this script is a screen reader which is a fully fledged solution for blind
-                // users to navigate in and interact with web pages.
-                mWebViewCore.sendMessage(EventHub.KEY_UP, event);
-                return true;
-            } else {
-                // Clean up if accessibility was disabled after loading the current URL.
-                mAccessibilityScriptInjected = false;
-            }
-        } else if (mAccessibilityInjector != null) {
-            if (AccessibilityManager.getInstance(mContext).isEnabled()) {
-                if (mAccessibilityInjector.onKeyEvent(event)) {
-                    // if an accessibility injector is present (no JavaScript enabled or the site
-                    // opts out injecting our JavaScript screen reader) we let it decide whether to
-                    // act on and consume the event.
-                    return true;
-                }
-            } else {
-                // Clean up if accessibility was disabled after loading the current URL.
-                mAccessibilityInjector = null;
-            }
-        }
-
-        if (keyCode >= KeyEvent.KEYCODE_DPAD_UP
-                && keyCode <= KeyEvent.KEYCODE_DPAD_RIGHT) {
-            if (nativePageShouldHandleShiftAndArrows()) {
-                letPageHandleNavKey(keyCode, event.getEventTime(), false, event.getMetaState());
-                return true;
-            }
-            // always handle the navigation keys in the UI thread
-            // Bubble up the key event as WebView doesn't handle it
-            return false;
-        }
-
-        if (isEnterActionKey(keyCode)) {
-            // remove the long press message first
-            mPrivateHandler.removeMessages(LONG_PRESS_CENTER);
-            mGotCenterDown = false;
-
-            if (mSelectingText) {
-                copySelection();
-                selectionDone();
-                return true; // discard press if copy in progress
-            }
-
-            if (!sDisableNavcache) {
-                // 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;
-                }
-                WebViewCore.CursorData data = cursorData();
-                mWebViewCore.sendMessage(EventHub.SET_MOVE_MOUSE, data);
-                playSoundEffect(SoundEffectConstants.CLICK);
-                if (nativeCursorIsTextInput()) {
-                    rebuildWebTextView();
-                    centerKeyPressOnTextField();
-                    if (inEditingMode()) {
-                        mWebTextView.setDefaultSelection();
-                    }
-                    return true;
-                }
-                clearTextEntry();
-                nativeShowCursorTimed();
-                if (mCallbackProxy.uiOverrideUrlLoading(nativeCursorText())) {
-                    return true;
-                }
-                if (nativeCursorNodePointer() != 0 && !nativeCursorWantsKeyEvents()) {
-                    mWebViewCore.sendMessage(EventHub.CLICK, data.mFrame,
-                            nativeCursorNodePointer());
-                    return true;
-                }
-            }
-        }
-
-        // TODO: should we pass all the keys to DOM or check the meta tag
-        if (nativeCursorWantsKeyEvents() || true) {
-            // pass the key to DOM
-            mWebViewCore.sendMessage(EventHub.KEY_UP, event);
-            // return true as DOM handles the key
-            return true;
-        }
-
-        // Bubble up the key event as WebView doesn't handle it
-        return false;
-    }
-
-    private boolean startSelectActionMode() {
-        mSelectCallback = new SelectActionModeCallback();
-        mSelectCallback.setTextSelected(!mIsCaretSelection);
-        mSelectCallback.setWebView(this);
-        if (startActionMode(mSelectCallback) == null) {
-            // There is no ActionMode, so do not allow the user to modify a
-            // selection.
-            selectionDone();
-            return false;
-        }
-        performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
-        return true;
-    }
-
-    private void showPasteWindow() {
-        ClipboardManager cm = (ClipboardManager)(mContext
-                .getSystemService(Context.CLIPBOARD_SERVICE));
-        if (cm.hasPrimaryClip()) {
-            Rect cursorRect = contentToViewRect(mSelectCursorBase);
-            int[] location = new int[2];
-            getLocationInWindow(location);
-            cursorRect.offset(location[0] - mScrollX, location[1] - mScrollY);
-            if (mPasteWindow == null) {
-                mPasteWindow = new PastePopupWindow();
-            }
-            mPasteWindow.show(cursorRect, location[0], location[1]);
-        }
-    }
-
-    private void hidePasteButton() {
-        if (mPasteWindow != null) {
-            mPasteWindow.hide();
-        }
-    }
-
-    private void syncSelectionCursors() {
-        mSelectCursorBaseLayerId =
-                nativeGetHandleLayerId(mNativeClass, HANDLE_ID_BASE, mSelectCursorBase);
-        mSelectCursorExtentLayerId =
-                nativeGetHandleLayerId(mNativeClass, HANDLE_ID_EXTENT, mSelectCursorExtent);
-    }
-
-    private boolean setupWebkitSelect() {
-        syncSelectionCursors();
-        if (mIsCaretSelection) {
-            showPasteWindow();
-        } else if (!startSelectActionMode()) {
-            selectionDone();
-            return false;
-        }
-        mSelectingText = true;
-        mTouchMode = TOUCH_DRAG_MODE;
-        return true;
-    }
-
-    private void updateWebkitSelection() {
-        int[] handles = null;
-        if (mIsCaretSelection) {
-            mSelectCursorExtent.set(mSelectCursorBase);
-        }
-        if (mSelectingText) {
-            handles = new int[4];
-            handles[0] = mSelectCursorBase.centerX();
-            handles[1] = mSelectCursorBase.centerY();
-            handles[2] = mSelectCursorExtent.centerX();
-            handles[3] = mSelectCursorExtent.centerY();
-        } else {
-            nativeSetTextSelection(mNativeClass, 0);
-        }
-        mWebViewCore.removeMessages(EventHub.SELECT_TEXT);
-        mWebViewCore.sendMessageAtFrontOfQueue(EventHub.SELECT_TEXT, handles);
-    }
-
-    private void resetCaretTimer() {
-        mPrivateHandler.removeMessages(CLEAR_CARET_HANDLE);
-        if (!mSelectionStarted) {
-            mPrivateHandler.sendEmptyMessageDelayed(CLEAR_CARET_HANDLE,
-                    CARET_HANDLE_STAMINA_MS);
-        }
-    }
-
     /**
      * Use this method to put the WebView into text selection mode.
      * Do not rely on this functionality; it will be deprecated in the future.
@@ -6149,165 +1433,7 @@
     @Deprecated
     public void emulateShiftHeld() {
         checkThread();
-    }
-
-    /**
-     * Select all of the text in this WebView.
-     *
-     * @hide This is an implementation detail.
-     */
-    public void selectAll() {
-        mWebViewCore.sendMessage(EventHub.SELECT_ALL);
-    }
-
-    /**
-     * Called when the selection has been removed.
-     */
-    void selectionDone() {
-        if (mSelectingText) {
-            hidePasteButton();
-            mSelectingText = false;
-            // finish is idempotent, so this is fine even if selectionDone was
-            // called by mSelectCallback.onDestroyActionMode
-            if (mSelectCallback != null) {
-                mSelectCallback.finish();
-                mSelectCallback = null;
-            }
-            if (!mIsCaretSelection) {
-                updateWebkitSelection();
-            }
-            mIsCaretSelection = false;
-            invalidate(); // redraw without selection
-            mAutoScrollX = 0;
-            mAutoScrollY = 0;
-            mSentAutoScrollMessage = false;
-        }
-    }
-
-    /**
-     * Copy the selection to the clipboard
-     *
-     * @hide This is an implementation detail.
-     */
-    public boolean copySelection() {
-        boolean copiedSomething = false;
-        String selection = getSelection();
-        if (selection != null && selection != "") {
-            if (DebugFlags.WEB_VIEW) {
-                Log.v(LOGTAG, "copySelection \"" + selection + "\"");
-            }
-            Toast.makeText(mContext
-                    , com.android.internal.R.string.text_copied
-                    , Toast.LENGTH_SHORT).show();
-            copiedSomething = true;
-            ClipboardManager cm = (ClipboardManager)getContext()
-                    .getSystemService(Context.CLIPBOARD_SERVICE);
-            cm.setText(selection);
-            int[] handles = new int[4];
-            getSelectionHandles(handles);
-            mWebViewCore.sendMessage(EventHub.COPY_TEXT, handles);
-        }
-        invalidate(); // remove selection region and pointer
-        return copiedSomething;
-    }
-
-    /**
-     * Cut the selected text into the clipboard
-     *
-     * @hide This is an implementation detail
-     */
-    public void cutSelection() {
-        copySelection();
-        int[] handles = new int[4];
-        getSelectionHandles(handles);
-        mWebViewCore.sendMessage(EventHub.DELETE_TEXT, handles);
-    }
-
-    /**
-     * Paste text from the clipboard to the cursor position.
-     *
-     * @hide This is an implementation detail
-     */
-    public void pasteFromClipboard() {
-        ClipboardManager cm = (ClipboardManager)getContext()
-                .getSystemService(Context.CLIPBOARD_SERVICE);
-        ClipData clipData = cm.getPrimaryClip();
-        if (clipData != null) {
-            ClipData.Item clipItem = clipData.getItemAt(0);
-            CharSequence pasteText = clipItem.getText();
-            if (mInputConnection != null) {
-                mInputConnection.replaceSelection(pasteText);
-            }
-        }
-    }
-
-    /**
-     * @hide This is an implementation detail.
-     */
-    public SearchBox getSearchBox() {
-        if ((mWebViewCore == null) || (mWebViewCore.getBrowserFrame() == null)) {
-            return null;
-        }
-        return mWebViewCore.getBrowserFrame().getSearchBox();
-    }
-
-    /**
-     * Returns the currently highlighted text as a string.
-     */
-    String getSelection() {
-        if (mNativeClass == 0) return "";
-        return nativeGetSelection();
-    }
-
-    @Override
-    protected void onAttachedToWindow() {
-        super.onAttachedToWindow();
-        if (hasWindowFocus()) setActive(true);
-        final ViewTreeObserver treeObserver = getViewTreeObserver();
-        if (mGlobalLayoutListener == null) {
-            mGlobalLayoutListener = new InnerGlobalLayoutListener();
-            treeObserver.addOnGlobalLayoutListener(mGlobalLayoutListener);
-        }
-        if (mScrollChangedListener == null) {
-            mScrollChangedListener = new InnerScrollChangedListener();
-            treeObserver.addOnScrollChangedListener(mScrollChangedListener);
-        }
-
-        addAccessibilityApisToJavaScript();
-
-        mTouchEventQueue.reset();
-    }
-
-    @Override
-    protected void onDetachedFromWindow() {
-        clearHelpers();
-        mZoomManager.dismissZoomPicker();
-        if (hasWindowFocus()) setActive(false);
-
-        final ViewTreeObserver treeObserver = getViewTreeObserver();
-        if (mGlobalLayoutListener != null) {
-            treeObserver.removeGlobalOnLayoutListener(mGlobalLayoutListener);
-            mGlobalLayoutListener = null;
-        }
-        if (mScrollChangedListener != null) {
-            treeObserver.removeOnScrollChangedListener(mScrollChangedListener);
-            mScrollChangedListener = null;
-        }
-
-        removeAccessibilityApisFromJavaScript();
-
-        super.onDetachedFromWindow();
-    }
-
-    @Override
-    protected void onVisibilityChanged(View changedView, int visibility) {
-        super.onVisibilityChanged(changedView, visibility);
-        // The zoomManager may be null if the webview is created from XML that
-        // specifies the view's visibility param as not visible (see http://b/2794841)
-        if (visibility != View.VISIBLE && mZoomManager != null) {
-            mZoomManager.dismissZoomPicker();
-        }
-        updateDrawingState();
+        mProvider.emulateShiftHeld();
     }
 
     /**
@@ -6338,1571 +1464,15 @@
     public void onGlobalFocusChanged(View oldFocus, View newFocus) {
     }
 
-    void setActive(boolean active) {
-        if (active) {
-            if (hasFocus()) {
-                // If our window regained focus, and we have focus, then begin
-                // drawing the cursor ring
-                mDrawCursorRing = !inEditingMode();
-                setFocusControllerActive(true);
-            } else {
-                mDrawCursorRing = false;
-                if (!inEditingMode()) {
-                    // If our window gained focus, but we do not have it, do not
-                    // draw the cursor ring.
-                    setFocusControllerActive(false);
-                }
-                // We do not call recordButtons here because we assume
-                // that when we lost focus, or window focus, it got called with
-                // false for the first parameter
-            }
-        } else {
-            if (!mZoomManager.isZoomPickerVisible()) {
-                /*
-                 * The external zoom controls come in their own window, so our
-                 * window loses focus. Our policy is to not draw the cursor ring
-                 * if our window is not focused, but this is an exception since
-                 * the user can still navigate the web page with the zoom
-                 * controls showing.
-                 */
-                mDrawCursorRing = false;
-            }
-            mKeysPressed.clear();
-            mPrivateHandler.removeMessages(SWITCH_TO_LONGPRESS);
-            mTouchMode = TOUCH_DONE_MODE;
-            setFocusControllerActive(false);
-        }
-        invalidate();
-    }
-
-    // To avoid drawing the cursor ring, and remove the TextView when our window
-    // loses focus.
-    @Override
-    public void onWindowFocusChanged(boolean hasWindowFocus) {
-        setActive(hasWindowFocus);
-        if (hasWindowFocus) {
-            JWebCoreJavaBridge.setActiveWebView(this);
-            if (mPictureUpdatePausedForFocusChange) {
-                WebViewCore.resumeUpdatePicture(mWebViewCore);
-                mPictureUpdatePausedForFocusChange = false;
-            }
-        } else {
-            JWebCoreJavaBridge.removeActiveWebView(this);
-            final WebSettings settings = getSettings();
-            if (settings != null && settings.enableSmoothTransition() &&
-                    mWebViewCore != null && !WebViewCore.isUpdatePicturePaused(mWebViewCore)) {
-                WebViewCore.pauseUpdatePicture(mWebViewCore);
-                mPictureUpdatePausedForFocusChange = true;
-            }
-        }
-        super.onWindowFocusChanged(hasWindowFocus);
-    }
-
-    /*
-     * Pass a message to WebCore Thread, telling the WebCore::Page's
-     * FocusController to be  "inactive" so that it will
-     * not draw the blinking cursor.  It gets set to "active" to draw the cursor
-     * in WebViewCore.cpp, when the WebCore thread receives key events/clicks.
-     */
-    /* package */ void setFocusControllerActive(boolean active) {
-        if (mWebViewCore == null) return;
-        mWebViewCore.sendMessage(EventHub.SET_ACTIVE, active ? 1 : 0, 0);
-        // Need to send this message after the document regains focus.
-        if (active && mListBoxMessage != null) {
-            mWebViewCore.sendMessage(mListBoxMessage);
-            mListBoxMessage = null;
-        }
-    }
-
-    @Override
-    protected void onFocusChanged(boolean focused, int direction,
-            Rect previouslyFocusedRect) {
-        if (DebugFlags.WEB_VIEW) {
-            Log.v(LOGTAG, "MT focusChanged " + focused + ", " + direction);
-        }
-        if (focused) {
-            // When we regain focus, if we have window focus, resume drawing
-            // the cursor ring
-            if (hasWindowFocus()) {
-                mDrawCursorRing = !inEditingMode();
-                setFocusControllerActive(true);
-            //} else {
-                // The WebView has gained focus while we do not have
-                // windowfocus.  When our window lost focus, we should have
-                // called recordButtons(false...)
-            }
-        } else {
-            // When we lost focus, unless focus went to the TextView (which is
-            // true if we are in editing mode), stop drawing the cursor ring.
-            mDrawCursorRing = false;
-            if (!inEditingMode()) {
-                setFocusControllerActive(false);
-            }
-            mKeysPressed.clear();
-        }
-
-        super.onFocusChanged(focused, direction, previouslyFocusedRect);
-    }
-
-    void setGLRectViewport() {
-        // Use the getGlobalVisibleRect() to get the intersection among the parents
-        // visible == false means we're clipped - send a null rect down to indicate that
-        // we should not draw
-        boolean visible = getGlobalVisibleRect(mGLRectViewport);
-        if (visible) {
-            // Then need to invert the Y axis, just for GL
-            View rootView = getRootView();
-            int rootViewHeight = rootView.getHeight();
-            mViewRectViewport.set(mGLRectViewport);
-            int savedWebViewBottom = mGLRectViewport.bottom;
-            mGLRectViewport.bottom = rootViewHeight - mGLRectViewport.top - getVisibleTitleHeightImpl();
-            mGLRectViewport.top = rootViewHeight - savedWebViewBottom;
-            mGLViewportEmpty = false;
-        } else {
-            mGLViewportEmpty = true;
-        }
-        calcOurContentVisibleRectF(mVisibleContentRect);
-        nativeUpdateDrawGLFunction(mGLViewportEmpty ? null : mGLRectViewport,
-                mGLViewportEmpty ? null : mViewRectViewport,
-                mVisibleContentRect, getScale());
-    }
-
-    /**
-     * @hide
-     */
-    @Override
-    protected boolean setFrame(int left, int top, int right, int bottom) {
-        boolean changed = super.setFrame(left, top, right, bottom);
-        if (!changed && mHeightCanMeasure) {
-            // When mHeightCanMeasure is true, we will set mLastHeightSent to 0
-            // in WebViewCore after we get the first layout. We do call
-            // requestLayout() when we get contentSizeChanged(). But the View
-            // system won't call onSizeChanged if the dimension is not changed.
-            // In this case, we need to call sendViewSizeZoom() explicitly to
-            // notify the WebKit about the new dimensions.
-            sendViewSizeZoom(false);
-        }
-        setGLRectViewport();
-        return changed;
-    }
-
-    @Override
-    protected void onSizeChanged(int w, int h, int ow, int oh) {
-        super.onSizeChanged(w, h, ow, oh);
-
-        // adjust the max viewport width depending on the view dimensions. This
-        // is to ensure the scaling is not going insane. So do not shrink it if
-        // the view size is temporarily smaller, e.g. when soft keyboard is up.
-        int newMaxViewportWidth = (int) (Math.max(w, h) / mZoomManager.getDefaultMinZoomScale());
-        if (newMaxViewportWidth > sMaxViewportWidth) {
-            sMaxViewportWidth = newMaxViewportWidth;
-        }
-
-        mZoomManager.onSizeChanged(w, h, ow, oh);
-
-        if (mLoadedPicture != null && mDelaySetPicture == null) {
-            // Size changes normally result in a new picture
-            // Re-set the loaded picture to simulate that
-            // However, do not update the base layer as that hasn't changed
-            setNewPicture(mLoadedPicture, false);
-        }
-    }
-
-    @Override
-    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
-        super.onScrollChanged(l, t, oldl, oldt);
-        if (!mInOverScrollMode) {
-            sendOurVisibleRect();
-            // update WebKit if visible title bar height changed. The logic is same
-            // as getVisibleTitleHeightImpl.
-            int titleHeight = getTitleHeight();
-            if (Math.max(titleHeight - t, 0) != Math.max(titleHeight - oldt, 0)) {
-                sendViewSizeZoom(false);
-            }
-        }
-    }
-
-    @Override
-    public boolean dispatchKeyEvent(KeyEvent event) {
-        switch (event.getAction()) {
-            case KeyEvent.ACTION_DOWN:
-                mKeysPressed.add(Integer.valueOf(event.getKeyCode()));
-                break;
-            case KeyEvent.ACTION_MULTIPLE:
-                // Always accept the action.
-                break;
-            case KeyEvent.ACTION_UP:
-                int location = mKeysPressed.indexOf(Integer.valueOf(event.getKeyCode()));
-                if (location == -1) {
-                    // We did not receive the key down for this key, so do not
-                    // handle the key up.
-                    return false;
-                } else {
-                    // We did receive the key down.  Handle the key up, and
-                    // remove it from our pressed keys.
-                    mKeysPressed.remove(location);
-                }
-                break;
-            default:
-                // Accept the action.  This should not happen, unless a new
-                // action is added to KeyEvent.
-                break;
-        }
-        if (inEditingMode() && mWebTextView.isFocused()) {
-            // Ensure that the WebTextView gets the event, even if it does
-            // not currently have a bounds.
-            return mWebTextView.dispatchKeyEvent(event);
-        } else {
-            return super.dispatchKeyEvent(event);
-        }
-    }
-
-    /*
-     * Here is the snap align logic:
-     * 1. If it starts nearly horizontally or vertically, snap align;
-     * 2. If there is a dramitic direction change, let it go;
-     *
-     * Adjustable parameters. Angle is the radians on a unit circle, limited
-     * to quadrant 1. Values range from 0f (horizontal) to PI/2 (vertical)
-     */
-    private static final float HSLOPE_TO_START_SNAP = .25f;
-    private static final float HSLOPE_TO_BREAK_SNAP = .4f;
-    private static final float VSLOPE_TO_START_SNAP = 1.25f;
-    private static final float VSLOPE_TO_BREAK_SNAP = .95f;
-    /*
-     *  These values are used to influence the average angle when entering
-     *  snap mode. If is is the first movement entering snap, we set the average
-     *  to the appropriate ideal. If the user is entering into snap after the
-     *  first movement, then we average the average angle with these values.
-     */
-    private static final float ANGLE_VERT = 2f;
-    private static final float ANGLE_HORIZ = 0f;
-    /*
-     *  The modified moving average weight.
-     *  Formula: MAV[t]=MAV[t-1] + (P[t]-MAV[t-1])/n
-     */
-    private static final float MMA_WEIGHT_N = 5;
-
-    private boolean hitFocusedPlugin(int contentX, int contentY) {
-        if (DebugFlags.WEB_VIEW) {
-            Log.v(LOGTAG, "nativeFocusIsPlugin()=" + nativeFocusIsPlugin());
-            Rect r = nativeFocusNodeBounds();
-            Log.v(LOGTAG, "nativeFocusNodeBounds()=(" + r.left + ", " + r.top
-                    + ", " + r.right + ", " + r.bottom + ")");
-        }
-        return nativeFocusIsPlugin()
-                && nativeFocusNodeBounds().contains(contentX, contentY);
-    }
-
-    private boolean shouldForwardTouchEvent() {
-        if (mFullScreenHolder != null) return true;
-        if (mBlockWebkitViewMessages) return false;
-        return mForwardTouchEvents
-                && !mSelectingText
-                && mPreventDefault != PREVENT_DEFAULT_IGNORE
-                && mPreventDefault != PREVENT_DEFAULT_NO;
-    }
-
-    private boolean inFullScreenMode() {
-        return mFullScreenHolder != null;
-    }
-
-    private void dismissFullScreenMode() {
-        if (inFullScreenMode()) {
-            mFullScreenHolder.hide();
-            mFullScreenHolder = null;
-            invalidate();
-        }
-    }
-
-    void onPinchToZoomAnimationStart() {
-        // cancel the single touch handling
-        cancelTouch();
-        onZoomAnimationStart();
-    }
-
-    void onPinchToZoomAnimationEnd(ScaleGestureDetector detector) {
-        onZoomAnimationEnd();
-        // start a drag, TOUCH_PINCH_DRAG, can't use TOUCH_INIT_MODE as
-        // it may trigger the unwanted click, can't use TOUCH_DRAG_MODE
-        // as it may trigger the unwanted fling.
-        mTouchMode = TOUCH_PINCH_DRAG;
-        mConfirmMove = true;
-        startTouch(detector.getFocusX(), detector.getFocusY(), mLastTouchTime);
-    }
-
-    // See if there is a layer at x, y and switch to TOUCH_DRAG_LAYER_MODE if a
-    // layer is found.
-    private void startScrollingLayer(float x, float y) {
-        int contentX = viewToContentX((int) x + mScrollX);
-        int contentY = viewToContentY((int) y + mScrollY);
-        mCurrentScrollingLayerId = nativeScrollableLayer(contentX, contentY,
-                mScrollingLayerRect, mScrollingLayerBounds);
-        if (mCurrentScrollingLayerId != 0) {
-            mTouchMode = TOUCH_DRAG_LAYER_MODE;
-        }
-    }
-
-    // 1/(density * density) used to compute the distance between points.
-    // Computed in init().
-    private float DRAG_LAYER_INVERSE_DENSITY_SQUARED;
-
-    // The distance between two points reported in onTouchEvent scaled by the
-    // density of the screen.
-    private static final int DRAG_LAYER_FINGER_DISTANCE = 20000;
-
-    @Override
-    public boolean onHoverEvent(MotionEvent event) {
-        if (mNativeClass == 0) {
-            return false;
-        }
-        WebViewCore.CursorData data = cursorDataNoPosition();
-        data.mX = viewToContentX((int) event.getX() + mScrollX);
-        data.mY = viewToContentY((int) event.getY() + mScrollY);
-        mWebViewCore.sendMessage(EventHub.SET_MOVE_MOUSE, data);
-        return true;
-    }
-
-    @Override
-    public boolean onTouchEvent(MotionEvent ev) {
-        if (mNativeClass == 0 || (!isClickable() && !isLongClickable())) {
-            return false;
-        }
-
-        if (DebugFlags.WEB_VIEW) {
-            Log.v(LOGTAG, ev + " at " + ev.getEventTime()
-                + " mTouchMode=" + mTouchMode
-                + " numPointers=" + ev.getPointerCount());
-        }
-
-        // If WebKit wasn't interested in this multitouch gesture, enqueue
-        // the event for handling directly rather than making the round trip
-        // to WebKit and back.
-        if (ev.getPointerCount() > 1 && mPreventDefault != PREVENT_DEFAULT_NO) {
-            passMultiTouchToWebKit(ev, mTouchEventQueue.nextTouchSequence());
-        } else {
-            mTouchEventQueue.enqueueTouchEvent(ev);
-        }
-
-        // Since all events are handled asynchronously, we always want the gesture stream.
-        return true;
-    }
-
-    private float calculateDragAngle(int dx, int dy) {
-        dx = Math.abs(dx);
-        dy = Math.abs(dy);
-        return (float) Math.atan2(dy, dx);
-    }
-
-    /*
-     * Common code for single touch and multi-touch.
-     * (x, y) denotes current focus point, which is the touch point for single touch
-     * and the middle point for multi-touch.
-     */
-    private boolean handleTouchEventCommon(MotionEvent ev, int action, int x, int y) {
-        long eventTime = ev.getEventTime();
-
-        // Due to the touch screen edge effect, a touch closer to the edge
-        // always snapped to the edge. As getViewWidth() can be different from
-        // getWidth() due to the scrollbar, adjusting the point to match
-        // getViewWidth(). Same applied to the height.
-        x = Math.min(x, getViewWidth() - 1);
-        y = Math.min(y, getViewHeightWithTitle() - 1);
-
-        int deltaX = mLastTouchX - x;
-        int deltaY = mLastTouchY - y;
-        int contentX = viewToContentX(x + mScrollX);
-        int contentY = viewToContentY(y + mScrollY);
-
-        switch (action) {
-            case MotionEvent.ACTION_DOWN: {
-                mPreventDefault = PREVENT_DEFAULT_NO;
-                mConfirmMove = false;
-                mInitialHitTestResult = null;
-                if (!mScroller.isFinished()) {
-                    // stop the current scroll animation, but if this is
-                    // the start of a fling, allow it to add to the current
-                    // fling's velocity
-                    mScroller.abortAnimation();
-                    mTouchMode = TOUCH_DRAG_START_MODE;
-                    mConfirmMove = true;
-                    nativeSetIsScrolling(false);
-                } else if (mPrivateHandler.hasMessages(RELEASE_SINGLE_TAP)) {
-                    mPrivateHandler.removeMessages(RELEASE_SINGLE_TAP);
-                    if (sDisableNavcache) {
-                        removeTouchHighlight();
-                    }
-                    if (deltaX * deltaX + deltaY * deltaY < mDoubleTapSlopSquare) {
-                        mTouchMode = TOUCH_DOUBLE_TAP_MODE;
-                    } else {
-                        // commit the short press action for the previous tap
-                        doShortPress();
-                        mTouchMode = TOUCH_INIT_MODE;
-                        mDeferTouchProcess = !mBlockWebkitViewMessages
-                                && (!inFullScreenMode() && mForwardTouchEvents)
-                                ? hitFocusedPlugin(contentX, contentY)
-                                : false;
-                    }
-                } else { // the normal case
-                    mTouchMode = TOUCH_INIT_MODE;
-                    mDeferTouchProcess = !mBlockWebkitViewMessages
-                            && (!inFullScreenMode() && mForwardTouchEvents)
-                            ? hitFocusedPlugin(contentX, contentY)
-                            : false;
-                    if (!mBlockWebkitViewMessages) {
-                        mWebViewCore.sendMessage(
-                                EventHub.UPDATE_FRAME_CACHE_IF_LOADING);
-                    }
-                    if (sDisableNavcache) {
-                        TouchHighlightData data = new TouchHighlightData();
-                        data.mX = contentX;
-                        data.mY = contentY;
-                        data.mNativeLayerRect = new Rect();
-                        data.mNativeLayer = nativeScrollableLayer(
-                                contentX, contentY, data.mNativeLayerRect, null);
-                        data.mSlop = viewToContentDimension(mNavSlop);
-                        mTouchHighlightRegion.setEmpty();
-                        if (!mBlockWebkitViewMessages) {
-                            mTouchHighlightRequested = System.currentTimeMillis();
-                            mWebViewCore.sendMessageAtFrontOfQueue(
-                                    EventHub.HIT_TEST, data);
-                        }
-                        if (DEBUG_TOUCH_HIGHLIGHT) {
-                            if (getSettings().getNavDump()) {
-                                mTouchHighlightX = x + mScrollX;
-                                mTouchHighlightY = y + mScrollY;
-                                mPrivateHandler.postDelayed(new Runnable() {
-                                    @Override
-                                    public void run() {
-                                        mTouchHighlightX = mTouchHighlightY = 0;
-                                        invalidate();
-                                    }
-                                }, TOUCH_HIGHLIGHT_ELAPSE_TIME);
-                            }
-                        }
-                    }
-                    if (mLogEvent && eventTime - mLastTouchUpTime < 1000) {
-                        EventLog.writeEvent(EventLogTags.BROWSER_DOUBLE_TAP_DURATION,
-                                (eventTime - mLastTouchUpTime), eventTime);
-                    }
-                    mSelectionStarted = false;
-                    if (mSelectingText) {
-                        int shiftedY = y - getTitleHeight() + mScrollY;
-                        int shiftedX = x + mScrollX;
-                        if (mSelectHandleCenter != null && mSelectHandleCenter.getBounds()
-                                .contains(shiftedX, shiftedY)) {
-                            mSelectionStarted = true;
-                            mSelectDraggingCursor = mSelectCursorBase;
-                            mPrivateHandler.removeMessages(CLEAR_CARET_HANDLE);
-                            hidePasteButton();
-                        } else if (mSelectHandleLeft != null
-                                && mSelectHandleLeft.getBounds()
-                                    .contains(shiftedX, shiftedY)) {
-                                mSelectionStarted = true;
-                                mSelectDraggingCursor = mSelectCursorBase;
-                        } else if (mSelectHandleRight != null
-                                && mSelectHandleRight.getBounds()
-                                .contains(shiftedX, shiftedY)) {
-                            mSelectionStarted = true;
-                            mSelectDraggingCursor = mSelectCursorExtent;
-                        } else if (mIsCaretSelection) {
-                            selectionDone();
-                        }
-                        if (mSelectDraggingCursor != null) {
-                            mSelectDraggingOffset.set(
-                                    mSelectDraggingCursor.left - contentX,
-                                    mSelectDraggingCursor.top - contentY);
-                        }
-                        if (DebugFlags.WEB_VIEW) {
-                            Log.v(LOGTAG, "select=" + contentX + "," + contentY);
-                        }
-                    }
-                }
-                // Trigger the link
-                if (!mSelectingText && (mTouchMode == TOUCH_INIT_MODE
-                        || mTouchMode == TOUCH_DOUBLE_TAP_MODE)) {
-                    mPrivateHandler.sendEmptyMessageDelayed(
-                            SWITCH_TO_SHORTPRESS, TAP_TIMEOUT);
-                    mPrivateHandler.sendEmptyMessageDelayed(
-                            SWITCH_TO_LONGPRESS, LONG_PRESS_TIMEOUT);
-                    if (inFullScreenMode() || mDeferTouchProcess) {
-                        mPreventDefault = PREVENT_DEFAULT_YES;
-                    } else if (!mBlockWebkitViewMessages && mForwardTouchEvents) {
-                        mPreventDefault = PREVENT_DEFAULT_MAYBE_YES;
-                    } else {
-                        mPreventDefault = PREVENT_DEFAULT_NO;
-                    }
-                    // pass the touch events from UI thread to WebCore thread
-                    if (shouldForwardTouchEvent()) {
-                        TouchEventData ted = new TouchEventData();
-                        ted.mAction = action;
-                        ted.mIds = new int[1];
-                        ted.mIds[0] = ev.getPointerId(0);
-                        ted.mPoints = new Point[1];
-                        ted.mPoints[0] = new Point(contentX, contentY);
-                        ted.mPointsInView = new Point[1];
-                        ted.mPointsInView[0] = new Point(x, y);
-                        ted.mMetaState = ev.getMetaState();
-                        ted.mReprocess = mDeferTouchProcess;
-                        ted.mNativeLayer = nativeScrollableLayer(
-                                contentX, contentY, ted.mNativeLayerRect, null);
-                        ted.mSequence = mTouchEventQueue.nextTouchSequence();
-                        mTouchEventQueue.preQueueTouchEventData(ted);
-                        mWebViewCore.sendMessage(EventHub.TOUCH_EVENT, ted);
-                        if (mDeferTouchProcess) {
-                            // still needs to set them for compute deltaX/Y
-                            mLastTouchX = x;
-                            mLastTouchY = y;
-                            break;
-                        }
-                        if (!inFullScreenMode()) {
-                            mPrivateHandler.removeMessages(PREVENT_DEFAULT_TIMEOUT);
-                            mPrivateHandler.sendMessageDelayed(mPrivateHandler
-                                    .obtainMessage(PREVENT_DEFAULT_TIMEOUT,
-                                            action, 0), TAP_TIMEOUT);
-                        }
-                    }
-                }
-                startTouch(x, y, eventTime);
-                break;
-            }
-            case MotionEvent.ACTION_MOVE: {
-                boolean firstMove = false;
-                if (!mConfirmMove && (deltaX * deltaX + deltaY * deltaY)
-                        >= mTouchSlopSquare) {
-                    mPrivateHandler.removeMessages(SWITCH_TO_SHORTPRESS);
-                    mPrivateHandler.removeMessages(SWITCH_TO_LONGPRESS);
-                    mConfirmMove = true;
-                    firstMove = true;
-                    if (mTouchMode == TOUCH_DOUBLE_TAP_MODE) {
-                        mTouchMode = TOUCH_INIT_MODE;
-                    }
-                    if (sDisableNavcache) {
-                        removeTouchHighlight();
-                    }
-                }
-                if (mSelectingText && mSelectionStarted) {
-                    if (DebugFlags.WEB_VIEW) {
-                        Log.v(LOGTAG, "extend=" + contentX + "," + contentY);
-                    }
-                    ViewParent parent = getParent();
-                    if (parent != null) {
-                        parent.requestDisallowInterceptTouchEvent(true);
-                    }
-                    if (deltaX != 0 || deltaY != 0) {
-                        mSelectDraggingCursor.offsetTo(
-                                contentX + mSelectDraggingOffset.x,
-                                contentY + mSelectDraggingOffset.y);
-                        updateWebkitSelection();
-                        mLastTouchX = x;
-                        mLastTouchY = y;
-                        invalidate();
-                    }
-                    break;
-                }
-
-                // pass the touch events from UI thread to WebCore thread
-                if (shouldForwardTouchEvent() && mConfirmMove && (firstMove
-                        || eventTime - mLastSentTouchTime > mCurrentTouchInterval)) {
-                    TouchEventData ted = new TouchEventData();
-                    ted.mAction = action;
-                    ted.mIds = new int[1];
-                    ted.mIds[0] = ev.getPointerId(0);
-                    ted.mPoints = new Point[1];
-                    ted.mPoints[0] = new Point(contentX, contentY);
-                    ted.mPointsInView = new Point[1];
-                    ted.mPointsInView[0] = new Point(x, y);
-                    ted.mMetaState = ev.getMetaState();
-                    ted.mReprocess = mDeferTouchProcess;
-                    ted.mNativeLayer = mCurrentScrollingLayerId;
-                    ted.mNativeLayerRect.set(mScrollingLayerRect);
-                    ted.mSequence = mTouchEventQueue.nextTouchSequence();
-                    mTouchEventQueue.preQueueTouchEventData(ted);
-                    mWebViewCore.sendMessage(EventHub.TOUCH_EVENT, ted);
-                    mLastSentTouchTime = eventTime;
-                    if (mDeferTouchProcess) {
-                        break;
-                    }
-                    if (firstMove && !inFullScreenMode()) {
-                        mPrivateHandler.sendMessageDelayed(mPrivateHandler
-                                .obtainMessage(PREVENT_DEFAULT_TIMEOUT,
-                                        action, 0), TAP_TIMEOUT);
-                    }
-                }
-                if (mTouchMode == TOUCH_DONE_MODE
-                        || mPreventDefault == PREVENT_DEFAULT_YES) {
-                    // no dragging during scroll zoom animation, or when prevent
-                    // default is yes
-                    break;
-                }
-                if (mVelocityTracker == null) {
-                    Log.e(LOGTAG, "Got null mVelocityTracker when "
-                            + "mPreventDefault = " + mPreventDefault
-                            + " mDeferTouchProcess = " + mDeferTouchProcess
-                            + " mTouchMode = " + mTouchMode);
-                } else {
-                    mVelocityTracker.addMovement(ev);
-                }
-
-                if (mTouchMode != TOUCH_DRAG_MODE &&
-                        mTouchMode != TOUCH_DRAG_LAYER_MODE) {
-
-                    if (!mConfirmMove) {
-                        break;
-                    }
-
-                    if (mPreventDefault == PREVENT_DEFAULT_MAYBE_YES
-                            || mPreventDefault == PREVENT_DEFAULT_NO_FROM_TOUCH_DOWN) {
-                        // track mLastTouchTime as we may need to do fling at
-                        // ACTION_UP
-                        mLastTouchTime = eventTime;
-                        break;
-                    }
-
-                    // Only lock dragging to one axis if we don't have a scale in progress.
-                    // Scaling implies free-roaming movement. Note this is only ever a question
-                    // if mZoomManager.supportsPanDuringZoom() is true.
-                    final ScaleGestureDetector detector =
-                      mZoomManager.getMultiTouchGestureDetector();
-                    mAverageAngle = calculateDragAngle(deltaX, deltaY);
-                    if (detector == null || !detector.isInProgress()) {
-                        // if it starts nearly horizontal or vertical, enforce it
-                        if (mAverageAngle < HSLOPE_TO_START_SNAP) {
-                            mSnapScrollMode = SNAP_X;
-                            mSnapPositive = deltaX > 0;
-                            mAverageAngle = ANGLE_HORIZ;
-                        } else if (mAverageAngle > VSLOPE_TO_START_SNAP) {
-                            mSnapScrollMode = SNAP_Y;
-                            mSnapPositive = deltaY > 0;
-                            mAverageAngle = ANGLE_VERT;
-                        }
-                    }
-
-                    mTouchMode = TOUCH_DRAG_MODE;
-                    mLastTouchX = x;
-                    mLastTouchY = y;
-                    deltaX = 0;
-                    deltaY = 0;
-
-                    startScrollingLayer(x, y);
-                    startDrag();
-                }
-
-                // do pan
-                boolean done = false;
-                boolean keepScrollBarsVisible = false;
-                if (deltaX == 0 && deltaY == 0) {
-                    keepScrollBarsVisible = done = true;
-                } else {
-                    mAverageAngle +=
-                        (calculateDragAngle(deltaX, deltaY) - mAverageAngle)
-                        / MMA_WEIGHT_N;
-                    if (mSnapScrollMode != SNAP_NONE) {
-                        if (mSnapScrollMode == SNAP_Y) {
-                            // radical change means getting out of snap mode
-                            if (mAverageAngle < VSLOPE_TO_BREAK_SNAP) {
-                                mSnapScrollMode = SNAP_NONE;
-                            }
-                        }
-                        if (mSnapScrollMode == SNAP_X) {
-                            // radical change means getting out of snap mode
-                            if (mAverageAngle > HSLOPE_TO_BREAK_SNAP) {
-                                mSnapScrollMode = SNAP_NONE;
-                            }
-                        }
-                    } else {
-                        if (mAverageAngle < HSLOPE_TO_START_SNAP) {
-                            mSnapScrollMode = SNAP_X;
-                            mSnapPositive = deltaX > 0;
-                            mAverageAngle = (mAverageAngle + ANGLE_HORIZ) / 2;
-                        } else if (mAverageAngle > VSLOPE_TO_START_SNAP) {
-                            mSnapScrollMode = SNAP_Y;
-                            mSnapPositive = deltaY > 0;
-                            mAverageAngle = (mAverageAngle + ANGLE_VERT) / 2;
-                        }
-                    }
-                    if (mSnapScrollMode != SNAP_NONE) {
-                        if ((mSnapScrollMode & SNAP_X) == SNAP_X) {
-                            deltaY = 0;
-                        } else {
-                            deltaX = 0;
-                        }
-                    }
-                    mLastTouchX = x;
-                    mLastTouchY = y;
-
-                    if (deltaX * deltaX + deltaY * deltaY > mTouchSlopSquare) {
-                        mHeldMotionless = MOTIONLESS_FALSE;
-                        nativeSetIsScrolling(true);
-                    } else {
-                        mHeldMotionless = MOTIONLESS_TRUE;
-                        nativeSetIsScrolling(false);
-                        keepScrollBarsVisible = true;
-                    }
-
-                    mLastTouchTime = eventTime;
-                }
-
-                doDrag(deltaX, deltaY);
-
-                // Turn off scrollbars when dragging a layer.
-                if (keepScrollBarsVisible &&
-                        mTouchMode != TOUCH_DRAG_LAYER_MODE) {
-                    if (mHeldMotionless != MOTIONLESS_TRUE) {
-                        mHeldMotionless = MOTIONLESS_TRUE;
-                        invalidate();
-                    }
-                    // keep the scrollbar on the screen even there is no scroll
-                    awakenScrollBars(ViewConfiguration.getScrollDefaultDelay(),
-                            false);
-                    // Post a message so that we'll keep them alive while we're not scrolling.
-                    mPrivateHandler.sendMessageDelayed(mPrivateHandler
-                            .obtainMessage(AWAKEN_SCROLL_BARS),
-                            ViewConfiguration.getScrollDefaultDelay());
-                    // return false to indicate that we can't pan out of the
-                    // view space
-                    return !done;
-                } else {
-                    mPrivateHandler.removeMessages(AWAKEN_SCROLL_BARS);
-                }
-                break;
-            }
-            case MotionEvent.ACTION_UP: {
-                if (!isFocused()) requestFocus();
-                // pass the touch events from UI thread to WebCore thread
-                if (shouldForwardTouchEvent()) {
-                    TouchEventData ted = new TouchEventData();
-                    ted.mIds = new int[1];
-                    ted.mIds[0] = ev.getPointerId(0);
-                    ted.mAction = action;
-                    ted.mPoints = new Point[1];
-                    ted.mPoints[0] = new Point(contentX, contentY);
-                    ted.mPointsInView = new Point[1];
-                    ted.mPointsInView[0] = new Point(x, y);
-                    ted.mMetaState = ev.getMetaState();
-                    ted.mReprocess = mDeferTouchProcess;
-                    ted.mNativeLayer = mCurrentScrollingLayerId;
-                    ted.mNativeLayerRect.set(mScrollingLayerRect);
-                    ted.mSequence = mTouchEventQueue.nextTouchSequence();
-                    mTouchEventQueue.preQueueTouchEventData(ted);
-                    mWebViewCore.sendMessage(EventHub.TOUCH_EVENT, ted);
-                }
-                mLastTouchUpTime = eventTime;
-                if (mSentAutoScrollMessage) {
-                    mAutoScrollX = mAutoScrollY = 0;
-                }
-                switch (mTouchMode) {
-                    case TOUCH_DOUBLE_TAP_MODE: // double tap
-                        mPrivateHandler.removeMessages(SWITCH_TO_SHORTPRESS);
-                        mPrivateHandler.removeMessages(SWITCH_TO_LONGPRESS);
-                        if (inFullScreenMode() || mDeferTouchProcess) {
-                            TouchEventData ted = new TouchEventData();
-                            ted.mIds = new int[1];
-                            ted.mIds[0] = ev.getPointerId(0);
-                            ted.mAction = WebViewCore.ACTION_DOUBLETAP;
-                            ted.mPoints = new Point[1];
-                            ted.mPoints[0] = new Point(contentX, contentY);
-                            ted.mPointsInView = new Point[1];
-                            ted.mPointsInView[0] = new Point(x, y);
-                            ted.mMetaState = ev.getMetaState();
-                            ted.mReprocess = mDeferTouchProcess;
-                            ted.mNativeLayer = nativeScrollableLayer(
-                                    contentX, contentY,
-                                    ted.mNativeLayerRect, null);
-                            ted.mSequence = mTouchEventQueue.nextTouchSequence();
-                            mTouchEventQueue.preQueueTouchEventData(ted);
-                            mWebViewCore.sendMessage(EventHub.TOUCH_EVENT, ted);
-                        } else if (mPreventDefault != PREVENT_DEFAULT_YES){
-                            mZoomManager.handleDoubleTap(mLastTouchX, mLastTouchY);
-                            mTouchMode = TOUCH_DONE_MODE;
-                        }
-                        break;
-                    case TOUCH_INIT_MODE: // tap
-                    case TOUCH_SHORTPRESS_START_MODE:
-                    case TOUCH_SHORTPRESS_MODE:
-                        mPrivateHandler.removeMessages(SWITCH_TO_SHORTPRESS);
-                        mPrivateHandler.removeMessages(SWITCH_TO_LONGPRESS);
-                        if (mConfirmMove) {
-                            Log.w(LOGTAG, "Miss a drag as we are waiting for" +
-                                    " WebCore's response for touch down.");
-                            if (mPreventDefault != PREVENT_DEFAULT_YES
-                                    && (computeMaxScrollX() > 0
-                                            || computeMaxScrollY() > 0)) {
-                                // If the user has performed a very quick touch
-                                // sequence it is possible that we may get here
-                                // before WebCore has had a chance to process the events.
-                                // In this case, any call to preventDefault in the
-                                // JS touch handler will not have been executed yet.
-                                // Hence we will see both the UI (now) and WebCore
-                                // (when context switches) handling the event,
-                                // regardless of whether the web developer actually
-                                // doeses preventDefault in their touch handler. This
-                                // is the nature of our asynchronous touch model.
-
-                                // we will not rewrite drag code here, but we
-                                // will try fling if it applies.
-                                WebViewCore.reducePriority();
-                                // to get better performance, pause updating the
-                                // picture
-                                WebViewCore.pauseUpdatePicture(mWebViewCore);
-                                // fall through to TOUCH_DRAG_MODE
-                            } else {
-                                // WebKit may consume the touch event and modify
-                                // DOM. drawContentPicture() will be called with
-                                // animateSroll as true for better performance.
-                                // Force redraw in high-quality.
-                                invalidate();
-                                break;
-                            }
-                        } else {
-                            if (mSelectingText) {
-                                // tapping on selection or controls does nothing
-                                if (!mSelectionStarted) {
-                                    selectionDone();
-                                }
-                                break;
-                            }
-                            // only trigger double tap if the WebView is
-                            // scalable
-                            if (mTouchMode == TOUCH_INIT_MODE
-                                    && (canZoomIn() || canZoomOut())) {
-                                mPrivateHandler.sendEmptyMessageDelayed(
-                                        RELEASE_SINGLE_TAP, ViewConfiguration
-                                                .getDoubleTapTimeout());
-                            } else {
-                                doShortPress();
-                            }
-                            break;
-                        }
-                    case TOUCH_DRAG_MODE:
-                    case TOUCH_DRAG_LAYER_MODE:
-                        mPrivateHandler.removeMessages(DRAG_HELD_MOTIONLESS);
-                        mPrivateHandler.removeMessages(AWAKEN_SCROLL_BARS);
-                        // if the user waits a while w/o moving before the
-                        // up, we don't want to do a fling
-                        if (eventTime - mLastTouchTime <= MIN_FLING_TIME) {
-                            if (mVelocityTracker == null) {
-                                Log.e(LOGTAG, "Got null mVelocityTracker when "
-                                        + "mPreventDefault = "
-                                        + mPreventDefault
-                                        + " mDeferTouchProcess = "
-                                        + mDeferTouchProcess);
-                            } else {
-                                mVelocityTracker.addMovement(ev);
-                            }
-                            // set to MOTIONLESS_IGNORE so that it won't keep
-                            // removing and sending message in
-                            // drawCoreAndCursorRing()
-                            mHeldMotionless = MOTIONLESS_IGNORE;
-                            doFling();
-                            break;
-                        } else {
-                            if (mScroller.springBack(mScrollX, mScrollY, 0,
-                                    computeMaxScrollX(), 0,
-                                    computeMaxScrollY())) {
-                                invalidate();
-                            }
-                        }
-                        // redraw in high-quality, as we're done dragging
-                        mHeldMotionless = MOTIONLESS_TRUE;
-                        invalidate();
-                        // fall through
-                    case TOUCH_DRAG_START_MODE:
-                        // TOUCH_DRAG_START_MODE should not happen for the real
-                        // device as we almost certain will get a MOVE. But this
-                        // is possible on emulator.
-                        mLastVelocity = 0;
-                        WebViewCore.resumePriority();
-                        if (!mSelectingText) {
-                            WebViewCore.resumeUpdatePicture(mWebViewCore);
-                        }
-                        break;
-                }
-                stopTouch();
-                break;
-            }
-            case MotionEvent.ACTION_CANCEL: {
-                if (mTouchMode == TOUCH_DRAG_MODE) {
-                    mScroller.springBack(mScrollX, mScrollY, 0,
-                            computeMaxScrollX(), 0, computeMaxScrollY());
-                    invalidate();
-                }
-                cancelWebCoreTouchEvent(contentX, contentY, false);
-                cancelTouch();
-                break;
-            }
-        }
-        return true;
-    }
-
-    private void passMultiTouchToWebKit(MotionEvent ev, long sequence) {
-        TouchEventData ted = new TouchEventData();
-        ted.mAction = ev.getActionMasked();
-        final int count = ev.getPointerCount();
-        ted.mIds = new int[count];
-        ted.mPoints = new Point[count];
-        ted.mPointsInView = new Point[count];
-        for (int c = 0; c < count; c++) {
-            ted.mIds[c] = ev.getPointerId(c);
-            int x = viewToContentX((int) ev.getX(c) + mScrollX);
-            int y = viewToContentY((int) ev.getY(c) + mScrollY);
-            ted.mPoints[c] = new Point(x, y);
-            ted.mPointsInView[c] = new Point((int) ev.getX(c), (int) ev.getY(c));
-        }
-        if (ted.mAction == MotionEvent.ACTION_POINTER_DOWN
-            || ted.mAction == MotionEvent.ACTION_POINTER_UP) {
-            ted.mActionIndex = ev.getActionIndex();
-        }
-        ted.mMetaState = ev.getMetaState();
-        ted.mReprocess = true;
-        ted.mMotionEvent = MotionEvent.obtain(ev);
-        ted.mSequence = sequence;
-        mTouchEventQueue.preQueueTouchEventData(ted);
-        mWebViewCore.sendMessage(EventHub.TOUCH_EVENT, ted);
-        cancelLongPress();
-        mPrivateHandler.removeMessages(SWITCH_TO_LONGPRESS);
-    }
-
-    void handleMultiTouchInWebView(MotionEvent ev) {
-        if (DebugFlags.WEB_VIEW) {
-            Log.v(LOGTAG, "multi-touch: " + ev + " at " + ev.getEventTime()
-                + " mTouchMode=" + mTouchMode
-                + " numPointers=" + ev.getPointerCount()
-                + " scrolloffset=(" + mScrollX + "," + mScrollY + ")");
-        }
-
-        final ScaleGestureDetector detector =
-            mZoomManager.getMultiTouchGestureDetector();
-
-        // A few apps use WebView but don't instantiate gesture detector.
-        // We don't need to support multi touch for them.
-        if (detector == null) return;
-
-        float x = ev.getX();
-        float y = ev.getY();
-
-        if (mPreventDefault != PREVENT_DEFAULT_YES) {
-            detector.onTouchEvent(ev);
-
-            if (detector.isInProgress()) {
-                if (DebugFlags.WEB_VIEW) {
-                    Log.v(LOGTAG, "detector is in progress");
-                }
-                mLastTouchTime = ev.getEventTime();
-                x = detector.getFocusX();
-                y = detector.getFocusY();
-
-                cancelLongPress();
-                mPrivateHandler.removeMessages(SWITCH_TO_LONGPRESS);
-                if (!mZoomManager.supportsPanDuringZoom()) {
-                    return;
-                }
-                mTouchMode = TOUCH_DRAG_MODE;
-                if (mVelocityTracker == null) {
-                    mVelocityTracker = VelocityTracker.obtain();
-                }
-            }
-        }
-
-        int action = ev.getActionMasked();
-        if (action == MotionEvent.ACTION_POINTER_DOWN) {
-            cancelTouch();
-            action = MotionEvent.ACTION_DOWN;
-        } else if (action == MotionEvent.ACTION_POINTER_UP && ev.getPointerCount() >= 2) {
-            // set mLastTouchX/Y to the remaining points for multi-touch.
-            mLastTouchX = Math.round(x);
-            mLastTouchY = Math.round(y);
-        } else if (action == MotionEvent.ACTION_MOVE) {
-            // negative x or y indicate it is on the edge, skip it.
-            if (x < 0 || y < 0) {
-                return;
-            }
-        }
-
-        handleTouchEventCommon(ev, action, Math.round(x), Math.round(y));
-    }
-
-    private void cancelWebCoreTouchEvent(int x, int y, boolean removeEvents) {
-        if (shouldForwardTouchEvent()) {
-            if (removeEvents) {
-                mWebViewCore.removeMessages(EventHub.TOUCH_EVENT);
-            }
-            TouchEventData ted = new TouchEventData();
-            ted.mIds = new int[1];
-            ted.mIds[0] = 0;
-            ted.mPoints = new Point[1];
-            ted.mPoints[0] = new Point(x, y);
-            ted.mPointsInView = new Point[1];
-            int viewX = contentToViewX(x) - mScrollX;
-            int viewY = contentToViewY(y) - mScrollY;
-            ted.mPointsInView[0] = new Point(viewX, viewY);
-            ted.mAction = MotionEvent.ACTION_CANCEL;
-            ted.mNativeLayer = nativeScrollableLayer(
-                    x, y, ted.mNativeLayerRect, null);
-            ted.mSequence = mTouchEventQueue.nextTouchSequence();
-            mWebViewCore.sendMessage(EventHub.TOUCH_EVENT, ted);
-            mPreventDefault = PREVENT_DEFAULT_IGNORE;
-
-            if (removeEvents) {
-                // Mark this after sending the message above; we should
-                // be willing to ignore the cancel event that we just sent.
-                mTouchEventQueue.ignoreCurrentlyMissingEvents();
-            }
-        }
-    }
-
-    private void startTouch(float x, float y, long eventTime) {
-        // Remember where the motion event started
-        mStartTouchX = mLastTouchX = Math.round(x);
-        mStartTouchY = mLastTouchY = Math.round(y);
-        mLastTouchTime = eventTime;
-        mVelocityTracker = VelocityTracker.obtain();
-        mSnapScrollMode = SNAP_NONE;
-        mPrivateHandler.sendEmptyMessageDelayed(UPDATE_SELECTION,
-                ViewConfiguration.getTapTimeout());
-    }
-
-    private void startDrag() {
-        WebViewCore.reducePriority();
-        // to get better performance, pause updating the picture
-        WebViewCore.pauseUpdatePicture(mWebViewCore);
-        nativeSetIsScrolling(true);
-
-        if (!mDragFromTextInput) {
-            nativeHideCursor();
-        }
-
-        if (mHorizontalScrollBarMode != SCROLLBAR_ALWAYSOFF
-                || mVerticalScrollBarMode != SCROLLBAR_ALWAYSOFF) {
-            mZoomManager.invokeZoomPicker();
-        }
-    }
-
-    private void doDrag(int deltaX, int deltaY) {
-        if ((deltaX | deltaY) != 0) {
-            int oldX = mScrollX;
-            int oldY = mScrollY;
-            int rangeX = computeMaxScrollX();
-            int rangeY = computeMaxScrollY();
-            // Check for the original scrolling layer in case we change
-            // directions.  mTouchMode might be TOUCH_DRAG_MODE if we have
-            // reached the edge of a layer but mScrollingLayer will be non-zero
-            // if we initiated the drag on a layer.
-            if (mCurrentScrollingLayerId != 0) {
-                final int contentX = viewToContentDimension(deltaX);
-                final int contentY = viewToContentDimension(deltaY);
-
-                // Check the scrolling bounds to see if we will actually do any
-                // scrolling.  The rectangle is in document coordinates.
-                final int maxX = mScrollingLayerRect.right;
-                final int maxY = mScrollingLayerRect.bottom;
-                final int resultX = Math.max(0,
-                        Math.min(mScrollingLayerRect.left + contentX, maxX));
-                final int resultY = Math.max(0,
-                        Math.min(mScrollingLayerRect.top + contentY, maxY));
-
-                if (resultX != mScrollingLayerRect.left ||
-                        resultY != mScrollingLayerRect.top) {
-                    // In case we switched to dragging the page.
-                    mTouchMode = TOUCH_DRAG_LAYER_MODE;
-                    deltaX = contentX;
-                    deltaY = contentY;
-                    oldX = mScrollingLayerRect.left;
-                    oldY = mScrollingLayerRect.top;
-                    rangeX = maxX;
-                    rangeY = maxY;
-                } else {
-                    // Scroll the main page if we are not going to scroll the
-                    // layer.  This does not reset mScrollingLayer in case the
-                    // user changes directions and the layer can scroll the
-                    // other way.
-                    mTouchMode = TOUCH_DRAG_MODE;
-                }
-            }
-
-            if (mOverScrollGlow != null) {
-                mOverScrollGlow.setOverScrollDeltas(deltaX, deltaY);
-            }
-
-            overScrollBy(deltaX, deltaY, oldX, oldY,
-                    rangeX, rangeY,
-                    mOverscrollDistance, mOverscrollDistance, true);
-            if (mOverScrollGlow != null && mOverScrollGlow.isAnimating()) {
-                invalidate();
-            }
-        }
-        mZoomManager.keepZoomPickerVisible();
-    }
-
-    private void stopTouch() {
-        if (mScroller.isFinished() && !mSelectingText
-                && (mTouchMode == TOUCH_DRAG_MODE || mTouchMode == TOUCH_DRAG_LAYER_MODE)) {
-            WebViewCore.resumePriority();
-            WebViewCore.resumeUpdatePicture(mWebViewCore);
-            nativeSetIsScrolling(false);
-        }
-
-        // we also use mVelocityTracker == null to tell us that we are
-        // not "moving around", so we can take the slower/prettier
-        // mode in the drawing code
-        if (mVelocityTracker != null) {
-            mVelocityTracker.recycle();
-            mVelocityTracker = null;
-        }
-
-        // Release any pulled glows
-        if (mOverScrollGlow != null) {
-            mOverScrollGlow.releaseAll();
-        }
-
-        if (mSelectingText) {
-            mSelectionStarted = false;
-            syncSelectionCursors();
-            if (mIsCaretSelection) {
-                resetCaretTimer();
-                showPasteWindow();
-            }
-            invalidate();
-        }
-    }
-
-    private void cancelTouch() {
-        // we also use mVelocityTracker == null to tell us that we are
-        // not "moving around", so we can take the slower/prettier
-        // mode in the drawing code
-        if (mVelocityTracker != null) {
-            mVelocityTracker.recycle();
-            mVelocityTracker = null;
-        }
-
-        if ((mTouchMode == TOUCH_DRAG_MODE
-                || mTouchMode == TOUCH_DRAG_LAYER_MODE) && !mSelectingText) {
-            WebViewCore.resumePriority();
-            WebViewCore.resumeUpdatePicture(mWebViewCore);
-            nativeSetIsScrolling(false);
-        }
-        mPrivateHandler.removeMessages(SWITCH_TO_SHORTPRESS);
-        mPrivateHandler.removeMessages(SWITCH_TO_LONGPRESS);
-        mPrivateHandler.removeMessages(DRAG_HELD_MOTIONLESS);
-        mPrivateHandler.removeMessages(AWAKEN_SCROLL_BARS);
-        if (sDisableNavcache) {
-            removeTouchHighlight();
-        }
-        mHeldMotionless = MOTIONLESS_TRUE;
-        mTouchMode = TOUCH_DONE_MODE;
-        nativeHideCursor();
-    }
-
-    @Override
-    public boolean onGenericMotionEvent(MotionEvent event) {
-        if ((event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0) {
-            switch (event.getAction()) {
-                case MotionEvent.ACTION_SCROLL: {
-                    final float vscroll;
-                    final float hscroll;
-                    if ((event.getMetaState() & KeyEvent.META_SHIFT_ON) != 0) {
-                        vscroll = 0;
-                        hscroll = event.getAxisValue(MotionEvent.AXIS_VSCROLL);
-                    } else {
-                        vscroll = -event.getAxisValue(MotionEvent.AXIS_VSCROLL);
-                        hscroll = event.getAxisValue(MotionEvent.AXIS_HSCROLL);
-                    }
-                    if (hscroll != 0 || vscroll != 0) {
-                        final int vdelta = (int) (vscroll * getVerticalScrollFactor());
-                        final int hdelta = (int) (hscroll * getHorizontalScrollFactor());
-                        if (pinScrollBy(hdelta, vdelta, false, 0)) {
-                            return true;
-                        }
-                    }
-                }
-            }
-        }
-        return super.onGenericMotionEvent(event);
-    }
-
-    private long mTrackballFirstTime = 0;
-    private long mTrackballLastTime = 0;
-    private float mTrackballRemainsX = 0.0f;
-    private float mTrackballRemainsY = 0.0f;
-    private int mTrackballXMove = 0;
-    private int mTrackballYMove = 0;
-    private boolean mSelectingText = false;
-    private boolean mSelectionStarted = false;
-    private static final int TRACKBALL_KEY_TIMEOUT = 1000;
-    private static final int TRACKBALL_TIMEOUT = 200;
-    private static final int TRACKBALL_WAIT = 100;
-    private static final int TRACKBALL_SCALE = 400;
-    private static final int TRACKBALL_SCROLL_COUNT = 5;
-    private static final int TRACKBALL_MOVE_COUNT = 10;
-    private static final int TRACKBALL_MULTIPLIER = 3;
-    private static final int SELECT_CURSOR_OFFSET = 16;
-    private static final int SELECT_SCROLL = 5;
-    private int mSelectX = 0;
-    private int mSelectY = 0;
-    private boolean mFocusSizeChanged = false;
-    private boolean mTrackballDown = false;
-    private long mTrackballUpTime = 0;
-    private long mLastCursorTime = 0;
-    private Rect mLastCursorBounds;
-
-    // Set by default; BrowserActivity clears to interpret trackball data
-    // directly for movement. Currently, the framework only passes
-    // arrow key events, not trackball events, from one child to the next
-    private boolean mMapTrackballToArrowKeys = true;
-
-    private DrawData mDelaySetPicture;
-    private DrawData mLoadedPicture;
-
     public void setMapTrackballToArrowKeys(boolean setMap) {
         checkThread();
-        mMapTrackballToArrowKeys = setMap;
+        mProvider.setMapTrackballToArrowKeys(setMap);
     }
 
-    void resetTrackballTime() {
-        mTrackballLastTime = 0;
-    }
-
-    @Override
-    public boolean onTrackballEvent(MotionEvent ev) {
-        long time = ev.getEventTime();
-        if ((ev.getMetaState() & KeyEvent.META_ALT_ON) != 0) {
-            if (ev.getY() > 0) pageDown(true);
-            if (ev.getY() < 0) pageUp(true);
-            return true;
-        }
-        if (ev.getAction() == MotionEvent.ACTION_DOWN) {
-            if (mSelectingText) {
-                return true; // discard press if copy in progress
-            }
-            mTrackballDown = true;
-            if (mNativeClass == 0) {
-                return false;
-            }
-            if (time - mLastCursorTime <= TRACKBALL_TIMEOUT
-                    && !mLastCursorBounds.equals(cursorRingBounds())) {
-                nativeSelectBestAt(mLastCursorBounds);
-            }
-            if (DebugFlags.WEB_VIEW) {
-                Log.v(LOGTAG, "onTrackballEvent down ev=" + ev
-                        + " time=" + time
-                        + " mLastCursorTime=" + mLastCursorTime);
-            }
-            if (isInTouchMode()) requestFocusFromTouch();
-            return false; // let common code in onKeyDown at it
-        }
-        if (ev.getAction() == MotionEvent.ACTION_UP) {
-            // LONG_PRESS_CENTER is set in common onKeyDown
-            mPrivateHandler.removeMessages(LONG_PRESS_CENTER);
-            mTrackballDown = false;
-            mTrackballUpTime = time;
-            if (mSelectingText) {
-                copySelection();
-                selectionDone();
-                return true; // discard press if copy in progress
-            }
-            if (DebugFlags.WEB_VIEW) {
-                Log.v(LOGTAG, "onTrackballEvent up ev=" + ev
-                        + " time=" + time
-                );
-            }
-            return false; // let common code in onKeyUp at it
-        }
-        if ((mMapTrackballToArrowKeys && (ev.getMetaState() & KeyEvent.META_SHIFT_ON) == 0) ||
-                AccessibilityManager.getInstance(mContext).isEnabled()) {
-            if (DebugFlags.WEB_VIEW) Log.v(LOGTAG, "onTrackballEvent gmail quit");
-            return false;
-        }
-        if (mTrackballDown) {
-            if (DebugFlags.WEB_VIEW) Log.v(LOGTAG, "onTrackballEvent down quit");
-            return true; // discard move if trackball is down
-        }
-        if (time - mTrackballUpTime < TRACKBALL_TIMEOUT) {
-            if (DebugFlags.WEB_VIEW) Log.v(LOGTAG, "onTrackballEvent up timeout quit");
-            return true;
-        }
-        // TODO: alternatively we can do panning as touch does
-        switchOutDrawHistory();
-        if (time - mTrackballLastTime > TRACKBALL_TIMEOUT) {
-            if (DebugFlags.WEB_VIEW) {
-                Log.v(LOGTAG, "onTrackballEvent time="
-                        + time + " last=" + mTrackballLastTime);
-            }
-            mTrackballFirstTime = time;
-            mTrackballXMove = mTrackballYMove = 0;
-        }
-        mTrackballLastTime = time;
-        if (DebugFlags.WEB_VIEW) {
-            Log.v(LOGTAG, "onTrackballEvent ev=" + ev + " time=" + time);
-        }
-        mTrackballRemainsX += ev.getX();
-        mTrackballRemainsY += ev.getY();
-        doTrackball(time, ev.getMetaState());
-        return true;
-    }
-
-    private int scaleTrackballX(float xRate, int width) {
-        int xMove = (int) (xRate / TRACKBALL_SCALE * width);
-        int nextXMove = xMove;
-        if (xMove > 0) {
-            if (xMove > mTrackballXMove) {
-                xMove -= mTrackballXMove;
-            }
-        } else if (xMove < mTrackballXMove) {
-            xMove -= mTrackballXMove;
-        }
-        mTrackballXMove = nextXMove;
-        return xMove;
-    }
-
-    private int scaleTrackballY(float yRate, int height) {
-        int yMove = (int) (yRate / TRACKBALL_SCALE * height);
-        int nextYMove = yMove;
-        if (yMove > 0) {
-            if (yMove > mTrackballYMove) {
-                yMove -= mTrackballYMove;
-            }
-        } else if (yMove < mTrackballYMove) {
-            yMove -= mTrackballYMove;
-        }
-        mTrackballYMove = nextYMove;
-        return yMove;
-    }
-
-    private int keyCodeToSoundsEffect(int keyCode) {
-        switch(keyCode) {
-            case KeyEvent.KEYCODE_DPAD_UP:
-                return SoundEffectConstants.NAVIGATION_UP;
-            case KeyEvent.KEYCODE_DPAD_RIGHT:
-                return SoundEffectConstants.NAVIGATION_RIGHT;
-            case KeyEvent.KEYCODE_DPAD_DOWN:
-                return SoundEffectConstants.NAVIGATION_DOWN;
-            case KeyEvent.KEYCODE_DPAD_LEFT:
-                return SoundEffectConstants.NAVIGATION_LEFT;
-        }
-        throw new IllegalArgumentException("keyCode must be one of " +
-                "{KEYCODE_DPAD_UP, KEYCODE_DPAD_RIGHT, KEYCODE_DPAD_DOWN, " +
-                "KEYCODE_DPAD_LEFT}.");
-    }
-
-    private void doTrackball(long time, int metaState) {
-        int elapsed = (int) (mTrackballLastTime - mTrackballFirstTime);
-        if (elapsed == 0) {
-            elapsed = TRACKBALL_TIMEOUT;
-        }
-        float xRate = mTrackballRemainsX * 1000 / elapsed;
-        float yRate = mTrackballRemainsY * 1000 / elapsed;
-        int viewWidth = getViewWidth();
-        int viewHeight = getViewHeight();
-        float ax = Math.abs(xRate);
-        float ay = Math.abs(yRate);
-        float maxA = Math.max(ax, ay);
-        if (DebugFlags.WEB_VIEW) {
-            Log.v(LOGTAG, "doTrackball elapsed=" + elapsed
-                    + " xRate=" + xRate
-                    + " yRate=" + yRate
-                    + " mTrackballRemainsX=" + mTrackballRemainsX
-                    + " mTrackballRemainsY=" + mTrackballRemainsY);
-        }
-        int width = mContentWidth - viewWidth;
-        int height = mContentHeight - viewHeight;
-        if (width < 0) width = 0;
-        if (height < 0) height = 0;
-        ax = Math.abs(mTrackballRemainsX * TRACKBALL_MULTIPLIER);
-        ay = Math.abs(mTrackballRemainsY * TRACKBALL_MULTIPLIER);
-        maxA = Math.max(ax, ay);
-        int count = Math.max(0, (int) maxA);
-        int oldScrollX = mScrollX;
-        int oldScrollY = mScrollY;
-        if (count > 0) {
-            int selectKeyCode = ax < ay ? mTrackballRemainsY < 0 ?
-                    KeyEvent.KEYCODE_DPAD_UP : KeyEvent.KEYCODE_DPAD_DOWN :
-                    mTrackballRemainsX < 0 ? KeyEvent.KEYCODE_DPAD_LEFT :
-                    KeyEvent.KEYCODE_DPAD_RIGHT;
-            count = Math.min(count, TRACKBALL_MOVE_COUNT);
-            if (DebugFlags.WEB_VIEW) {
-                Log.v(LOGTAG, "doTrackball keyCode=" + selectKeyCode
-                        + " count=" + count
-                        + " mTrackballRemainsX=" + mTrackballRemainsX
-                        + " mTrackballRemainsY=" + mTrackballRemainsY);
-            }
-            if (mNativeClass != 0 && nativePageShouldHandleShiftAndArrows()) {
-                for (int i = 0; i < count; i++) {
-                    letPageHandleNavKey(selectKeyCode, time, true, metaState);
-                }
-                letPageHandleNavKey(selectKeyCode, time, false, metaState);
-            } else if (navHandledKey(selectKeyCode, count, false, time)) {
-                playSoundEffect(keyCodeToSoundsEffect(selectKeyCode));
-            }
-            mTrackballRemainsX = mTrackballRemainsY = 0;
-        }
-        if (count >= TRACKBALL_SCROLL_COUNT) {
-            int xMove = scaleTrackballX(xRate, width);
-            int yMove = scaleTrackballY(yRate, height);
-            if (DebugFlags.WEB_VIEW) {
-                Log.v(LOGTAG, "doTrackball pinScrollBy"
-                        + " count=" + count
-                        + " xMove=" + xMove + " yMove=" + yMove
-                        + " mScrollX-oldScrollX=" + (mScrollX-oldScrollX)
-                        + " mScrollY-oldScrollY=" + (mScrollY-oldScrollY)
-                        );
-            }
-            if (Math.abs(mScrollX - oldScrollX) > Math.abs(xMove)) {
-                xMove = 0;
-            }
-            if (Math.abs(mScrollY - oldScrollY) > Math.abs(yMove)) {
-                yMove = 0;
-            }
-            if (xMove != 0 || yMove != 0) {
-                pinScrollBy(xMove, yMove, true, 0);
-            }
-        }
-    }
-
-    /**
-     * Compute the maximum horizontal scroll position. Used by {@link OverScrollGlow}.
-     * @return Maximum horizontal scroll position within real content
-     */
-    int computeMaxScrollX() {
-        return Math.max(computeRealHorizontalScrollRange() - getViewWidth(), 0);
-    }
-
-    /**
-     * Compute the maximum vertical scroll position. Used by {@link OverScrollGlow}.
-     * @return Maximum vertical scroll position within real content
-     */
-    int computeMaxScrollY() {
-        return Math.max(computeRealVerticalScrollRange() + getTitleHeight()
-                - getViewHeightWithTitle(), 0);
-    }
-
-    boolean updateScrollCoordinates(int x, int y) {
-        int oldX = mScrollX;
-        int oldY = mScrollY;
-        mScrollX = x;
-        mScrollY = y;
-        if (oldX != mScrollX || oldY != mScrollY) {
-            onScrollChanged(mScrollX, mScrollY, oldX, oldY);
-            return true;
-        } else {
-            return false;
-        }
-    }
 
     public void flingScroll(int vx, int vy) {
         checkThread();
-        mScroller.fling(mScrollX, mScrollY, vx, vy, 0, computeMaxScrollX(), 0,
-                computeMaxScrollY(), mOverflingDistance, mOverflingDistance);
-        invalidate();
-    }
-
-    private void doFling() {
-        if (mVelocityTracker == null) {
-            return;
-        }
-        int maxX = computeMaxScrollX();
-        int maxY = computeMaxScrollY();
-
-        mVelocityTracker.computeCurrentVelocity(1000, mMaximumFling);
-        int vx = (int) mVelocityTracker.getXVelocity();
-        int vy = (int) mVelocityTracker.getYVelocity();
-
-        int scrollX = mScrollX;
-        int scrollY = mScrollY;
-        int overscrollDistance = mOverscrollDistance;
-        int overflingDistance = mOverflingDistance;
-
-        // Use the layer's scroll data if applicable.
-        if (mTouchMode == TOUCH_DRAG_LAYER_MODE) {
-            scrollX = mScrollingLayerRect.left;
-            scrollY = mScrollingLayerRect.top;
-            maxX = mScrollingLayerRect.right;
-            maxY = mScrollingLayerRect.bottom;
-            // No overscrolling for layers.
-            overscrollDistance = overflingDistance = 0;
-        }
-
-        if (mSnapScrollMode != SNAP_NONE) {
-            if ((mSnapScrollMode & SNAP_X) == SNAP_X) {
-                vy = 0;
-            } else {
-                vx = 0;
-            }
-        }
-        if ((maxX == 0 && vy == 0) || (maxY == 0 && vx == 0)) {
-            WebViewCore.resumePriority();
-            if (!mSelectingText) {
-                WebViewCore.resumeUpdatePicture(mWebViewCore);
-            }
-            if (mScroller.springBack(scrollX, scrollY, 0, maxX, 0, maxY)) {
-                invalidate();
-            }
-            return;
-        }
-        float currentVelocity = mScroller.getCurrVelocity();
-        float velocity = (float) Math.hypot(vx, vy);
-        if (mLastVelocity > 0 && currentVelocity > 0 && velocity
-                > mLastVelocity * MINIMUM_VELOCITY_RATIO_FOR_ACCELERATION) {
-            float deltaR = (float) (Math.abs(Math.atan2(mLastVelY, mLastVelX)
-                    - Math.atan2(vy, vx)));
-            final float circle = (float) (Math.PI) * 2.0f;
-            if (deltaR > circle * 0.9f || deltaR < circle * 0.1f) {
-                vx += currentVelocity * mLastVelX / mLastVelocity;
-                vy += currentVelocity * mLastVelY / mLastVelocity;
-                velocity = (float) Math.hypot(vx, vy);
-                if (DebugFlags.WEB_VIEW) {
-                    Log.v(LOGTAG, "doFling vx= " + vx + " vy=" + vy);
-                }
-            } else if (DebugFlags.WEB_VIEW) {
-                Log.v(LOGTAG, "doFling missed " + deltaR / circle);
-            }
-        } else if (DebugFlags.WEB_VIEW) {
-            Log.v(LOGTAG, "doFling start last=" + mLastVelocity
-                    + " current=" + currentVelocity
-                    + " vx=" + vx + " vy=" + vy
-                    + " maxX=" + maxX + " maxY=" + maxY
-                    + " scrollX=" + scrollX + " scrollY=" + scrollY
-                    + " layer=" + mCurrentScrollingLayerId);
-        }
-
-        // Allow sloppy flings without overscrolling at the edges.
-        if ((scrollX == 0 || scrollX == maxX) && Math.abs(vx) < Math.abs(vy)) {
-            vx = 0;
-        }
-        if ((scrollY == 0 || scrollY == maxY) && Math.abs(vy) < Math.abs(vx)) {
-            vy = 0;
-        }
-
-        if (overscrollDistance < overflingDistance) {
-            if ((vx > 0 && scrollX == -overscrollDistance) ||
-                    (vx < 0 && scrollX == maxX + overscrollDistance)) {
-                vx = 0;
-            }
-            if ((vy > 0 && scrollY == -overscrollDistance) ||
-                    (vy < 0 && scrollY == maxY + overscrollDistance)) {
-                vy = 0;
-            }
-        }
-
-        mLastVelX = vx;
-        mLastVelY = vy;
-        mLastVelocity = velocity;
-
-        // no horizontal overscroll if the content just fits
-        mScroller.fling(scrollX, scrollY, -vx, -vy, 0, maxX, 0, maxY,
-                maxX == 0 ? 0 : overflingDistance, overflingDistance);
-        // Duration is calculated based on velocity. With range boundaries and overscroll
-        // we may not know how long the final animation will take. (Hence the deprecation
-        // warning on the call below.) It's not a big deal for scroll bars but if webcore
-        // resumes during this effect we will take a performance hit. See computeScroll;
-        // we resume webcore there when the animation is finished.
-        final int time = mScroller.getDuration();
-
-        // Suppress scrollbars for layer scrolling.
-        if (mTouchMode != TOUCH_DRAG_LAYER_MODE) {
-            awakenScrollBars(time);
-        }
-
-        invalidate();
+        mProvider.flingScroll(vx, vy);
     }
 
     /**
@@ -7921,27 +1491,7 @@
     @Deprecated
     public View getZoomControls() {
         checkThread();
-        if (!getSettings().supportZoom()) {
-            Log.w(LOGTAG, "This WebView doesn't support zoom.");
-            return null;
-        }
-        return mZoomManager.getExternalZoomPicker();
-    }
-
-    void dismissZoomControl() {
-        mZoomManager.dismissZoomPicker();
-    }
-
-    float getDefaultZoomScale() {
-        return mZoomManager.getDefaultScale();
-    }
-
-    /**
-     * Return the overview scale of the WebView
-     * @return The overview scale.
-     */
-    float getZoomOverviewScale() {
-        return mZoomManager.getZoomOverviewScale();
+        return mProvider.getZoomControls();
     }
 
     /**
@@ -7949,7 +1499,7 @@
      */
     public boolean canZoomIn() {
         checkThread();
-        return mZoomManager.canZoomIn();
+        return mProvider.canZoomIn();
     }
 
     /**
@@ -7957,7 +1507,7 @@
      */
     public boolean canZoomOut() {
         checkThread();
-        return mZoomManager.canZoomOut();
+        return mProvider.canZoomOut();
     }
 
     /**
@@ -7966,7 +1516,7 @@
      */
     public boolean zoomIn() {
         checkThread();
-        return mZoomManager.zoomIn();
+        return mProvider.zoomIn();
     }
 
     /**
@@ -7975,2262 +1525,7 @@
      */
     public boolean zoomOut() {
         checkThread();
-        return mZoomManager.zoomOut();
-    }
-
-    /**
-     * This selects the best clickable target at mLastTouchX and mLastTouchY
-     * and calls showCursorTimed on the native side
-     */
-    private void updateSelection() {
-        if (mNativeClass == 0 || sDisableNavcache) {
-            return;
-        }
-        mPrivateHandler.removeMessages(UPDATE_SELECTION);
-        // mLastTouchX and mLastTouchY are the point in the current viewport
-        int contentX = viewToContentX(mLastTouchX + mScrollX);
-        int contentY = viewToContentY(mLastTouchY + mScrollY);
-        int slop = viewToContentDimension(mNavSlop);
-        Rect rect = new Rect(contentX - slop, contentY - slop,
-                contentX + slop, contentY + slop);
-        nativeSelectBestAt(rect);
-        mInitialHitTestResult = hitTestResult(null);
-    }
-
-    /**
-     * Scroll the focused text field to match the WebTextView
-     * @param xPercent New x position of the WebTextView from 0 to 1.
-     */
-    /*package*/ void scrollFocusedTextInputX(float xPercent) {
-        if (!inEditingMode() || mWebViewCore == null) {
-            return;
-        }
-        mWebViewCore.sendMessage(EventHub.SCROLL_TEXT_INPUT, 0,
-                new Float(xPercent));
-    }
-
-    /**
-     * Scroll the focused textarea vertically to match the WebTextView
-     * @param y New y position of the WebTextView in view coordinates
-     */
-    /* package */ void scrollFocusedTextInputY(int y) {
-        if (!inEditingMode() || mWebViewCore == null) {
-            return;
-        }
-        mWebViewCore.sendMessage(EventHub.SCROLL_TEXT_INPUT, 0, viewToContentDimension(y));
-    }
-
-    /**
-     * Set our starting point and time for a drag from the WebTextView.
-     */
-    /*package*/ void initiateTextFieldDrag(float x, float y, long eventTime) {
-        if (!inEditingMode()) {
-            return;
-        }
-        mLastTouchX = Math.round(x + mWebTextView.getLeft() - mScrollX);
-        mLastTouchY = Math.round(y + mWebTextView.getTop() - mScrollY);
-        mLastTouchTime = eventTime;
-        if (!mScroller.isFinished()) {
-            abortAnimation();
-        }
-        mSnapScrollMode = SNAP_NONE;
-        mVelocityTracker = VelocityTracker.obtain();
-        mTouchMode = TOUCH_DRAG_START_MODE;
-    }
-
-    /**
-     * Given a motion event from the WebTextView, set its location to our
-     * coordinates, and handle the event.
-     */
-    /*package*/ boolean textFieldDrag(MotionEvent event) {
-        if (!inEditingMode()) {
-            return false;
-        }
-        mDragFromTextInput = true;
-        event.offsetLocation((mWebTextView.getLeft() - mScrollX),
-                (mWebTextView.getTop() - mScrollY));
-        boolean result = onTouchEvent(event);
-        mDragFromTextInput = false;
-        return result;
-    }
-
-    /**
-     * Due a touch up from a WebTextView.  This will be handled by webkit to
-     * change the selection.
-     * @param event MotionEvent in the WebTextView's coordinates.
-     */
-    /*package*/ void touchUpOnTextField(MotionEvent event) {
-        if (!inEditingMode()) {
-            return;
-        }
-        int x = viewToContentX((int) event.getX() + mWebTextView.getLeft());
-        int y = viewToContentY((int) event.getY() + mWebTextView.getTop());
-        int slop = viewToContentDimension(mNavSlop);
-        nativeMotionUp(x, y, slop);
-    }
-
-    /**
-     * Called when pressing the center key or trackball on a textfield.
-     */
-    /*package*/ void centerKeyPressOnTextField() {
-        mWebViewCore.sendMessage(EventHub.CLICK, nativeCursorFramePointer(),
-                    nativeCursorNodePointer());
-    }
-
-    private void doShortPress() {
-        if (mNativeClass == 0) {
-            return;
-        }
-        if (mPreventDefault == PREVENT_DEFAULT_YES) {
-            return;
-        }
-        mTouchMode = TOUCH_DONE_MODE;
-        updateSelection();
-        switchOutDrawHistory();
-        // mLastTouchX and mLastTouchY are the point in the current viewport
-        int contentX = viewToContentX(mLastTouchX + mScrollX);
-        int contentY = viewToContentY(mLastTouchY + mScrollY);
-        int slop = viewToContentDimension(mNavSlop);
-        if (sDisableNavcache && !mTouchHighlightRegion.isEmpty()) {
-            // set mTouchHighlightRequested to 0 to cause an immediate
-            // drawing of the touch rings
-            mTouchHighlightRequested = 0;
-            invalidate(mTouchHighlightRegion.getBounds());
-            mPrivateHandler.postDelayed(new Runnable() {
-                @Override
-                public void run() {
-                    removeTouchHighlight();
-                }
-            }, ViewConfiguration.getPressedStateDuration());
-        }
-        if (mFocusedNode != null && mFocusedNode.mIntentUrl != null) {
-            playSoundEffect(SoundEffectConstants.CLICK);
-            overrideLoading(mFocusedNode.mIntentUrl);
-        } else if (sDisableNavcache) {
-            WebViewCore.TouchUpData touchUpData = new WebViewCore.TouchUpData();
-            // use "0" as generation id to inform WebKit to use the same x/y as
-            // it used when processing GET_TOUCH_HIGHLIGHT_RECTS
-            touchUpData.mMoveGeneration = 0;
-            mWebViewCore.sendMessage(EventHub.TOUCH_UP, touchUpData);
-        } else if (nativePointInNavCache(contentX, contentY, slop)) {
-            WebViewCore.MotionUpData motionUpData = new WebViewCore
-                    .MotionUpData();
-            motionUpData.mFrame = nativeCacheHitFramePointer();
-            motionUpData.mNode = nativeCacheHitNodePointer();
-            motionUpData.mBounds = nativeCacheHitNodeBounds();
-            motionUpData.mX = contentX;
-            motionUpData.mY = contentY;
-            mWebViewCore.sendMessageAtFrontOfQueue(EventHub.VALID_NODE_BOUNDS,
-                    motionUpData);
-        } else {
-            doMotionUp(contentX, contentY);
-        }
-    }
-
-    private void doMotionUp(int contentX, int contentY) {
-        int slop = viewToContentDimension(mNavSlop);
-        if (nativeMotionUp(contentX, contentY, slop) && mLogEvent) {
-            EventLog.writeEvent(EventLogTags.BROWSER_SNAP_CENTER);
-        }
-        if (nativeHasCursorNode() && !nativeCursorIsTextInput()) {
-            playSoundEffect(SoundEffectConstants.CLICK);
-        }
-    }
-
-    void sendPluginDrawMsg() {
-        mWebViewCore.sendMessage(EventHub.PLUGIN_SURFACE_READY);
-    }
-
-    /**
-     * Returns plugin bounds if x/y in content coordinates corresponds to a
-     * plugin. Otherwise a NULL rectangle is returned.
-     */
-    Rect getPluginBounds(int x, int y) {
-        int slop = viewToContentDimension(mNavSlop);
-        if (nativePointInNavCache(x, y, slop) && nativeCacheHitIsPlugin()) {
-            return nativeCacheHitNodeBounds();
-        } else {
-            return null;
-        }
-    }
-
-    /*
-     * Return true if the rect (e.g. plugin) is fully visible and maximized
-     * inside the WebView.
-     */
-    boolean isRectFitOnScreen(Rect rect) {
-        final int rectWidth = rect.width();
-        final int rectHeight = rect.height();
-        final int viewWidth = getViewWidth();
-        final int viewHeight = getViewHeightWithTitle();
-        float scale = Math.min((float) viewWidth / rectWidth, (float) viewHeight / rectHeight);
-        scale = mZoomManager.computeScaleWithLimits(scale);
-        return !mZoomManager.willScaleTriggerZoom(scale)
-                && contentToViewX(rect.left) >= mScrollX
-                && contentToViewX(rect.right) <= mScrollX + viewWidth
-                && contentToViewY(rect.top) >= mScrollY
-                && contentToViewY(rect.bottom) <= mScrollY + viewHeight;
-    }
-
-    /*
-     * Maximize and center the rectangle, specified in the document coordinate
-     * space, inside the WebView. If the zoom doesn't need to be changed, do an
-     * animated scroll to center it. If the zoom needs to be changed, find the
-     * zoom center and do a smooth zoom transition. The rect is in document
-     * coordinates
-     */
-    void centerFitRect(Rect rect) {
-        final int rectWidth = rect.width();
-        final int rectHeight = rect.height();
-        final int viewWidth = getViewWidth();
-        final int viewHeight = getViewHeightWithTitle();
-        float scale = Math.min((float) viewWidth / rectWidth, (float) viewHeight
-                / rectHeight);
-        scale = mZoomManager.computeScaleWithLimits(scale);
-        if (!mZoomManager.willScaleTriggerZoom(scale)) {
-            pinScrollTo(contentToViewX(rect.left + rectWidth / 2) - viewWidth / 2,
-                    contentToViewY(rect.top + rectHeight / 2) - viewHeight / 2,
-                    true, 0);
-        } else {
-            float actualScale = mZoomManager.getScale();
-            float oldScreenX = rect.left * actualScale - mScrollX;
-            float rectViewX = rect.left * scale;
-            float rectViewWidth = rectWidth * scale;
-            float newMaxWidth = mContentWidth * scale;
-            float newScreenX = (viewWidth - rectViewWidth) / 2;
-            // pin the newX to the WebView
-            if (newScreenX > rectViewX) {
-                newScreenX = rectViewX;
-            } else if (newScreenX > (newMaxWidth - rectViewX - rectViewWidth)) {
-                newScreenX = viewWidth - (newMaxWidth - rectViewX);
-            }
-            float zoomCenterX = (oldScreenX * scale - newScreenX * actualScale)
-                    / (scale - actualScale);
-            float oldScreenY = rect.top * actualScale + getTitleHeight()
-                    - mScrollY;
-            float rectViewY = rect.top * scale + getTitleHeight();
-            float rectViewHeight = rectHeight * scale;
-            float newMaxHeight = mContentHeight * scale + getTitleHeight();
-            float newScreenY = (viewHeight - rectViewHeight) / 2;
-            // pin the newY to the WebView
-            if (newScreenY > rectViewY) {
-                newScreenY = rectViewY;
-            } else if (newScreenY > (newMaxHeight - rectViewY - rectViewHeight)) {
-                newScreenY = viewHeight - (newMaxHeight - rectViewY);
-            }
-            float zoomCenterY = (oldScreenY * scale - newScreenY * actualScale)
-                    / (scale - actualScale);
-            mZoomManager.setZoomCenter(zoomCenterX, zoomCenterY);
-            mZoomManager.startZoomAnimation(scale, false);
-        }
-    }
-
-    // Called by JNI to handle a touch on a node representing an email address,
-    // address, or phone number
-    private void overrideLoading(String url) {
-        mCallbackProxy.uiOverrideUrlLoading(url);
-    }
-
-    @Override
-    public boolean requestFocus(int direction, Rect previouslyFocusedRect) {
-        // FIXME: If a subwindow is showing find, and the user touches the
-        // background window, it can steal focus.
-        if (mFindIsUp) return false;
-        boolean result = false;
-        if (inEditingMode()) {
-            result = mWebTextView.requestFocus(direction,
-                    previouslyFocusedRect);
-        } else {
-            result = super.requestFocus(direction, previouslyFocusedRect);
-            if (mWebViewCore.getSettings().getNeedInitialFocus() && !isInTouchMode()) {
-                // For cases such as GMail, where we gain focus from a direction,
-                // we want to move to the first available link.
-                // FIXME: If there are no visible links, we may not want to
-                int fakeKeyDirection = 0;
-                switch(direction) {
-                    case View.FOCUS_UP:
-                        fakeKeyDirection = KeyEvent.KEYCODE_DPAD_UP;
-                        break;
-                    case View.FOCUS_DOWN:
-                        fakeKeyDirection = KeyEvent.KEYCODE_DPAD_DOWN;
-                        break;
-                    case View.FOCUS_LEFT:
-                        fakeKeyDirection = KeyEvent.KEYCODE_DPAD_LEFT;
-                        break;
-                    case View.FOCUS_RIGHT:
-                        fakeKeyDirection = KeyEvent.KEYCODE_DPAD_RIGHT;
-                        break;
-                    default:
-                        return result;
-                }
-                if (mNativeClass != 0 && !nativeHasCursorNode()) {
-                    navHandledKey(fakeKeyDirection, 1, true, 0);
-                }
-            }
-        }
-        return result;
-    }
-
-    @Override
-    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
-        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
-
-        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
-        int heightSize = MeasureSpec.getSize(heightMeasureSpec);
-        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
-        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
-
-        int measuredHeight = heightSize;
-        int measuredWidth = widthSize;
-
-        // Grab the content size from WebViewCore.
-        int contentHeight = contentToViewDimension(mContentHeight);
-        int contentWidth = contentToViewDimension(mContentWidth);
-
-//        Log.d(LOGTAG, "------- measure " + heightMode);
-
-        if (heightMode != MeasureSpec.EXACTLY) {
-            mHeightCanMeasure = true;
-            measuredHeight = contentHeight;
-            if (heightMode == MeasureSpec.AT_MOST) {
-                // If we are larger than the AT_MOST height, then our height can
-                // no longer be measured and we should scroll internally.
-                if (measuredHeight > heightSize) {
-                    measuredHeight = heightSize;
-                    mHeightCanMeasure = false;
-                    measuredHeight |= MEASURED_STATE_TOO_SMALL;
-                }
-            }
-        } else {
-            mHeightCanMeasure = false;
-        }
-        if (mNativeClass != 0) {
-            nativeSetHeightCanMeasure(mHeightCanMeasure);
-        }
-        // For the width, always use the given size unless unspecified.
-        if (widthMode == MeasureSpec.UNSPECIFIED) {
-            mWidthCanMeasure = true;
-            measuredWidth = contentWidth;
-        } else {
-            if (measuredWidth < contentWidth) {
-                measuredWidth |= MEASURED_STATE_TOO_SMALL;
-            }
-            mWidthCanMeasure = false;
-        }
-
-        synchronized (this) {
-            setMeasuredDimension(measuredWidth, measuredHeight);
-        }
-    }
-
-    @Override
-    public boolean requestChildRectangleOnScreen(View child,
-                                                 Rect rect,
-                                                 boolean immediate) {
-        if (mNativeClass == 0) {
-            return false;
-        }
-        // don't scroll while in zoom animation. When it is done, we will adjust
-        // the necessary components (e.g., WebTextView if it is in editing mode)
-        if (mZoomManager.isFixedLengthAnimationInProgress()) {
-            return false;
-        }
-
-        rect.offset(child.getLeft() - child.getScrollX(),
-                child.getTop() - child.getScrollY());
-
-        Rect content = new Rect(viewToContentX(mScrollX),
-                viewToContentY(mScrollY),
-                viewToContentX(mScrollX + getWidth()
-                - getVerticalScrollbarWidth()),
-                viewToContentY(mScrollY + getViewHeightWithTitle()));
-        content = nativeSubtractLayers(content);
-        int screenTop = contentToViewY(content.top);
-        int screenBottom = contentToViewY(content.bottom);
-        int height = screenBottom - screenTop;
-        int scrollYDelta = 0;
-
-        if (rect.bottom > screenBottom) {
-            int oneThirdOfScreenHeight = height / 3;
-            if (rect.height() > 2 * oneThirdOfScreenHeight) {
-                // If the rectangle is too tall to fit in the bottom two thirds
-                // of the screen, place it at the top.
-                scrollYDelta = rect.top - screenTop;
-            } else {
-                // If the rectangle will still fit on screen, we want its
-                // top to be in the top third of the screen.
-                scrollYDelta = rect.top - (screenTop + oneThirdOfScreenHeight);
-            }
-        } else if (rect.top < screenTop) {
-            scrollYDelta = rect.top - screenTop;
-        }
-
-        int screenLeft = contentToViewX(content.left);
-        int screenRight = contentToViewX(content.right);
-        int width = screenRight - screenLeft;
-        int scrollXDelta = 0;
-
-        if (rect.right > screenRight && rect.left > screenLeft) {
-            if (rect.width() > width) {
-                scrollXDelta += (rect.left - screenLeft);
-            } else {
-                scrollXDelta += (rect.right - screenRight);
-            }
-        } else if (rect.left < screenLeft) {
-            scrollXDelta -= (screenLeft - rect.left);
-        }
-
-        if ((scrollYDelta | scrollXDelta) != 0) {
-            return pinScrollBy(scrollXDelta, scrollYDelta, !immediate, 0);
-        }
-
-        return false;
-    }
-
-    /* package */ void replaceTextfieldText(int oldStart, int oldEnd,
-            String replace, int newStart, int newEnd) {
-        WebViewCore.ReplaceTextData arg = new WebViewCore.ReplaceTextData();
-        arg.mReplace = replace;
-        arg.mNewStart = newStart;
-        arg.mNewEnd = newEnd;
-        mTextGeneration++;
-        arg.mTextGeneration = mTextGeneration;
-        mWebViewCore.sendMessage(EventHub.REPLACE_TEXT, oldStart, oldEnd, arg);
-    }
-
-    /* package */ void passToJavaScript(String currentText, KeyEvent event) {
-        // check if mWebViewCore has been destroyed
-        if (mWebViewCore == null) {
-            return;
-        }
-        WebViewCore.JSKeyData arg = new WebViewCore.JSKeyData();
-        arg.mEvent = event;
-        arg.mCurrentText = currentText;
-        // Increase our text generation number, and pass it to webcore thread
-        mTextGeneration++;
-        mWebViewCore.sendMessage(EventHub.PASS_TO_JS, mTextGeneration, 0, arg);
-        // WebKit's document state is not saved until about to leave the page.
-        // To make sure the host application, like Browser, has the up to date
-        // document state when it goes to background, we force to save the
-        // document state.
-        mWebViewCore.removeMessages(EventHub.SAVE_DOCUMENT_STATE);
-        mWebViewCore.sendMessageDelayed(EventHub.SAVE_DOCUMENT_STATE,
-                cursorData(), 1000);
-    }
-
-    /**
-     * @hide
-     */
-    public synchronized WebViewCore getWebViewCore() {
-        return mWebViewCore;
-    }
-
-    /**
-     * Used only by TouchEventQueue to store pending touch events.
-     */
-    private static class QueuedTouch {
-        long mSequence;
-        MotionEvent mEvent; // Optional
-        TouchEventData mTed; // Optional
-
-        QueuedTouch mNext;
-
-        public QueuedTouch set(TouchEventData ted) {
-            mSequence = ted.mSequence;
-            mTed = ted;
-            mEvent = null;
-            mNext = null;
-            return this;
-        }
-
-        public QueuedTouch set(MotionEvent ev, long sequence) {
-            mEvent = MotionEvent.obtain(ev);
-            mSequence = sequence;
-            mTed = null;
-            mNext = null;
-            return this;
-        }
-
-        public QueuedTouch add(QueuedTouch other) {
-            if (other.mSequence < mSequence) {
-                other.mNext = this;
-                return other;
-            }
-
-            QueuedTouch insertAt = this;
-            while (insertAt.mNext != null && insertAt.mNext.mSequence < other.mSequence) {
-                insertAt = insertAt.mNext;
-            }
-            other.mNext = insertAt.mNext;
-            insertAt.mNext = other;
-            return this;
-        }
-    }
-
-    /**
-     * WebView handles touch events asynchronously since some events must be passed to WebKit
-     * for potentially slower processing. TouchEventQueue serializes touch events regardless
-     * of which path they take to ensure that no events are ever processed out of order
-     * by WebView.
-     */
-    private class TouchEventQueue {
-        private long mNextTouchSequence = Long.MIN_VALUE + 1;
-        private long mLastHandledTouchSequence = Long.MIN_VALUE;
-        private long mIgnoreUntilSequence = Long.MIN_VALUE + 1;
-
-        // Events waiting to be processed.
-        private QueuedTouch mTouchEventQueue;
-
-        // Known events that are waiting on a response before being enqueued.
-        private QueuedTouch mPreQueue;
-
-        // Pool of QueuedTouch objects saved for later use.
-        private QueuedTouch mQueuedTouchRecycleBin;
-        private int mQueuedTouchRecycleCount;
-
-        private long mLastEventTime = Long.MAX_VALUE;
-        private static final int MAX_RECYCLED_QUEUED_TOUCH = 15;
-
-        // milliseconds until we abandon hope of getting all of a previous gesture
-        private static final int QUEUED_GESTURE_TIMEOUT = 1000;
-
-        private QueuedTouch obtainQueuedTouch() {
-            if (mQueuedTouchRecycleBin != null) {
-                QueuedTouch result = mQueuedTouchRecycleBin;
-                mQueuedTouchRecycleBin = result.mNext;
-                mQueuedTouchRecycleCount--;
-                return result;
-            }
-            return new QueuedTouch();
-        }
-
-        /**
-         * Allow events with any currently missing sequence numbers to be skipped in processing.
-         */
-        public void ignoreCurrentlyMissingEvents() {
-            mIgnoreUntilSequence = mNextTouchSequence;
-
-            // Run any events we have available and complete, pre-queued or otherwise.
-            runQueuedAndPreQueuedEvents();
-        }
-
-        private void runQueuedAndPreQueuedEvents() {
-            QueuedTouch qd = mPreQueue;
-            boolean fromPreQueue = true;
-            while (qd != null && qd.mSequence == mLastHandledTouchSequence + 1) {
-                handleQueuedTouch(qd);
-                QueuedTouch recycleMe = qd;
-                if (fromPreQueue) {
-                    mPreQueue = qd.mNext;
-                } else {
-                    mTouchEventQueue = qd.mNext;
-                }
-                recycleQueuedTouch(recycleMe);
-                mLastHandledTouchSequence++;
-
-                long nextPre = mPreQueue != null ? mPreQueue.mSequence : Long.MAX_VALUE;
-                long nextQueued = mTouchEventQueue != null ?
-                        mTouchEventQueue.mSequence : Long.MAX_VALUE;
-                fromPreQueue = nextPre < nextQueued;
-                qd = fromPreQueue ? mPreQueue : mTouchEventQueue;
-            }
-        }
-
-        /**
-         * Add a TouchEventData to the pre-queue.
-         *
-         * An event in the pre-queue is an event that we know about that
-         * has been sent to webkit, but that we haven't received back and
-         * enqueued into the normal touch queue yet. If webkit ever times
-         * out and we need to ignore currently missing events, we'll run
-         * events from the pre-queue to patch the holes.
-         *
-         * @param ted TouchEventData to pre-queue
-         */
-        public void preQueueTouchEventData(TouchEventData ted) {
-            QueuedTouch newTouch = obtainQueuedTouch().set(ted);
-            if (mPreQueue == null) {
-                mPreQueue = newTouch;
-            } else {
-                QueuedTouch insertionPoint = mPreQueue;
-                while (insertionPoint.mNext != null &&
-                        insertionPoint.mNext.mSequence < newTouch.mSequence) {
-                    insertionPoint = insertionPoint.mNext;
-                }
-                newTouch.mNext = insertionPoint.mNext;
-                insertionPoint.mNext = newTouch;
-            }
-        }
-
-        private void recycleQueuedTouch(QueuedTouch qd) {
-            if (mQueuedTouchRecycleCount < MAX_RECYCLED_QUEUED_TOUCH) {
-                qd.mNext = mQueuedTouchRecycleBin;
-                mQueuedTouchRecycleBin = qd;
-                mQueuedTouchRecycleCount++;
-            }
-        }
-
-        /**
-         * Reset the touch event queue. This will dump any pending events
-         * and reset the sequence numbering.
-         */
-        public void reset() {
-            mNextTouchSequence = Long.MIN_VALUE + 1;
-            mLastHandledTouchSequence = Long.MIN_VALUE;
-            mIgnoreUntilSequence = Long.MIN_VALUE + 1;
-            while (mTouchEventQueue != null) {
-                QueuedTouch recycleMe = mTouchEventQueue;
-                mTouchEventQueue = mTouchEventQueue.mNext;
-                recycleQueuedTouch(recycleMe);
-            }
-            while (mPreQueue != null) {
-                QueuedTouch recycleMe = mPreQueue;
-                mPreQueue = mPreQueue.mNext;
-                recycleQueuedTouch(recycleMe);
-            }
-        }
-
-        /**
-         * Return the next valid sequence number for tagging incoming touch events.
-         * @return The next touch event sequence number
-         */
-        public long nextTouchSequence() {
-            return mNextTouchSequence++;
-        }
-
-        /**
-         * Enqueue a touch event in the form of TouchEventData.
-         * The sequence number will be read from the mSequence field of the argument.
-         *
-         * If the touch event's sequence number is the next in line to be processed, it will
-         * be handled before this method returns. Any subsequent events that have already
-         * been queued will also be processed in their proper order.
-         *
-         * @param ted Touch data to be processed in order.
-         * @return true if the event was processed before returning, false if it was just enqueued.
-         */
-        public boolean enqueueTouchEvent(TouchEventData ted) {
-            // Remove from the pre-queue if present
-            QueuedTouch preQueue = mPreQueue;
-            if (preQueue != null) {
-                // On exiting this block, preQueue is set to the pre-queued QueuedTouch object
-                // if it was present in the pre-queue, and removed from the pre-queue itself.
-                if (preQueue.mSequence == ted.mSequence) {
-                    mPreQueue = preQueue.mNext;
-                } else {
-                    QueuedTouch prev = preQueue;
-                    preQueue = null;
-                    while (prev.mNext != null) {
-                        if (prev.mNext.mSequence == ted.mSequence) {
-                            preQueue = prev.mNext;
-                            prev.mNext = preQueue.mNext;
-                            break;
-                        } else {
-                            prev = prev.mNext;
-                        }
-                    }
-                }
-            }
-
-            if (ted.mSequence < mLastHandledTouchSequence) {
-                // Stale event and we already moved on; drop it. (Should not be common.)
-                Log.w(LOGTAG, "Stale touch event " + MotionEvent.actionToString(ted.mAction) +
-                        " received from webcore; ignoring");
-                return false;
-            }
-
-            if (dropStaleGestures(ted.mMotionEvent, ted.mSequence)) {
-                return false;
-            }
-
-            // dropStaleGestures above might have fast-forwarded us to
-            // an event we have already.
-            runNextQueuedEvents();
-
-            if (mLastHandledTouchSequence + 1 == ted.mSequence) {
-                if (preQueue != null) {
-                    recycleQueuedTouch(preQueue);
-                    preQueue = null;
-                }
-                handleQueuedTouchEventData(ted);
-
-                mLastHandledTouchSequence++;
-
-                // Do we have any more? Run them if so.
-                runNextQueuedEvents();
-            } else {
-                // Reuse the pre-queued object if we had it.
-                QueuedTouch qd = preQueue != null ? preQueue : obtainQueuedTouch().set(ted);
-                mTouchEventQueue = mTouchEventQueue == null ? qd : mTouchEventQueue.add(qd);
-            }
-            return true;
-        }
-
-        /**
-         * Enqueue a touch event in the form of a MotionEvent from the framework.
-         *
-         * If the touch event's sequence number is the next in line to be processed, it will
-         * be handled before this method returns. Any subsequent events that have already
-         * been queued will also be processed in their proper order.
-         *
-         * @param ev MotionEvent to be processed in order
-         */
-        public void enqueueTouchEvent(MotionEvent ev) {
-            final long sequence = nextTouchSequence();
-
-            if (dropStaleGestures(ev, sequence)) {
-                return;
-            }
-
-            // dropStaleGestures above might have fast-forwarded us to
-            // an event we have already.
-            runNextQueuedEvents();
-
-            if (mLastHandledTouchSequence + 1 == sequence) {
-                handleQueuedMotionEvent(ev);
-
-                mLastHandledTouchSequence++;
-
-                // Do we have any more? Run them if so.
-                runNextQueuedEvents();
-            } else {
-                QueuedTouch qd = obtainQueuedTouch().set(ev, sequence);
-                mTouchEventQueue = mTouchEventQueue == null ? qd : mTouchEventQueue.add(qd);
-            }
-        }
-
-        private void runNextQueuedEvents() {
-            QueuedTouch qd = mTouchEventQueue;
-            while (qd != null && qd.mSequence == mLastHandledTouchSequence + 1) {
-                handleQueuedTouch(qd);
-                QueuedTouch recycleMe = qd;
-                qd = qd.mNext;
-                recycleQueuedTouch(recycleMe);
-                mLastHandledTouchSequence++;
-            }
-            mTouchEventQueue = qd;
-        }
-
-        private boolean dropStaleGestures(MotionEvent ev, long sequence) {
-            if (ev != null && ev.getAction() == MotionEvent.ACTION_MOVE && !mConfirmMove) {
-                // This is to make sure that we don't attempt to process a tap
-                // or long press when webkit takes too long to get back to us.
-                // The movement will be properly confirmed when we process the
-                // enqueued event later.
-                final int dx = Math.round(ev.getX()) - mLastTouchX;
-                final int dy = Math.round(ev.getY()) - mLastTouchY;
-                if (dx * dx + dy * dy > mTouchSlopSquare) {
-                    mPrivateHandler.removeMessages(SWITCH_TO_SHORTPRESS);
-                    mPrivateHandler.removeMessages(SWITCH_TO_LONGPRESS);
-                }
-            }
-
-            if (mTouchEventQueue == null) {
-                return sequence <= mLastHandledTouchSequence;
-            }
-
-            // If we have a new down event and it's been a while since the last event
-            // we saw, catch up as best we can and keep going.
-            if (ev != null && ev.getAction() == MotionEvent.ACTION_DOWN) {
-                long eventTime = ev.getEventTime();
-                long lastHandledEventTime = mLastEventTime;
-                if (eventTime > lastHandledEventTime + QUEUED_GESTURE_TIMEOUT) {
-                    Log.w(LOGTAG, "Got ACTION_DOWN but still waiting on stale event. " +
-                            "Catching up.");
-                    runQueuedAndPreQueuedEvents();
-
-                    // Drop leftovers that we truly don't have.
-                    QueuedTouch qd = mTouchEventQueue;
-                    while (qd != null && qd.mSequence < sequence) {
-                        QueuedTouch recycleMe = qd;
-                        qd = qd.mNext;
-                        recycleQueuedTouch(recycleMe);
-                    }
-                    mTouchEventQueue = qd;
-                    mLastHandledTouchSequence = sequence - 1;
-                }
-            }
-
-            if (mIgnoreUntilSequence - 1 > mLastHandledTouchSequence) {
-                QueuedTouch qd = mTouchEventQueue;
-                while (qd != null && qd.mSequence < mIgnoreUntilSequence) {
-                    QueuedTouch recycleMe = qd;
-                    qd = qd.mNext;
-                    recycleQueuedTouch(recycleMe);
-                }
-                mTouchEventQueue = qd;
-                mLastHandledTouchSequence = mIgnoreUntilSequence - 1;
-            }
-
-            if (mPreQueue != null) {
-                // Drop stale prequeued events
-                QueuedTouch qd = mPreQueue;
-                while (qd != null && qd.mSequence < mIgnoreUntilSequence) {
-                    QueuedTouch recycleMe = qd;
-                    qd = qd.mNext;
-                    recycleQueuedTouch(recycleMe);
-                }
-                mPreQueue = qd;
-            }
-
-            return sequence <= mLastHandledTouchSequence;
-        }
-
-        private void handleQueuedTouch(QueuedTouch qt) {
-            if (qt.mTed != null) {
-                handleQueuedTouchEventData(qt.mTed);
-            } else {
-                handleQueuedMotionEvent(qt.mEvent);
-                qt.mEvent.recycle();
-            }
-        }
-
-        private void handleQueuedMotionEvent(MotionEvent ev) {
-            mLastEventTime = ev.getEventTime();
-            int action = ev.getActionMasked();
-            if (ev.getPointerCount() > 1) {  // Multi-touch
-                handleMultiTouchInWebView(ev);
-            } else {
-                final ScaleGestureDetector detector = mZoomManager.getMultiTouchGestureDetector();
-                if (detector != null && mPreventDefault != PREVENT_DEFAULT_YES) {
-                    // ScaleGestureDetector needs a consistent event stream to operate properly.
-                    // It won't take any action with fewer than two pointers, but it needs to
-                    // update internal bookkeeping state.
-                    detector.onTouchEvent(ev);
-                }
-
-                handleTouchEventCommon(ev, action, Math.round(ev.getX()), Math.round(ev.getY()));
-            }
-        }
-
-        private void handleQueuedTouchEventData(TouchEventData ted) {
-            if (ted.mMotionEvent != null) {
-                mLastEventTime = ted.mMotionEvent.getEventTime();
-            }
-            if (!ted.mReprocess) {
-                if (ted.mAction == MotionEvent.ACTION_DOWN
-                        && mPreventDefault == PREVENT_DEFAULT_MAYBE_YES) {
-                    // if prevent default is called from WebCore, UI
-                    // will not handle the rest of the touch events any
-                    // more.
-                    mPreventDefault = ted.mNativeResult ? PREVENT_DEFAULT_YES
-                            : PREVENT_DEFAULT_NO_FROM_TOUCH_DOWN;
-                } else if (ted.mAction == MotionEvent.ACTION_MOVE
-                        && mPreventDefault == PREVENT_DEFAULT_NO_FROM_TOUCH_DOWN) {
-                    // the return for the first ACTION_MOVE will decide
-                    // whether UI will handle touch or not. Currently no
-                    // support for alternating prevent default
-                    mPreventDefault = ted.mNativeResult ? PREVENT_DEFAULT_YES
-                            : PREVENT_DEFAULT_NO;
-                }
-                if (mPreventDefault == PREVENT_DEFAULT_YES) {
-                    mTouchHighlightRegion.setEmpty();
-                }
-            } else {
-                if (ted.mPoints.length > 1) {  // multi-touch
-                    if (!ted.mNativeResult && mPreventDefault != PREVENT_DEFAULT_YES) {
-                        mPreventDefault = PREVENT_DEFAULT_NO;
-                        handleMultiTouchInWebView(ted.mMotionEvent);
-                    } else {
-                        mPreventDefault = PREVENT_DEFAULT_YES;
-                    }
-                    return;
-                }
-
-                // prevent default is not called in WebCore, so the
-                // message needs to be reprocessed in UI
-                if (!ted.mNativeResult) {
-                    // Following is for single touch.
-                    switch (ted.mAction) {
-                        case MotionEvent.ACTION_DOWN:
-                            mLastDeferTouchX = ted.mPointsInView[0].x;
-                            mLastDeferTouchY = ted.mPointsInView[0].y;
-                            mDeferTouchMode = TOUCH_INIT_MODE;
-                            break;
-                        case MotionEvent.ACTION_MOVE: {
-                            // no snapping in defer process
-                            int x = ted.mPointsInView[0].x;
-                            int y = ted.mPointsInView[0].y;
-
-                            if (mDeferTouchMode != TOUCH_DRAG_MODE) {
-                                mDeferTouchMode = TOUCH_DRAG_MODE;
-                                mLastDeferTouchX = x;
-                                mLastDeferTouchY = y;
-                                startScrollingLayer(x, y);
-                                startDrag();
-                            }
-                            int deltaX = pinLocX((int) (mScrollX
-                                    + mLastDeferTouchX - x))
-                                    - mScrollX;
-                            int deltaY = pinLocY((int) (mScrollY
-                                    + mLastDeferTouchY - y))
-                                    - mScrollY;
-                            doDrag(deltaX, deltaY);
-                            if (deltaX != 0) mLastDeferTouchX = x;
-                            if (deltaY != 0) mLastDeferTouchY = y;
-                            break;
-                        }
-                        case MotionEvent.ACTION_UP:
-                        case MotionEvent.ACTION_CANCEL:
-                            if (mDeferTouchMode == TOUCH_DRAG_MODE) {
-                                // no fling in defer process
-                                mScroller.springBack(mScrollX, mScrollY, 0,
-                                        computeMaxScrollX(), 0,
-                                        computeMaxScrollY());
-                                invalidate();
-                                WebViewCore.resumePriority();
-                                WebViewCore.resumeUpdatePicture(mWebViewCore);
-                            }
-                            mDeferTouchMode = TOUCH_DONE_MODE;
-                            break;
-                        case WebViewCore.ACTION_DOUBLETAP:
-                            // doDoubleTap() needs mLastTouchX/Y as anchor
-                            mLastDeferTouchX = ted.mPointsInView[0].x;
-                            mLastDeferTouchY = ted.mPointsInView[0].y;
-                            mZoomManager.handleDoubleTap(mLastTouchX, mLastTouchY);
-                            mDeferTouchMode = TOUCH_DONE_MODE;
-                            break;
-                        case WebViewCore.ACTION_LONGPRESS:
-                            HitTestResult hitTest = getHitTestResult();
-                            if (hitTest != null && hitTest.mType
-                                    != HitTestResult.UNKNOWN_TYPE) {
-                                performLongClick();
-                            }
-                            mDeferTouchMode = TOUCH_DONE_MODE;
-                            break;
-                    }
-                }
-            }
-        }
-    }
-
-    //-------------------------------------------------------------------------
-    // Methods can be called from a separate thread, like WebViewCore
-    // If it needs to call the View system, it has to send message.
-    //-------------------------------------------------------------------------
-
-    /**
-     * General handler to receive message coming from webkit thread
-     */
-    class PrivateHandler extends Handler {
-        @Override
-        public void handleMessage(Message msg) {
-            // exclude INVAL_RECT_MSG_ID since it is frequently output
-            if (DebugFlags.WEB_VIEW && msg.what != INVAL_RECT_MSG_ID) {
-                if (msg.what >= FIRST_PRIVATE_MSG_ID
-                        && msg.what <= LAST_PRIVATE_MSG_ID) {
-                    Log.v(LOGTAG, HandlerPrivateDebugString[msg.what
-                            - FIRST_PRIVATE_MSG_ID]);
-                } else if (msg.what >= FIRST_PACKAGE_MSG_ID
-                        && msg.what <= LAST_PACKAGE_MSG_ID) {
-                    Log.v(LOGTAG, HandlerPackageDebugString[msg.what
-                            - FIRST_PACKAGE_MSG_ID]);
-                } else {
-                    Log.v(LOGTAG, Integer.toString(msg.what));
-                }
-            }
-            if (mWebViewCore == null) {
-                // after WebView's destroy() is called, skip handling messages.
-                return;
-            }
-            if (mBlockWebkitViewMessages
-                    && msg.what != WEBCORE_INITIALIZED_MSG_ID) {
-                // Blocking messages from webkit
-                return;
-            }
-            switch (msg.what) {
-                case REMEMBER_PASSWORD: {
-                    mDatabase.setUsernamePassword(
-                            msg.getData().getString("host"),
-                            msg.getData().getString("username"),
-                            msg.getData().getString("password"));
-                    ((Message) msg.obj).sendToTarget();
-                    break;
-                }
-                case NEVER_REMEMBER_PASSWORD: {
-                    mDatabase.setUsernamePassword(
-                            msg.getData().getString("host"), null, null);
-                    ((Message) msg.obj).sendToTarget();
-                    break;
-                }
-                case PREVENT_DEFAULT_TIMEOUT: {
-                    // if timeout happens, cancel it so that it won't block UI
-                    // to continue handling touch events
-                    if ((msg.arg1 == MotionEvent.ACTION_DOWN
-                            && mPreventDefault == PREVENT_DEFAULT_MAYBE_YES)
-                            || (msg.arg1 == MotionEvent.ACTION_MOVE
-                            && mPreventDefault == PREVENT_DEFAULT_NO_FROM_TOUCH_DOWN)) {
-                        cancelWebCoreTouchEvent(
-                                viewToContentX(mLastTouchX + mScrollX),
-                                viewToContentY(mLastTouchY + mScrollY),
-                                true);
-                    }
-                    break;
-                }
-                case SCROLL_SELECT_TEXT: {
-                    if (mAutoScrollX == 0 && mAutoScrollY == 0) {
-                        mSentAutoScrollMessage = false;
-                        break;
-                    }
-                    if (mCurrentScrollingLayerId == 0) {
-                        pinScrollBy(mAutoScrollX, mAutoScrollY, true, 0);
-                    } else {
-                        scrollLayerTo(mScrollingLayerRect.left + mAutoScrollX,
-                                mScrollingLayerRect.top + mAutoScrollY);
-                    }
-                    sendEmptyMessageDelayed(
-                            SCROLL_SELECT_TEXT, SELECT_SCROLL_INTERVAL);
-                    break;
-                }
-                case UPDATE_SELECTION: {
-                    if (mTouchMode == TOUCH_INIT_MODE
-                            || mTouchMode == TOUCH_SHORTPRESS_MODE
-                            || mTouchMode == TOUCH_SHORTPRESS_START_MODE) {
-                        updateSelection();
-                    }
-                    break;
-                }
-                case SWITCH_TO_SHORTPRESS: {
-                    if (mTouchMode == TOUCH_INIT_MODE) {
-                        if (!sDisableNavcache
-                                && mPreventDefault != PREVENT_DEFAULT_YES) {
-                            mTouchMode = TOUCH_SHORTPRESS_START_MODE;
-                            updateSelection();
-                        } else {
-                            // set to TOUCH_SHORTPRESS_MODE so that it won't
-                            // trigger double tap any more
-                            mTouchMode = TOUCH_SHORTPRESS_MODE;
-                        }
-                    } else if (mTouchMode == TOUCH_DOUBLE_TAP_MODE) {
-                        mTouchMode = TOUCH_DONE_MODE;
-                    }
-                    break;
-                }
-                case SWITCH_TO_LONGPRESS: {
-                    if (sDisableNavcache) {
-                        removeTouchHighlight();
-                    }
-                    if (inFullScreenMode() || mDeferTouchProcess) {
-                        TouchEventData ted = new TouchEventData();
-                        ted.mAction = WebViewCore.ACTION_LONGPRESS;
-                        ted.mIds = new int[1];
-                        ted.mIds[0] = 0;
-                        ted.mPoints = new Point[1];
-                        ted.mPoints[0] = new Point(viewToContentX(mLastTouchX + mScrollX),
-                                                   viewToContentY(mLastTouchY + mScrollY));
-                        ted.mPointsInView = new Point[1];
-                        ted.mPointsInView[0] = new Point(mLastTouchX, mLastTouchY);
-                        // metaState for long press is tricky. Should it be the
-                        // state when the press started or when the press was
-                        // released? Or some intermediary key state? For
-                        // simplicity for now, we don't set it.
-                        ted.mMetaState = 0;
-                        ted.mReprocess = mDeferTouchProcess;
-                        ted.mNativeLayer = nativeScrollableLayer(
-                                ted.mPoints[0].x, ted.mPoints[0].y,
-                                ted.mNativeLayerRect, null);
-                        ted.mSequence = mTouchEventQueue.nextTouchSequence();
-                        mTouchEventQueue.preQueueTouchEventData(ted);
-                        mWebViewCore.sendMessage(EventHub.TOUCH_EVENT, ted);
-                    } else if (mPreventDefault != PREVENT_DEFAULT_YES) {
-                        mTouchMode = TOUCH_DONE_MODE;
-                        performLongClick();
-                    }
-                    break;
-                }
-                case RELEASE_SINGLE_TAP: {
-                    doShortPress();
-                    break;
-                }
-                case SCROLL_TO_MSG_ID: {
-                    // arg1 = animate, arg2 = onlyIfImeIsShowing
-                    // obj = Point(x, y)
-                    if (msg.arg2 == 1) {
-                        // This scroll is intended to bring the textfield into
-                        // view, but is only necessary if the IME is showing
-                        InputMethodManager imm = InputMethodManager.peekInstance();
-                        if (imm == null || !imm.isAcceptingText()
-                                || (!imm.isActive(WebView.this) && (!inEditingMode()
-                                || !imm.isActive(mWebTextView)))) {
-                            break;
-                        }
-                    }
-                    final Point p = (Point) msg.obj;
-                    if (msg.arg1 == 1) {
-                        spawnContentScrollTo(p.x, p.y);
-                    } else {
-                        setContentScrollTo(p.x, p.y);
-                    }
-                    break;
-                }
-                case UPDATE_ZOOM_RANGE: {
-                    WebViewCore.ViewState viewState = (WebViewCore.ViewState) msg.obj;
-                    // mScrollX contains the new minPrefWidth
-                    mZoomManager.updateZoomRange(viewState, getViewWidth(), viewState.mScrollX);
-                    break;
-                }
-                case UPDATE_ZOOM_DENSITY: {
-                    final float density = (Float) msg.obj;
-                    mZoomManager.updateDefaultZoomDensity(density);
-                    break;
-                }
-                case REPLACE_BASE_CONTENT: {
-                    nativeReplaceBaseContent(msg.arg1);
-                    break;
-                }
-                case NEW_PICTURE_MSG_ID: {
-                    // called for new content
-                    final WebViewCore.DrawData draw = (WebViewCore.DrawData) msg.obj;
-                    setNewPicture(draw, true);
-                    break;
-                }
-                case WEBCORE_INITIALIZED_MSG_ID:
-                    // nativeCreate sets mNativeClass to a non-zero value
-                    String drawableDir = BrowserFrame.getRawResFilename(
-                            BrowserFrame.DRAWABLEDIR, mContext);
-                    WindowManager windowManager =
-                            (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
-                    Display display = windowManager.getDefaultDisplay();
-                    nativeCreate(msg.arg1, drawableDir,
-                            ActivityManager.isHighEndGfx(display));
-                    if (mDelaySetPicture != null) {
-                        setNewPicture(mDelaySetPicture, true);
-                        mDelaySetPicture = null;
-                    }
-                    if (mIsPaused) {
-                        nativeSetPauseDrawing(mNativeClass, true);
-                    }
-                    break;
-                case UPDATE_TEXTFIELD_TEXT_MSG_ID:
-                    // Make sure that the textfield is currently focused
-                    // and representing the same node as the pointer.
-                    if (msg.arg2 == mTextGeneration) {
-                        String text = (String) msg.obj;
-                        if (null == text) {
-                            text = "";
-                        }
-                        if (inEditingMode() &&
-                                mWebTextView.isSameTextField(msg.arg1)) {
-                            mWebTextView.setTextAndKeepSelection(text);
-                        } else if (mInputConnection != null &&
-                                mFieldPointer == msg.arg1) {
-                            mInputConnection.setTextAndKeepSelection(text);
-                        }
-                    }
-                    break;
-                case REQUEST_KEYBOARD_WITH_SELECTION_MSG_ID:
-                    displaySoftKeyboard(true);
-                    // fall through to UPDATE_TEXT_SELECTION_MSG_ID
-                case UPDATE_TEXT_SELECTION_MSG_ID:
-                    updateTextSelectionFromMessage(msg.arg1, msg.arg2,
-                            (WebViewCore.TextSelectionData) msg.obj);
-                    break;
-                case FORM_DID_BLUR:
-                    if (inEditingMode()
-                            && mWebTextView.isSameTextField(msg.arg1)) {
-                        hideSoftKeyboard();
-                    }
-                    break;
-                case RETURN_LABEL:
-                    if (inEditingMode()
-                            && mWebTextView.isSameTextField(msg.arg1)) {
-                        mWebTextView.setHint((String) msg.obj);
-                        InputMethodManager imm
-                                = InputMethodManager.peekInstance();
-                        // The hint is propagated to the IME in
-                        // onCreateInputConnection.  If the IME is already
-                        // active, restart it so that its hint text is updated.
-                        if (imm != null && imm.isActive(mWebTextView)) {
-                            imm.restartInput(mWebTextView);
-                        }
-                    }
-                    break;
-                case UNHANDLED_NAV_KEY:
-                    navHandledKey(msg.arg1, 1, false, 0);
-                    break;
-                case UPDATE_TEXT_ENTRY_MSG_ID:
-                    // this is sent after finishing resize in WebViewCore. Make
-                    // sure the text edit box is still on the  screen.
-                    if (inEditingMode() && nativeCursorIsTextInput()) {
-                        updateWebTextViewPosition();
-                    }
-                    break;
-                case CLEAR_TEXT_ENTRY:
-                    clearTextEntry();
-                    break;
-                case INVAL_RECT_MSG_ID: {
-                    Rect r = (Rect)msg.obj;
-                    if (r == null) {
-                        invalidate();
-                    } else {
-                        // we need to scale r from content into view coords,
-                        // which viewInvalidate() does for us
-                        viewInvalidate(r.left, r.top, r.right, r.bottom);
-                    }
-                    break;
-                }
-                case REQUEST_FORM_DATA:
-                    AutoCompleteAdapter adapter = (AutoCompleteAdapter) msg.obj;
-                    if (mWebTextView.isSameTextField(msg.arg1)) {
-                        mWebTextView.setAdapterCustom(adapter);
-                    }
-                    break;
-
-                case LONG_PRESS_CENTER:
-                    // as this is shared by keydown and trackballdown, reset all
-                    // the states
-                    mGotCenterDown = false;
-                    mTrackballDown = false;
-                    performLongClick();
-                    break;
-
-                case WEBCORE_NEED_TOUCH_EVENTS:
-                    mForwardTouchEvents = (msg.arg1 != 0);
-                    break;
-
-                case PREVENT_TOUCH_ID:
-                    if (inFullScreenMode()) {
-                        break;
-                    }
-                    TouchEventData ted = (TouchEventData) msg.obj;
-
-                    if (mTouchEventQueue.enqueueTouchEvent(ted)) {
-                        // WebCore is responding to us; remove pending timeout.
-                        // It will be re-posted when needed.
-                        removeMessages(PREVENT_DEFAULT_TIMEOUT);
-                    }
-                    break;
-
-                case REQUEST_KEYBOARD:
-                    if (msg.arg1 == 0) {
-                        hideSoftKeyboard();
-                    } else {
-                        displaySoftKeyboard(false);
-                    }
-                    break;
-
-                case DRAG_HELD_MOTIONLESS:
-                    mHeldMotionless = MOTIONLESS_TRUE;
-                    invalidate();
-                    // fall through to keep scrollbars awake
-
-                case AWAKEN_SCROLL_BARS:
-                    if (mTouchMode == TOUCH_DRAG_MODE
-                            && mHeldMotionless == MOTIONLESS_TRUE) {
-                        awakenScrollBars(ViewConfiguration
-                                .getScrollDefaultDelay(), false);
-                        mPrivateHandler.sendMessageDelayed(mPrivateHandler
-                                .obtainMessage(AWAKEN_SCROLL_BARS),
-                                ViewConfiguration.getScrollDefaultDelay());
-                    }
-                    break;
-
-                case DO_MOTION_UP:
-                    doMotionUp(msg.arg1, msg.arg2);
-                    break;
-
-                case SCREEN_ON:
-                    setKeepScreenOn(msg.arg1 == 1);
-                    break;
-
-                case ENTER_FULLSCREEN_VIDEO:
-                    int layerId = msg.arg1;
-
-                    String url = (String) msg.obj;
-                    if (mHTML5VideoViewProxy != null) {
-                        mHTML5VideoViewProxy.enterFullScreenVideo(layerId, url);
-                    }
-                    break;
-
-                case EXIT_FULLSCREEN_VIDEO:
-                    if (mHTML5VideoViewProxy != null) {
-                        mHTML5VideoViewProxy.exitFullScreenVideo();
-                    }
-                    break;
-
-                case SHOW_FULLSCREEN: {
-                    View view = (View) msg.obj;
-                    int orientation = msg.arg1;
-                    int npp = msg.arg2;
-
-                    if (inFullScreenMode()) {
-                        Log.w(LOGTAG, "Should not have another full screen.");
-                        dismissFullScreenMode();
-                    }
-                    mFullScreenHolder = new PluginFullScreenHolder(WebView.this, orientation, npp);
-                    mFullScreenHolder.setContentView(view);
-                    mFullScreenHolder.show();
-                    invalidate();
-
-                    break;
-                }
-                case HIDE_FULLSCREEN:
-                    dismissFullScreenMode();
-                    break;
-
-                case DOM_FOCUS_CHANGED:
-                    if (inEditingMode()) {
-                        nativeClearCursor();
-                        rebuildWebTextView();
-                    }
-                    break;
-
-                case SHOW_RECT_MSG_ID: {
-                    WebViewCore.ShowRectData data = (WebViewCore.ShowRectData) msg.obj;
-                    int x = mScrollX;
-                    int left = contentToViewX(data.mLeft);
-                    int width = contentToViewDimension(data.mWidth);
-                    int maxWidth = contentToViewDimension(data.mContentWidth);
-                    int viewWidth = getViewWidth();
-                    if (width < viewWidth) {
-                        // center align
-                        x += left + width / 2 - mScrollX - viewWidth / 2;
-                    } else {
-                        x += (int) (left + data.mXPercentInDoc * width
-                                - mScrollX - data.mXPercentInView * viewWidth);
-                    }
-                    if (DebugFlags.WEB_VIEW) {
-                        Log.v(LOGTAG, "showRectMsg=(left=" + left + ",width=" +
-                              width + ",maxWidth=" + maxWidth +
-                              ",viewWidth=" + viewWidth + ",x="
-                              + x + ",xPercentInDoc=" + data.mXPercentInDoc +
-                              ",xPercentInView=" + data.mXPercentInView+ ")");
-                    }
-                    // use the passing content width to cap x as the current
-                    // mContentWidth may not be updated yet
-                    x = Math.max(0,
-                            (Math.min(maxWidth, x + viewWidth)) - viewWidth);
-                    int top = contentToViewY(data.mTop);
-                    int height = contentToViewDimension(data.mHeight);
-                    int maxHeight = contentToViewDimension(data.mContentHeight);
-                    int viewHeight = getViewHeight();
-                    int y = (int) (top + data.mYPercentInDoc * height -
-                                   data.mYPercentInView * viewHeight);
-                    if (DebugFlags.WEB_VIEW) {
-                        Log.v(LOGTAG, "showRectMsg=(top=" + top + ",height=" +
-                              height + ",maxHeight=" + maxHeight +
-                              ",viewHeight=" + viewHeight + ",y="
-                              + y + ",yPercentInDoc=" + data.mYPercentInDoc +
-                              ",yPercentInView=" + data.mYPercentInView+ ")");
-                    }
-                    // use the passing content height to cap y as the current
-                    // mContentHeight may not be updated yet
-                    y = Math.max(0,
-                            (Math.min(maxHeight, y + viewHeight) - viewHeight));
-                    // We need to take into account the visible title height
-                    // when scrolling since y is an absolute view position.
-                    y = Math.max(0, y - getVisibleTitleHeightImpl());
-                    scrollTo(x, y);
-                    }
-                    break;
-
-                case CENTER_FIT_RECT:
-                    centerFitRect((Rect)msg.obj);
-                    break;
-
-                case SET_SCROLLBAR_MODES:
-                    mHorizontalScrollBarMode = msg.arg1;
-                    mVerticalScrollBarMode = msg.arg2;
-                    break;
-
-                case SELECTION_STRING_CHANGED:
-                    if (mAccessibilityInjector != null) {
-                        String selectionString = (String) msg.obj;
-                        mAccessibilityInjector.onSelectionStringChange(selectionString);
-                    }
-                    break;
-
-                case HIT_TEST_RESULT:
-                    WebKitHitTest hit = (WebKitHitTest) msg.obj;
-                    mFocusedNode = hit;
-                    setTouchHighlightRects(hit);
-                    setHitTestResult(hit);
-                    break;
-
-                case SAVE_WEBARCHIVE_FINISHED:
-                    SaveWebArchiveMessage saveMessage = (SaveWebArchiveMessage)msg.obj;
-                    if (saveMessage.mCallback != null) {
-                        saveMessage.mCallback.onReceiveValue(saveMessage.mResultFile);
-                    }
-                    break;
-
-                case SET_AUTOFILLABLE:
-                    mAutoFillData = (WebViewCore.AutoFillData) msg.obj;
-                    if (mWebTextView != null) {
-                        mWebTextView.setAutoFillable(mAutoFillData.getQueryId());
-                        rebuildWebTextView();
-                    }
-                    break;
-
-                case AUTOFILL_COMPLETE:
-                    if (mWebTextView != null) {
-                        // Clear the WebTextView adapter when AutoFill finishes
-                        // so that the drop down gets cleared.
-                        mWebTextView.setAdapterCustom(null);
-                    }
-                    break;
-
-                case SELECT_AT:
-                    nativeSelectAt(msg.arg1, msg.arg2);
-                    break;
-
-                case COPY_TO_CLIPBOARD:
-                    copyToClipboard((String) msg.obj);
-                    break;
-
-                case INIT_EDIT_FIELD:
-                    if (mInputConnection != null) {
-                        TextFieldInitData initData = (TextFieldInitData) msg.obj;
-                        mTextGeneration = 0;
-                        mFieldPointer = initData.mFieldPointer;
-                        mInputConnection.initEditorInfo(initData);
-                        mInputConnection.setTextAndKeepSelection(initData.mText);
-                    }
-                    break;
-
-                case REPLACE_TEXT:{
-                    String text = (String)msg.obj;
-                    int start = msg.arg1;
-                    int end = msg.arg2;
-                    int cursorPosition = start + text.length();
-                    replaceTextfieldText(start, end, text,
-                            cursorPosition, cursorPosition);
-                    break;
-                }
-
-                case UPDATE_MATCH_COUNT: {
-                    if (mFindCallback != null) {
-                        mFindCallback.updateMatchCount(msg.arg1, msg.arg2,
-                            (String) msg.obj);
-                    }
-                    break;
-                }
-                case CLEAR_CARET_HANDLE:
-                    selectionDone();
-                    break;
-
-                case KEY_PRESS:
-                    mWebViewCore.sendMessage(EventHub.KEY_PRESS, msg.arg1);
-                    break;
-
-                default:
-                    super.handleMessage(msg);
-                    break;
-            }
-        }
-    }
-
-    private void setHitTestTypeFromUrl(String url) {
-        String substr = null;
-        if (url.startsWith(SCHEME_GEO)) {
-            mInitialHitTestResult.mType = HitTestResult.GEO_TYPE;
-            substr = url.substring(SCHEME_GEO.length());
-        } else if (url.startsWith(SCHEME_TEL)) {
-            mInitialHitTestResult.mType = HitTestResult.PHONE_TYPE;
-            substr = url.substring(SCHEME_TEL.length());
-        } else if (url.startsWith(SCHEME_MAILTO)) {
-            mInitialHitTestResult.mType = HitTestResult.EMAIL_TYPE;
-            substr = url.substring(SCHEME_MAILTO.length());
-        } else {
-            mInitialHitTestResult.mType = HitTestResult.SRC_ANCHOR_TYPE;
-            mInitialHitTestResult.mExtra = url;
-            return;
-        }
-        try {
-            mInitialHitTestResult.mExtra = URLDecoder.decode(substr, "UTF-8");
-        } catch (Throwable e) {
-            Log.w(LOGTAG, "Failed to decode URL! " + substr, e);
-            mInitialHitTestResult.mType = HitTestResult.UNKNOWN_TYPE;
-        }
-    }
-
-    private void setHitTestResult(WebKitHitTest hit) {
-        if (hit == null) {
-            mInitialHitTestResult = null;
-            return;
-        }
-        mInitialHitTestResult = new HitTestResult();
-        if (hit.mLinkUrl != null) {
-            setHitTestTypeFromUrl(hit.mLinkUrl);
-            if (hit.mImageUrl != null
-                    && mInitialHitTestResult.mType == HitTestResult.SRC_ANCHOR_TYPE) {
-                mInitialHitTestResult.mType = HitTestResult.SRC_IMAGE_ANCHOR_TYPE;
-                mInitialHitTestResult.mExtra = hit.mImageUrl;
-            }
-        } else if (hit.mImageUrl != null) {
-            mInitialHitTestResult.mType = HitTestResult.IMAGE_TYPE;
-            mInitialHitTestResult.mExtra = hit.mImageUrl;
-        } else if (hit.mEditable) {
-            mInitialHitTestResult.mType = HitTestResult.EDIT_TEXT_TYPE;
-        } else if (hit.mIntentUrl != null) {
-            setHitTestTypeFromUrl(hit.mIntentUrl);
-        }
-    }
-
-    private boolean shouldDrawHighlightRect() {
-        if (mFocusedNode == null || mInitialHitTestResult == null) {
-            return false;
-        }
-        if (mTouchHighlightRegion.isEmpty()) {
-            return false;
-        }
-        if (mFocusedNode.mHasFocus && !isInTouchMode()) {
-            return !mFocusedNode.mEditable;
-        }
-        if (mInitialHitTestResult.mType == HitTestResult.UNKNOWN_TYPE) {
-            return false;
-        }
-        long delay = System.currentTimeMillis() - mTouchHighlightRequested;
-        if (delay < ViewConfiguration.getTapTimeout()) {
-            Rect r = mTouchHighlightRegion.getBounds();
-            postInvalidateDelayed(delay, r.left, r.top, r.right, r.bottom);
-            return false;
-        }
-        return true;
-    }
-
-
-    private FocusTransitionDrawable mFocusTransition = null;
-    static class FocusTransitionDrawable extends Drawable {
-        Region mPreviousRegion;
-        Region mNewRegion;
-        float mProgress = 0;
-        WebView mWebView;
-        Paint mPaint;
-        int mMaxAlpha;
-        Point mTranslate;
-
-        public FocusTransitionDrawable(WebView view) {
-            mWebView = view;
-            mPaint = new Paint(mWebView.mTouchHightlightPaint);
-            mMaxAlpha = mPaint.getAlpha();
-        }
-
-        @Override
-        public void setColorFilter(ColorFilter cf) {
-        }
-
-        @Override
-        public void setAlpha(int alpha) {
-        }
-
-        @Override
-        public int getOpacity() {
-            return 0;
-        }
-
-        public void setProgress(float p) {
-            mProgress = p;
-            if (mWebView.mFocusTransition == this) {
-                if (mProgress == 1f)
-                    mWebView.mFocusTransition = null;
-                mWebView.invalidate();
-            }
-        }
-
-        public float getProgress() {
-            return mProgress;
-        }
-
-        @Override
-        public void draw(Canvas canvas) {
-            if (mTranslate == null) {
-                Rect bounds = mPreviousRegion.getBounds();
-                Point from = new Point(bounds.centerX(), bounds.centerY());
-                mNewRegion.getBounds(bounds);
-                Point to = new Point(bounds.centerX(), bounds.centerY());
-                mTranslate = new Point(from.x - to.x, from.y - to.y);
-            }
-            int alpha = (int) (mProgress * mMaxAlpha);
-            RegionIterator iter = new RegionIterator(mPreviousRegion);
-            Rect r = new Rect();
-            mPaint.setAlpha(mMaxAlpha - alpha);
-            float tx = mTranslate.x * mProgress;
-            float ty = mTranslate.y * mProgress;
-            int save = canvas.save(Canvas.MATRIX_SAVE_FLAG);
-            canvas.translate(-tx, -ty);
-            while (iter.next(r)) {
-                canvas.drawRect(r, mPaint);
-            }
-            canvas.restoreToCount(save);
-            iter = new RegionIterator(mNewRegion);
-            r = new Rect();
-            mPaint.setAlpha(alpha);
-            save = canvas.save(Canvas.MATRIX_SAVE_FLAG);
-            tx = mTranslate.x - tx;
-            ty = mTranslate.y - ty;
-            canvas.translate(tx, ty);
-            while (iter.next(r)) {
-                canvas.drawRect(r, mPaint);
-            }
-            canvas.restoreToCount(save);
-        }
-    };
-
-    private boolean shouldAnimateTo(WebKitHitTest hit) {
-        // TODO: Don't be annoying or throw out the animation entirely
-        return false;
-    }
-
-    private void setTouchHighlightRects(WebKitHitTest hit) {
-        FocusTransitionDrawable transition = null;
-        if (shouldAnimateTo(hit)) {
-            transition = new FocusTransitionDrawable(this);
-        }
-        Rect[] rects = hit != null ? hit.mTouchRects : null;
-        if (!mTouchHighlightRegion.isEmpty()) {
-            invalidate(mTouchHighlightRegion.getBounds());
-            if (transition != null) {
-                transition.mPreviousRegion = new Region(mTouchHighlightRegion);
-            }
-            mTouchHighlightRegion.setEmpty();
-        }
-        if (rects != null) {
-            mTouchHightlightPaint.setColor(hit.mTapHighlightColor);
-            for (Rect rect : rects) {
-                Rect viewRect = contentToViewRect(rect);
-                // some sites, like stories in nytimes.com, set
-                // mouse event handler in the top div. It is not
-                // user friendly to highlight the div if it covers
-                // more than half of the screen.
-                if (viewRect.width() < getWidth() >> 1
-                        || viewRect.height() < getHeight() >> 1) {
-                    mTouchHighlightRegion.union(viewRect);
-                } else {
-                    Log.w(LOGTAG, "Skip the huge selection rect:"
-                            + viewRect);
-                }
-            }
-            invalidate(mTouchHighlightRegion.getBounds());
-            if (transition != null && transition.mPreviousRegion != null) {
-                transition.mNewRegion = new Region(mTouchHighlightRegion);
-                mFocusTransition = transition;
-                ObjectAnimator animator = ObjectAnimator.ofFloat(
-                        mFocusTransition, "progress", 1f);
-                animator.start();
-            }
-        }
-    }
-
-    /** @hide Called by JNI when pages are swapped (only occurs with hardware
-     * acceleration) */
-    protected void pageSwapCallback(boolean notifyAnimationStarted) {
-        mWebViewCore.resumeWebKitDraw();
-        if (inEditingMode()) {
-            didUpdateWebTextViewDimensions(ANYWHERE);
-        }
-        if (notifyAnimationStarted) {
-            mWebViewCore.sendMessage(EventHub.NOTIFY_ANIMATION_STARTED);
-        }
-    }
-
-    void setNewPicture(final WebViewCore.DrawData draw, boolean updateBaseLayer) {
-        if (mNativeClass == 0) {
-            if (mDelaySetPicture != null) {
-                throw new IllegalStateException("Tried to setNewPicture with"
-                        + " a delay picture already set! (memory leak)");
-            }
-            // Not initialized yet, delay set
-            mDelaySetPicture = draw;
-            return;
-        }
-        WebViewCore.ViewState viewState = draw.mViewState;
-        boolean isPictureAfterFirstLayout = viewState != null;
-
-        if (updateBaseLayer) {
-            setBaseLayer(draw.mBaseLayer, draw.mInvalRegion,
-                    getSettings().getShowVisualIndicator(),
-                    isPictureAfterFirstLayout);
-        }
-        final Point viewSize = draw.mViewSize;
-        // We update the layout (i.e. request a layout from the
-        // view system) if the last view size that we sent to
-        // WebCore matches the view size of the picture we just
-        // received in the fixed dimension.
-        final boolean updateLayout = viewSize.x == mLastWidthSent
-                && viewSize.y == mLastHeightSent;
-        // Don't send scroll event for picture coming from webkit,
-        // since the new picture may cause a scroll event to override
-        // the saved history scroll position.
-        mSendScrollEvent = false;
-        recordNewContentSize(draw.mContentSize.x,
-                draw.mContentSize.y, updateLayout);
-        if (isPictureAfterFirstLayout) {
-            // Reset the last sent data here since dealing with new page.
-            mLastWidthSent = 0;
-            mZoomManager.onFirstLayout(draw);
-            int scrollX = viewState.mShouldStartScrolledRight
-                    ? getContentWidth() : viewState.mScrollX;
-            int scrollY = viewState.mScrollY;
-            setContentScrollTo(scrollX, scrollY);
-            if (!mDrawHistory) {
-                // As we are on a new page, remove the WebTextView. This
-                // is necessary for page loads driven by webkit, and in
-                // particular when the user was on a password field, so
-                // the WebTextView was visible.
-                clearTextEntry();
-            }
-        }
-        mSendScrollEvent = true;
-
-        if (DebugFlags.WEB_VIEW) {
-            Rect b = draw.mInvalRegion.getBounds();
-            Log.v(LOGTAG, "NEW_PICTURE_MSG_ID {" +
-                    b.left+","+b.top+","+b.right+","+b.bottom+"}");
-        }
-        invalidateContentRect(draw.mInvalRegion.getBounds());
-
-        if (mPictureListener != null) {
-            mPictureListener.onNewPicture(WebView.this, capturePicture());
-        }
-
-        // update the zoom information based on the new picture
-        mZoomManager.onNewPicture(draw);
-
-        if (draw.mFocusSizeChanged && inEditingMode()) {
-            mFocusSizeChanged = true;
-        }
-        if (isPictureAfterFirstLayout) {
-            mViewManager.postReadyToDrawAll();
-        }
-    }
-
-    /**
-     * Used when receiving messages for REQUEST_KEYBOARD_WITH_SELECTION_MSG_ID
-     * and UPDATE_TEXT_SELECTION_MSG_ID.  Update the selection of WebTextView.
-     */
-    private void updateTextSelectionFromMessage(int nodePointer,
-            int textGeneration, WebViewCore.TextSelectionData data) {
-        if (textGeneration == mTextGeneration) {
-            if (inEditingMode()
-                    && mWebTextView.isSameTextField(nodePointer)) {
-                mWebTextView.setSelectionFromWebKit(data.mStart, data.mEnd);
-            } else if (mInputConnection != null && mFieldPointer == nodePointer) {
-                mInputConnection.setSelection(data.mStart, data.mEnd);
-            }
-        }
-        nativeSetTextSelection(mNativeClass, data.mSelectTextPtr);
-
-        if (data.mSelectTextPtr != 0 &&
-                (data.mStart != data.mEnd ||
-                (mFieldPointer == nodePointer && mFieldPointer != 0))) {
-            mIsCaretSelection = (data.mStart == data.mEnd);
-            if (!mSelectingText) {
-                setupWebkitSelect();
-            } else if (!mSelectionStarted) {
-                syncSelectionCursors();
-            }
-            if (mIsCaretSelection) {
-                resetCaretTimer();
-            }
-        } else {
-            selectionDone();
-        }
-        invalidate();
-    }
-
-    // Class used to use a dropdown for a <select> element
-    private class InvokeListBox implements Runnable {
-        // Whether the listbox allows multiple selection.
-        private boolean     mMultiple;
-        // Passed in to a list with multiple selection to tell
-        // which items are selected.
-        private int[]       mSelectedArray;
-        // Passed in to a list with single selection to tell
-        // where the initial selection is.
-        private int         mSelection;
-
-        private Container[] mContainers;
-
-        // Need these to provide stable ids to my ArrayAdapter,
-        // which normally does not have stable ids. (Bug 1250098)
-        private class Container extends Object {
-            /**
-             * Possible values for mEnabled.  Keep in sync with OptionStatus in
-             * WebViewCore.cpp
-             */
-            final static int OPTGROUP = -1;
-            final static int OPTION_DISABLED = 0;
-            final static int OPTION_ENABLED = 1;
-
-            String  mString;
-            int     mEnabled;
-            int     mId;
-
-            @Override
-            public String toString() {
-                return mString;
-            }
-        }
-
-        /**
-         *  Subclass ArrayAdapter so we can disable OptionGroupLabels,
-         *  and allow filtering.
-         */
-        private class MyArrayListAdapter extends ArrayAdapter<Container> {
-            public MyArrayListAdapter() {
-                super(mContext,
-                        mMultiple ? com.android.internal.R.layout.select_dialog_multichoice :
-                        com.android.internal.R.layout.webview_select_singlechoice,
-                        mContainers);
-            }
-
-            @Override
-            public View getView(int position, View convertView,
-                    ViewGroup parent) {
-                // Always pass in null so that we will get a new CheckedTextView
-                // Otherwise, an item which was previously used as an <optgroup>
-                // element (i.e. has no check), could get used as an <option>
-                // element, which needs a checkbox/radio, but it would not have
-                // one.
-                convertView = super.getView(position, null, parent);
-                Container c = item(position);
-                if (c != null && Container.OPTION_ENABLED != c.mEnabled) {
-                    // ListView does not draw dividers between disabled and
-                    // enabled elements.  Use a LinearLayout to provide dividers
-                    LinearLayout layout = new LinearLayout(mContext);
-                    layout.setOrientation(LinearLayout.VERTICAL);
-                    if (position > 0) {
-                        View dividerTop = new View(mContext);
-                        dividerTop.setBackgroundResource(
-                                android.R.drawable.divider_horizontal_bright);
-                        layout.addView(dividerTop);
-                    }
-
-                    if (Container.OPTGROUP == c.mEnabled) {
-                        // Currently select_dialog_multichoice uses CheckedTextViews.
-                        // If that changes, the class cast will no longer be valid.
-                        if (mMultiple) {
-                            Assert.assertTrue(convertView instanceof CheckedTextView);
-                            ((CheckedTextView) convertView).setCheckMarkDrawable(null);
-                        }
-                    } else {
-                        // c.mEnabled == Container.OPTION_DISABLED
-                        // Draw the disabled element in a disabled state.
-                        convertView.setEnabled(false);
-                    }
-
-                    layout.addView(convertView);
-                    if (position < getCount() - 1) {
-                        View dividerBottom = new View(mContext);
-                        dividerBottom.setBackgroundResource(
-                                android.R.drawable.divider_horizontal_bright);
-                        layout.addView(dividerBottom);
-                    }
-                    return layout;
-                }
-                return convertView;
-            }
-
-            @Override
-            public boolean hasStableIds() {
-                // AdapterView's onChanged method uses this to determine whether
-                // to restore the old state.  Return false so that the old (out
-                // of date) state does not replace the new, valid state.
-                return false;
-            }
-
-            private Container item(int position) {
-                if (position < 0 || position >= getCount()) {
-                    return null;
-                }
-                return getItem(position);
-            }
-
-            @Override
-            public long getItemId(int position) {
-                Container item = item(position);
-                if (item == null) {
-                    return -1;
-                }
-                return item.mId;
-            }
-
-            @Override
-            public boolean areAllItemsEnabled() {
-                return false;
-            }
-
-            @Override
-            public boolean isEnabled(int position) {
-                Container item = item(position);
-                if (item == null) {
-                    return false;
-                }
-                return Container.OPTION_ENABLED == item.mEnabled;
-            }
-        }
-
-        private InvokeListBox(String[] array, int[] enabled, int[] selected) {
-            mMultiple = true;
-            mSelectedArray = selected;
-
-            int length = array.length;
-            mContainers = new Container[length];
-            for (int i = 0; i < length; i++) {
-                mContainers[i] = new Container();
-                mContainers[i].mString = array[i];
-                mContainers[i].mEnabled = enabled[i];
-                mContainers[i].mId = i;
-            }
-        }
-
-        private InvokeListBox(String[] array, int[] enabled, int selection) {
-            mSelection = selection;
-            mMultiple = false;
-
-            int length = array.length;
-            mContainers = new Container[length];
-            for (int i = 0; i < length; i++) {
-                mContainers[i] = new Container();
-                mContainers[i].mString = array[i];
-                mContainers[i].mEnabled = enabled[i];
-                mContainers[i].mId = i;
-            }
-        }
-
-        /*
-         * Whenever the data set changes due to filtering, this class ensures
-         * that the checked item remains checked.
-         */
-        private class SingleDataSetObserver extends DataSetObserver {
-            private long        mCheckedId;
-            private ListView    mListView;
-            private Adapter     mAdapter;
-
-            /*
-             * Create a new observer.
-             * @param id The ID of the item to keep checked.
-             * @param l ListView for getting and clearing the checked states
-             * @param a Adapter for getting the IDs
-             */
-            public SingleDataSetObserver(long id, ListView l, Adapter a) {
-                mCheckedId = id;
-                mListView = l;
-                mAdapter = a;
-            }
-
-            @Override
-            public void onChanged() {
-                // The filter may have changed which item is checked.  Find the
-                // item that the ListView thinks is checked.
-                int position = mListView.getCheckedItemPosition();
-                long id = mAdapter.getItemId(position);
-                if (mCheckedId != id) {
-                    // Clear the ListView's idea of the checked item, since
-                    // it is incorrect
-                    mListView.clearChoices();
-                    // Search for mCheckedId.  If it is in the filtered list,
-                    // mark it as checked
-                    int count = mAdapter.getCount();
-                    for (int i = 0; i < count; i++) {
-                        if (mAdapter.getItemId(i) == mCheckedId) {
-                            mListView.setItemChecked(i, true);
-                            break;
-                        }
-                    }
-                }
-            }
-        }
-
-        @Override
-        public void run() {
-            final ListView listView = (ListView) LayoutInflater.from(mContext)
-                    .inflate(com.android.internal.R.layout.select_dialog, null);
-            final MyArrayListAdapter adapter = new MyArrayListAdapter();
-            AlertDialog.Builder b = new AlertDialog.Builder(mContext)
-                    .setView(listView).setCancelable(true)
-                    .setInverseBackgroundForced(true);
-
-            if (mMultiple) {
-                b.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
-                    @Override
-                    public void onClick(DialogInterface dialog, int which) {
-                        mWebViewCore.sendMessage(
-                                EventHub.LISTBOX_CHOICES,
-                                adapter.getCount(), 0,
-                                listView.getCheckedItemPositions());
-                    }});
-                b.setNegativeButton(android.R.string.cancel,
-                        new DialogInterface.OnClickListener() {
-                    @Override
-                    public void onClick(DialogInterface dialog, int which) {
-                        mWebViewCore.sendMessage(
-                                EventHub.SINGLE_LISTBOX_CHOICE, -2, 0);
-                }});
-            }
-            mListBoxDialog = b.create();
-            listView.setAdapter(adapter);
-            listView.setFocusableInTouchMode(true);
-            // There is a bug (1250103) where the checks in a ListView with
-            // multiple items selected are associated with the positions, not
-            // the ids, so the items do not properly retain their checks when
-            // filtered.  Do not allow filtering on multiple lists until
-            // that bug is fixed.
-
-            listView.setTextFilterEnabled(!mMultiple);
-            if (mMultiple) {
-                listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
-                int length = mSelectedArray.length;
-                for (int i = 0; i < length; i++) {
-                    listView.setItemChecked(mSelectedArray[i], true);
-                }
-            } else {
-                listView.setOnItemClickListener(new OnItemClickListener() {
-                    @Override
-                    public void onItemClick(AdapterView<?> parent, View v,
-                            int position, long id) {
-                        // Rather than sending the message right away, send it
-                        // after the page regains focus.
-                        mListBoxMessage = Message.obtain(null,
-                                EventHub.SINGLE_LISTBOX_CHOICE, (int) id, 0);
-                        mListBoxDialog.dismiss();
-                        mListBoxDialog = null;
-                    }
-                });
-                if (mSelection != -1) {
-                    listView.setSelection(mSelection);
-                    listView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
-                    listView.setItemChecked(mSelection, true);
-                    DataSetObserver observer = new SingleDataSetObserver(
-                            adapter.getItemId(mSelection), listView, adapter);
-                    adapter.registerDataSetObserver(observer);
-                }
-            }
-            mListBoxDialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
-                @Override
-                public void onCancel(DialogInterface dialog) {
-                    mWebViewCore.sendMessage(
-                                EventHub.SINGLE_LISTBOX_CHOICE, -2, 0);
-                    mListBoxDialog = null;
-                }
-            });
-            mListBoxDialog.show();
-        }
-    }
-
-    private Message mListBoxMessage;
-
-    /*
-     * Request a dropdown menu for a listbox with multiple selection.
-     *
-     * @param array Labels for the listbox.
-     * @param enabledArray  State for each element in the list.  See static
-     *      integers in Container class.
-     * @param selectedArray Which positions are initally selected.
-     */
-    void requestListBox(String[] array, int[] enabledArray, int[]
-            selectedArray) {
-        mPrivateHandler.post(
-                new InvokeListBox(array, enabledArray, selectedArray));
-    }
-
-    /*
-     * Request a dropdown menu for a listbox with single selection or a single
-     * <select> element.
-     *
-     * @param array Labels for the listbox.
-     * @param enabledArray  State for each element in the list.  See static
-     *      integers in Container class.
-     * @param selection Which position is initally selected.
-     */
-    void requestListBox(String[] array, int[] enabledArray, int selection) {
-        mPrivateHandler.post(
-                new InvokeListBox(array, enabledArray, selection));
-    }
-
-    // called by JNI
-    private void sendMoveFocus(int frame, int node) {
-        mWebViewCore.sendMessage(EventHub.SET_MOVE_FOCUS,
-                new WebViewCore.CursorData(frame, node, 0, 0));
-    }
-
-    // called by JNI
-    private void sendMoveMouse(int frame, int node, int x, int y) {
-        mWebViewCore.sendMessage(EventHub.SET_MOVE_MOUSE,
-                new WebViewCore.CursorData(frame, node, x, y));
-    }
-
-    /*
-     * Send a mouse move event to the webcore thread.
-     *
-     * @param removeFocus Pass true to remove the WebTextView, if present.
-     * @param stopPaintingCaret Stop drawing the blinking caret if true.
-     * called by JNI
-     */
-    @SuppressWarnings("unused")
-    private void sendMoveMouseIfLatest(boolean removeFocus, boolean stopPaintingCaret) {
-        if (removeFocus) {
-            clearTextEntry();
-        }
-        mWebViewCore.sendMessage(EventHub.SET_MOVE_MOUSE_IF_LATEST,
-                stopPaintingCaret ? 1 : 0, 0,
-                cursorData());
-    }
-
-    /**
-     * Called by JNI to send a message to the webcore thread that the user
-     * touched the webpage.
-     * @param touchGeneration Generation number of the touch, to ignore touches
-     *      after a new one has been generated.
-     * @param frame Pointer to the frame holding the node that was touched.
-     * @param node Pointer to the node touched.
-     * @param x x-position of the touch.
-     * @param y y-position of the touch.
-     */
-    private void sendMotionUp(int touchGeneration,
-            int frame, int node, int x, int y) {
-        WebViewCore.TouchUpData touchUpData = new WebViewCore.TouchUpData();
-        touchUpData.mMoveGeneration = touchGeneration;
-        touchUpData.mFrame = frame;
-        touchUpData.mNode = node;
-        touchUpData.mX = x;
-        touchUpData.mY = y;
-        touchUpData.mNativeLayer = nativeScrollableLayer(
-                x, y, touchUpData.mNativeLayerRect, null);
-        mWebViewCore.sendMessage(EventHub.TOUCH_UP, touchUpData);
-    }
-
-
-    private int getScaledMaxXScroll() {
-        int width;
-        if (mHeightCanMeasure == false) {
-            width = getViewWidth() / 4;
-        } else {
-            Rect visRect = new Rect();
-            calcOurVisibleRect(visRect);
-            width = visRect.width() / 2;
-        }
-        // FIXME the divisor should be retrieved from somewhere
-        return viewToContentX(width);
-    }
-
-    private int getScaledMaxYScroll() {
-        int height;
-        if (mHeightCanMeasure == false) {
-            height = getViewHeight() / 4;
-        } else {
-            Rect visRect = new Rect();
-            calcOurVisibleRect(visRect);
-            height = visRect.height() / 2;
-        }
-        // FIXME the divisor should be retrieved from somewhere
-        // the closest thing today is hard-coded into ScrollView.java
-        // (from ScrollView.java, line 363)   int maxJump = height/2;
-        return Math.round(height * mZoomManager.getInvScale());
-    }
-
-    /**
-     * Called by JNI to invalidate view
-     */
-    private void viewInvalidate() {
-        invalidate();
-    }
-
-    /**
-     * Pass the key directly to the page.  This assumes that
-     * nativePageShouldHandleShiftAndArrows() returned true.
-     */
-    private void letPageHandleNavKey(int keyCode, long time, boolean down, int metaState) {
-        int keyEventAction;
-        int eventHubAction;
-        if (down) {
-            keyEventAction = KeyEvent.ACTION_DOWN;
-            eventHubAction = EventHub.KEY_DOWN;
-            playSoundEffect(keyCodeToSoundsEffect(keyCode));
-        } else {
-            keyEventAction = KeyEvent.ACTION_UP;
-            eventHubAction = EventHub.KEY_UP;
-        }
-
-        KeyEvent event = new KeyEvent(time, time, keyEventAction, keyCode,
-                1, (metaState & KeyEvent.META_SHIFT_ON)
-                | (metaState & KeyEvent.META_ALT_ON)
-                | (metaState & KeyEvent.META_SYM_ON)
-                , KeyCharacterMap.VIRTUAL_KEYBOARD, 0, 0);
-        mWebViewCore.sendMessage(eventHubAction, event);
-    }
-
-    // return true if the key was handled
-    private boolean navHandledKey(int keyCode, int count, boolean noScroll,
-            long time) {
-        if (mNativeClass == 0) {
-            return false;
-        }
-        mInitialHitTestResult = null;
-        mLastCursorTime = time;
-        mLastCursorBounds = cursorRingBounds();
-        boolean keyHandled
-                = nativeMoveCursor(keyCode, count, noScroll) == false;
-        if (DebugFlags.WEB_VIEW) {
-            Log.v(LOGTAG, "navHandledKey mLastCursorBounds=" + mLastCursorBounds
-                    + " mLastCursorTime=" + mLastCursorTime
-                    + " handled=" + keyHandled);
-        }
-        if (keyHandled == false) {
-            return keyHandled;
-        }
-        Rect contentCursorRingBounds = cursorRingBounds();
-        if (contentCursorRingBounds.isEmpty()) return keyHandled;
-        Rect viewCursorRingBounds = contentToViewRect(contentCursorRingBounds);
-        // set last touch so that context menu related functions will work
-        mLastTouchX = (viewCursorRingBounds.left + viewCursorRingBounds.right) / 2;
-        mLastTouchY = (viewCursorRingBounds.top + viewCursorRingBounds.bottom) / 2;
-        if (mHeightCanMeasure == false) {
-            return keyHandled;
-        }
-        Rect visRect = new Rect();
-        calcOurVisibleRect(visRect);
-        Rect outset = new Rect(visRect);
-        int maxXScroll = visRect.width() / 2;
-        int maxYScroll = visRect.height() / 2;
-        outset.inset(-maxXScroll, -maxYScroll);
-        if (Rect.intersects(outset, viewCursorRingBounds) == false) {
-            return keyHandled;
-        }
-        // FIXME: Necessary because ScrollView/ListView do not scroll left/right
-        int maxH = Math.min(viewCursorRingBounds.right - visRect.right,
-                maxXScroll);
-        if (maxH > 0) {
-            pinScrollBy(maxH, 0, true, 0);
-        } else {
-            maxH = Math.max(viewCursorRingBounds.left - visRect.left,
-                    -maxXScroll);
-            if (maxH < 0) {
-                pinScrollBy(maxH, 0, true, 0);
-            }
-        }
-        if (mLastCursorBounds.isEmpty()) return keyHandled;
-        if (mLastCursorBounds.equals(contentCursorRingBounds)) {
-            return keyHandled;
-        }
-        if (DebugFlags.WEB_VIEW) {
-            Log.v(LOGTAG, "navHandledKey contentCursorRingBounds="
-                    + contentCursorRingBounds);
-        }
-        requestRectangleOnScreen(viewCursorRingBounds);
-        return keyHandled;
-    }
-
-    /**
-     * @return Whether accessibility script has been injected.
-     */
-    private boolean accessibilityScriptInjected() {
-        // TODO: Maybe the injected script should announce its presence in
-        // the page meta-tag so the nativePageShouldHandleShiftAndArrows
-        // will check that as one of the conditions it looks for
-        return mAccessibilityScriptInjected;
-    }
-
-    /**
-     * Set the background color. It's white by default. Pass
-     * zero to make the view transparent.
-     * @param color   the ARGB color described by Color.java
-     */
-    @Override
-    public void setBackgroundColor(int color) {
-        mBackgroundColor = color;
-        mWebViewCore.sendMessage(EventHub.SET_BACKGROUND_COLOR, color);
+        return mProvider.zoomOut();
     }
 
     /**
@@ -10239,70 +1534,165 @@
     @Deprecated
     public void debugDump() {
         checkThread();
-        nativeDebugDump();
-        mWebViewCore.sendMessage(EventHub.DUMP_NAVTREE);
+        mProvider.debugDump();
     }
 
+    //-------------------------------------------------------------------------
+    // Interface for WebView providers
+    //-------------------------------------------------------------------------
+
     /**
-     * Draw the HTML page into the specified canvas. This call ignores any
-     * view-specific zoom, scroll offset, or other changes. It does not draw
-     * any view-specific chrome, such as progress or URL bars.
+     * Used by providers to obtain the underlying implementation, e.g. when the appliction
+     * responds to WebViewClient.onCreateWindow() request.
      *
-     * @hide only needs to be accessible to Browser and testing
+     * @hide WebViewProvider is not public API.
      */
-    public void drawPage(Canvas canvas) {
-        calcOurContentVisibleRectF(mVisibleContentRect);
-        nativeDraw(canvas, mVisibleContentRect, 0, 0, false);
+    public WebViewProvider getWebViewProvider() {
+        return mProvider;
     }
 
     /**
-     * Enable the communication b/t the webView and VideoViewProxy
-     *
-     * @hide only used by the Browser
+     * Callback interface, allows the provider implementation to access non-public methods
+     * and fields, and make super-class calls in this WebView instance.
+     * @hide Only for use by WebViewProvider implementations
      */
-    public void setHTML5VideoViewProxy(HTML5VideoViewProxy proxy) {
-        mHTML5VideoViewProxy = proxy;
+    public class PrivateAccess {
+        // ---- Access to super-class methods ----
+        public int super_getScrollBarStyle() {
+            return WebView.super.getScrollBarStyle();
+        }
+
+        public void super_scrollTo(int scrollX, int scrollY) {
+            WebView.super.scrollTo(scrollX, scrollY);
+        }
+
+        public void super_computeScroll() {
+            WebView.super.computeScroll();
+        }
+
+        public boolean super_performLongClick() {
+            return WebView.super.performLongClick();
+        }
+
+        public boolean super_setFrame(int left, int top, int right, int bottom) {
+            return WebView.super.setFrame(left, top, right, bottom);
+        }
+
+        public boolean super_dispatchKeyEvent(KeyEvent event) {
+            return WebView.super.dispatchKeyEvent(event);
+        }
+
+        public boolean super_onGenericMotionEvent(MotionEvent event) {
+            return WebView.super.onGenericMotionEvent(event);
+        }
+
+        public boolean super_requestFocus(int direction, Rect previouslyFocusedRect) {
+            return WebView.super.requestFocus(direction, previouslyFocusedRect);
+        }
+
+        public void super_setLayoutParams(ViewGroup.LayoutParams params) {
+            WebView.super.setLayoutParams(params);
+        }
+
+        // ---- Access to non-public methods ----
+        public void overScrollBy(int deltaX, int deltaY,
+                int scrollX, int scrollY,
+                int scrollRangeX, int scrollRangeY,
+                int maxOverScrollX, int maxOverScrollY,
+                boolean isTouchEvent) {
+            WebView.this.overScrollBy(deltaX, deltaY, scrollX, scrollY, scrollRangeX, scrollRangeY,
+                    maxOverScrollX, maxOverScrollY, isTouchEvent);
+        }
+
+        public void awakenScrollBars(int duration) {
+            WebView.this.awakenScrollBars(duration);
+        }
+
+        public void awakenScrollBars(int duration, boolean invalidate) {
+            WebView.this.awakenScrollBars(duration, invalidate);
+        }
+
+        public float getVerticalScrollFactor() {
+            return WebView.this.getVerticalScrollFactor();
+        }
+
+        public float getHorizontalScrollFactor() {
+            return WebView.this.getHorizontalScrollFactor();
+        }
+
+        public void setMeasuredDimension(int measuredWidth, int measuredHeight) {
+            WebView.this.setMeasuredDimension(measuredWidth, measuredHeight);
+        }
+
+        public void onScrollChanged(int l, int t, int oldl, int oldt) {
+            WebView.this.onScrollChanged(l, t, oldl, oldt);
+        }
+
+        public int getHorizontalScrollbarHeight() {
+            return WebView.this.getHorizontalScrollbarHeight();
+        }
+
+        // ---- Access to (non-public) fields ----
+        /** Raw setter for the scroll X value, without invoking onScrollChanged handlers etc. */
+        public void setScrollXRaw(int scrollX) {
+            WebView.this.mScrollX = scrollX;
+        }
+
+        /** Raw setter for the scroll Y value, without invoking onScrollChanged handlers etc. */
+        public void setScrollYRaw(int scrollY) {
+            WebView.this.mScrollY = scrollY;
+        }
+
     }
 
-    /**
-     * Set the time to wait between passing touches to WebCore. See also the
-     * TOUCH_SENT_INTERVAL member for further discussion.
-     *
-     * @hide This is only used by the DRT test application.
-     */
-    public void setTouchInterval(int interval) {
-        mCurrentTouchInterval = interval;
+    //-------------------------------------------------------------------------
+    // Private internal stuff
+    //-------------------------------------------------------------------------
+
+    // Cache the factory both for efficiency, and ensure any one process gets all webviews from the
+    // same provider.
+    private static WebViewFactoryProvider sProviderFactory;
+
+    private WebViewProvider mProvider;
+
+    private void ensureProviderCreated() {
+        checkThread();
+        if (mProvider == null) {
+            if (DEBUG) Log.v(LOGTAG, "instantiating webview provider instance");
+            // As this can get called during the base class constructor chain, pass the minimum
+            // number of dependencies here; the rest are deferred to init().
+            mProvider = getFactory().createWebView(this, new PrivateAccess());
+        }
     }
 
-    /**
-     * Copy text into the clipboard. This is called indirectly from
-     * WebViewCore.
-     * @param text The text to put into the clipboard.
-     */
-    private void copyToClipboard(String text) {
-        ClipboardManager cm = (ClipboardManager)getContext()
-                .getSystemService(Context.CLIPBOARD_SERVICE);
-        ClipData clip = ClipData.newPlainText(getTitle(), text);
-        cm.setPrimaryClip(clip);
+    private static synchronized WebViewFactoryProvider getFactory() {
+        // For now the main purpose of this function (and the factory abstration) is to keep
+        // us honest and minimize usage of WebViewClassic internals when binding the proxy.
+        checkThread();
+        if (sProviderFactory != null) return sProviderFactory;
+
+        sProviderFactory = getFactoryByName(DEFAULT_WEB_VIEW_FACTORY);
+        if (sProviderFactory == null) {
+            if (DEBUG) Log.v (LOGTAG, "Falling back to explicit linkage");
+            sProviderFactory = new WebViewClassic.Factory();
+        }
+        return sProviderFactory;
     }
 
-    /**
-     *  Update our cache with updatedText.
-     *  @param updatedText  The new text to put in our cache.
-     *  @hide
-     */
-    protected void updateCachedTextfield(String updatedText) {
-        // Also place our generation number so that when we look at the cache
-        // we recognize that it is up to date.
-        nativeUpdateCachedTextfield(updatedText, mTextGeneration);
-    }
-
-    /*package*/ void autoFillForm(int autoFillQueryId) {
-        mWebViewCore.sendMessage(EventHub.AUTOFILL_FORM, autoFillQueryId, /* unused */0);
-    }
-
-    /* package */ ViewManager getViewManager() {
-        return mViewManager;
+    private static WebViewFactoryProvider getFactoryByName(String providerName) {
+        try {
+            if (DEBUG) Log.v(LOGTAG, "attempt to load class " + providerName);
+            Class<?> c = Class.forName(providerName);
+            if (DEBUG) Log.v(LOGTAG, "instantiating factory");
+            return (WebViewFactoryProvider) c.newInstance();
+        } catch (ClassNotFoundException e) {
+            Log.e(LOGTAG, "error loading " + providerName, e);
+        } catch (IllegalAccessException e) {
+            Log.e(LOGTAG, "error loading " + providerName, e);
+        } catch (InstantiationException e) {
+            Log.e(LOGTAG, "error loading " + providerName, e);
+        }
+        return null;
     }
 
     private static void checkThread() {
@@ -10317,234 +1707,252 @@
         }
     }
 
-    /** @hide send content invalidate */
-    protected void contentInvalidateAll() {
-        if (mWebViewCore != null && !mBlockWebkitViewMessages) {
-            mWebViewCore.sendMessage(EventHub.CONTENT_INVALIDATE_ALL);
-        }
+    //-------------------------------------------------------------------------
+    // Override View methods
+    //-------------------------------------------------------------------------
+
+    // TODO: Add a test that enumerates all methods in ViewDelegte & ScrollDelegate, and ensures
+    // there's a corresponding override (or better, caller) for each of them in here.
+
+    @Override
+    protected void onAttachedToWindow() {
+        super.onAttachedToWindow();
+        mProvider.getViewDelegate().onAttachedToWindow();
     }
 
-    /** @hide discard all textures from tiles */
-    protected void discardAllTextures() {
-        nativeDiscardAllTextures();
+    @Override
+    protected void onDetachedFromWindow() {
+        mProvider.getViewDelegate().onDetachedFromWindow();
+        super.onDetachedFromWindow();
     }
 
-    /**
-     * Begin collecting per-tile profiling data
-     *
-     * @hide only used by profiling tests
-     */
-    public void tileProfilingStart() {
-        nativeTileProfilingStart();
-    }
-    /**
-     * Return per-tile profiling data
-     *
-     * @hide only used by profiling tests
-     */
-    public float tileProfilingStop() {
-        return nativeTileProfilingStop();
+    @Override
+    public void setLayoutParams(ViewGroup.LayoutParams params) {
+        mProvider.getViewDelegate().setLayoutParams(params);
     }
 
-    /** @hide only used by profiling tests */
-    public void tileProfilingClear() {
-        nativeTileProfilingClear();
-    }
-    /** @hide only used by profiling tests */
-    public int tileProfilingNumFrames() {
-        return nativeTileProfilingNumFrames();
-    }
-    /** @hide only used by profiling tests */
-    public int tileProfilingNumTilesInFrame(int frame) {
-        return nativeTileProfilingNumTilesInFrame(frame);
-    }
-    /** @hide only used by profiling tests */
-    public int tileProfilingGetInt(int frame, int tile, String key) {
-        return nativeTileProfilingGetInt(frame, tile, key);
-    }
-    /** @hide only used by profiling tests */
-    public float tileProfilingGetFloat(int frame, int tile, String key) {
-        return nativeTileProfilingGetFloat(frame, tile, key);
+    @Override
+    public void setOverScrollMode(int mode) {
+        super.setOverScrollMode(mode);
+        // This method may called in the constructor chain, before the WebView provider is
+        // created. (Fortunately, this is the only method we override that can get called by
+        // any of the base class constructors).
+        ensureProviderCreated();
+        mProvider.getViewDelegate().setOverScrollMode(mode);
     }
 
-    /**
-     * Checks the focused content for an editable text field. This can be
-     * text input or ContentEditable.
-     * @return true if the focused item is an editable text field.
-     */
-    boolean focusCandidateIsEditableText() {
-        boolean isEditable = false;
-        // TODO: reverse sDisableNavcache so that its name is positive
-        boolean isNavcacheEnabled = !sDisableNavcache;
-        if (isNavcacheEnabled) {
-            isEditable = nativeFocusCandidateIsEditableText(mNativeClass);
-        } else if (mFocusedNode != null) {
-            isEditable = mFocusedNode.mEditable;
-        }
-        return isEditable;
+    @Override
+    public void setScrollBarStyle(int style) {
+        mProvider.getViewDelegate().setScrollBarStyle(style);
+        super.setScrollBarStyle(style);
     }
 
-    // TODO: Remove this
-    Rect cursorRingBounds() {
-        if (sDisableNavcache) {
-            return new Rect();
-        }
-        return nativeGetCursorRingBounds();
+    @Override
+    protected int computeHorizontalScrollRange() {
+        return mProvider.getScrollDelegate().computeHorizontalScrollRange();
     }
 
-    private native int nativeCacheHitFramePointer();
-    private native boolean  nativeCacheHitIsPlugin();
-    private native Rect nativeCacheHitNodeBounds();
-    private native int nativeCacheHitNodePointer();
-    /* package */ native void nativeClearCursor();
-    private native void     nativeCreate(int ptr, String drawableDir, boolean isHighEndGfx);
-    private native int      nativeCursorFramePointer();
-    private native Rect     nativeCursorNodeBounds();
-    private native int nativeCursorNodePointer();
-    private native boolean  nativeCursorIntersects(Rect visibleRect);
-    private native boolean  nativeCursorIsAnchor();
-    private native boolean  nativeCursorIsTextInput();
-    private native Point    nativeCursorPosition();
-    private native String   nativeCursorText();
-    /**
-     * Returns true if the native cursor node says it wants to handle key events
-     * (ala plugins). This can only be called if mNativeClass is non-zero!
-     */
-    private native boolean  nativeCursorWantsKeyEvents();
-    private native void     nativeDebugDump();
-    private native void     nativeDestroy();
+    @Override
+    protected int computeHorizontalScrollOffset() {
+        return mProvider.getScrollDelegate().computeHorizontalScrollOffset();
+    }
 
-    /**
-     * Draw the picture set with a background color and extra. If
-     * "splitIfNeeded" is true and the return value is not 0, the return value
-     * MUST be passed to WebViewCore with SPLIT_PICTURE_SET message so that the
-     * native allocation can be freed.
-     */
-    private native int nativeDraw(Canvas canvas, RectF visibleRect,
-            int color, int extra, boolean splitIfNeeded);
-    private native void     nativeDumpDisplayTree(String urlOrNull);
-    private native boolean  nativeEvaluateLayersAnimations(int nativeInstance);
-    private native int      nativeGetDrawGLFunction(int nativeInstance, Rect rect,
-            Rect viewRect, RectF visibleRect, float scale, int extras);
-    private native void     nativeUpdateDrawGLFunction(Rect rect, Rect viewRect,
-            RectF visibleRect, float scale);
-    private native void     nativeExtendSelection(int x, int y);
-    /* package */ native int      nativeFocusCandidateFramePointer();
-    /* package */ native boolean  nativeFocusCandidateHasNextTextfield();
-    /* package */ native boolean  nativeFocusCandidateIsPassword();
-    private native boolean  nativeFocusCandidateIsRtlText();
-    private native boolean  nativeFocusCandidateIsTextInput();
-    private native boolean nativeFocusCandidateIsEditableText(int nativeClass);
-    /* package */ native int      nativeFocusCandidateMaxLength();
-    /* package */ native boolean  nativeFocusCandidateIsAutoComplete();
-    /* package */ native boolean  nativeFocusCandidateIsSpellcheck();
-    /* package */ native String   nativeFocusCandidateName();
-    private native Rect     nativeFocusCandidateNodeBounds();
-    /**
-     * @return A Rect with left, top, right, bottom set to the corresponding
-     * padding values in the focus candidate, if it is a textfield/textarea with
-     * a style.  Otherwise return null.  This is not actually a rectangle; Rect
-     * is being used to pass four integers.
-     */
-    private native Rect     nativeFocusCandidatePaddingRect();
-    /* package */ native int      nativeFocusCandidatePointer();
-    private native String   nativeFocusCandidateText();
-    /* package */ native float    nativeFocusCandidateTextSize();
-    /* package */ native int nativeFocusCandidateLineHeight();
-    /**
-     * Returns an integer corresponding to WebView.cpp::type.
-     * See WebTextView.setType()
-     */
-    private native int      nativeFocusCandidateType();
-    private native int      nativeFocusCandidateLayerId();
-    private native boolean  nativeFocusIsPlugin();
-    private native Rect     nativeFocusNodeBounds();
-    /* package */ native int nativeFocusNodePointer();
-    private native Rect     nativeGetCursorRingBounds();
-    private native String   nativeGetSelection();
-    private native boolean  nativeHasCursorNode();
-    private native boolean  nativeHasFocusNode();
-    private native void     nativeHideCursor();
-    private native boolean  nativeHitSelection(int x, int y);
-    private native String   nativeImageURI(int x, int y);
-    private native Rect     nativeLayerBounds(int layer);
-    /* package */ native boolean nativeMoveCursorToNextTextInput();
-    // return true if the page has been scrolled
-    private native boolean  nativeMotionUp(int x, int y, int slop);
-    // returns false if it handled the key
-    private native boolean  nativeMoveCursor(int keyCode, int count,
-            boolean noScroll);
-    private native int      nativeMoveGeneration();
-    /**
-     * @return true if the page should get the shift and arrow keys, rather
-     * than select text/navigation.
-     *
-     * If the focus is a plugin, or if the focus and cursor match and are
-     * a contentEditable element, then the page should handle these keys.
-     */
-    private native boolean  nativePageShouldHandleShiftAndArrows();
-    private native boolean  nativePointInNavCache(int x, int y, int slop);
-    private native void     nativeSelectBestAt(Rect rect);
-    private native void     nativeSelectAt(int x, int y);
-    private native void     nativeSetExtendSelection();
-    private native void     nativeSetFindIsUp(boolean isUp);
-    private native void     nativeSetHeightCanMeasure(boolean measure);
-    private native boolean  nativeSetBaseLayer(int nativeInstance,
-            int layer, Region invalRegion,
-            boolean showVisualIndicator, boolean isPictureAfterFirstLayout);
-    private native int      nativeGetBaseLayer();
-    private native void     nativeShowCursorTimed();
-    private native void     nativeReplaceBaseContent(int content);
-    private native void     nativeCopyBaseContentToPicture(Picture pict);
-    private native boolean  nativeHasContent();
-    private native void     nativeSetSelectionPointer(int nativeInstance,
-            boolean set, float scale, int x, int y);
-    private native boolean  nativeStartSelection(int x, int y);
-    private native void     nativeStopGL();
-    private native Rect     nativeSubtractLayers(Rect content);
-    private native int      nativeTextGeneration();
-    private native void     nativeDiscardAllTextures();
-    private native void     nativeTileProfilingStart();
-    private native float    nativeTileProfilingStop();
-    private native void     nativeTileProfilingClear();
-    private native int      nativeTileProfilingNumFrames();
-    private native int      nativeTileProfilingNumTilesInFrame(int frame);
-    private native int      nativeTileProfilingGetInt(int frame, int tile, String key);
-    private native float    nativeTileProfilingGetFloat(int frame, int tile, String key);
-    // Never call this version except by updateCachedTextfield(String) -
-    // we always want to pass in our generation number.
-    private native void     nativeUpdateCachedTextfield(String updatedText,
-            int generation);
-    private native boolean  nativeWordSelection(int x, int y);
-    // return NO_LEFTEDGE means failure.
-    static final int NO_LEFTEDGE = -1;
-    native int nativeGetBlockLeftEdge(int x, int y, float scale);
+    @Override
+    protected int computeVerticalScrollRange() {
+        return mProvider.getScrollDelegate().computeVerticalScrollRange();
+    }
 
-    private native void     nativeUseHardwareAccelSkia(boolean enabled);
+    @Override
+    protected int computeVerticalScrollOffset() {
+        return mProvider.getScrollDelegate().computeVerticalScrollOffset();
+    }
 
-    // Returns a pointer to the scrollable LayerAndroid at the given point.
-    private native int      nativeScrollableLayer(int x, int y, Rect scrollRect,
-            Rect scrollBounds);
-    /**
-     * Scroll the specified layer.
-     * @param layer Id of the layer to scroll, as determined by nativeScrollableLayer.
-     * @param newX Destination x position to which to scroll.
-     * @param newY Destination y position to which to scroll.
-     * @return True if the layer is successfully scrolled.
-     */
-    private native boolean  nativeScrollLayer(int layer, int newX, int newY);
-    private native void     nativeSetIsScrolling(boolean isScrolling);
-    private native int      nativeGetBackgroundColor();
-    native boolean  nativeSetProperty(String key, String value);
-    native String   nativeGetProperty(String key);
-    /**
-     * See {@link ComponentCallbacks2} for the trim levels and descriptions
-     */
-    private static native void     nativeOnTrimMemory(int level);
-    private static native void nativeSetPauseDrawing(int instance, boolean pause);
-    private static native boolean nativeDisableNavcache();
-    private static native void nativeSetTextSelection(int instance, int selection);
-    private static native int nativeGetHandleLayerId(int instance, int handle,
-            Rect cursorLocation);
-    private static native boolean nativeIsBaseFirst(int instance);
+    @Override
+    protected int computeVerticalScrollExtent() {
+        return mProvider.getScrollDelegate().computeVerticalScrollExtent();
+    }
+
+    @Override
+    public void computeScroll() {
+        mProvider.getScrollDelegate().computeScroll();
+    }
+
+    @Override
+    public boolean onHoverEvent(MotionEvent event) {
+        return mProvider.getViewDelegate().onHoverEvent(event);
+    }
+
+    @Override
+    public boolean onTouchEvent(MotionEvent event) {
+        return mProvider.getViewDelegate().onTouchEvent(event);
+    }
+
+    @Override
+    public boolean onGenericMotionEvent(MotionEvent event) {
+        return mProvider.getViewDelegate().onGenericMotionEvent(event);
+    }
+
+    @Override
+    public boolean onTrackballEvent(MotionEvent event) {
+        return mProvider.getViewDelegate().onTrackballEvent(event);
+    }
+
+    @Override
+    public boolean onKeyDown(int keyCode, KeyEvent event) {
+        return mProvider.getViewDelegate().onKeyDown(keyCode, event);
+    }
+
+    @Override
+    public boolean onKeyUp(int keyCode, KeyEvent event) {
+        return mProvider.getViewDelegate().onKeyUp(keyCode, event);
+    }
+
+    @Override
+    public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) {
+        return mProvider.getViewDelegate().onKeyMultiple(keyCode, repeatCount, event);
+    }
+
+    /*
+    TODO: These are not currently implemented in WebViewClassic, but it seems inconsistent not
+    to be delegating them too.
+
+    @Override
+    public boolean onKeyPreIme(int keyCode, KeyEvent event) {
+        return mProvider.getViewDelegate().onKeyPreIme(keyCode, event);
+    }
+    @Override
+    public boolean onKeyLongPress(int keyCode, KeyEvent event) {
+        return mProvider.getViewDelegate().onKeyLongPress(keyCode, event);
+    }
+    @Override
+    public boolean onKeyShortcut(int keyCode, KeyEvent event) {
+        return mProvider.getViewDelegate().onKeyShortcut(keyCode, event);
+    }
+    */
+
+    @Deprecated
+    @Override
+    public boolean shouldDelayChildPressedState() {
+        return mProvider.getViewDelegate().shouldDelayChildPressedState();
+    }
+
+    @Override
+    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
+        super.onInitializeAccessibilityNodeInfo(info);
+        mProvider.getViewDelegate().onInitializeAccessibilityNodeInfo(info);
+    }
+
+    @Override
+    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
+        super.onInitializeAccessibilityEvent(event);
+        mProvider.getViewDelegate().onInitializeAccessibilityEvent(event);
+    }
+
+    /** @hide */
+    @Override
+    protected void onDrawVerticalScrollBar(Canvas canvas, Drawable scrollBar,
+            int l, int t, int r, int b) {
+        mProvider.getViewDelegate().onDrawVerticalScrollBar(canvas, scrollBar, l, t, r, b);
+    }
+
+    @Override
+    protected void onOverScrolled(int scrollX, int scrollY, boolean clampedX, boolean clampedY) {
+        mProvider.getViewDelegate().onOverScrolled(scrollX, scrollY, clampedX, clampedY);
+    }
+
+    @Override
+    protected void onWindowVisibilityChanged(int visibility) {
+        super.onWindowVisibilityChanged(visibility);
+        mProvider.getViewDelegate().onWindowVisibilityChanged(visibility);
+    }
+
+    @Override
+    protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
+        // Not using short-circuit OR: provider does suppress base-class call.
+        return mProvider.getViewDelegate().drawChild(canvas, child, drawingTime) |
+                super.drawChild(canvas, child, drawingTime);
+    }
+
+    @Override
+    protected void onDraw(Canvas canvas) {
+        mProvider.getViewDelegate().onDraw(canvas);
+    }
+
+    @Override
+    public boolean performLongClick() {
+        return mProvider.getViewDelegate().performLongClick();
+    }
+
+    @Override
+    protected void onConfigurationChanged(Configuration newConfig) {
+        mProvider.getViewDelegate().onConfigurationChanged(newConfig);
+    }
+
+    @Override
+    public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
+        return mProvider.getViewDelegate().onCreateInputConnection(outAttrs);
+    }
+
+    @Override
+    protected void onVisibilityChanged(View changedView, int visibility) {
+        super.onVisibilityChanged(changedView, visibility);
+        mProvider.getViewDelegate().onVisibilityChanged(changedView, visibility);
+    }
+
+    @Override
+    public void onWindowFocusChanged(boolean hasWindowFocus) {
+        mProvider.getViewDelegate().onWindowFocusChanged(hasWindowFocus);
+        super.onWindowFocusChanged(hasWindowFocus);
+    }
+
+    @Override
+    protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) {
+        mProvider.getViewDelegate().onFocusChanged(focused, direction, previouslyFocusedRect);
+        super.onFocusChanged(focused, direction, previouslyFocusedRect);
+    }
+
+    /** @hide */
+    @Override
+    protected boolean setFrame(int left, int top, int right, int bottom) {
+        return mProvider.getViewDelegate().setFrame(left, top, right, bottom);
+    }
+
+    @Override
+    protected void onSizeChanged(int w, int h, int ow, int oh) {
+        super.onSizeChanged(w, h, ow, oh);
+        mProvider.getViewDelegate().onSizeChanged(w, h, ow, oh);
+    }
+
+    @Override
+    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
+        super.onScrollChanged(l, t, oldl, oldt);
+        mProvider.getViewDelegate().onScrollChanged(l, t, oldl, oldt);
+    }
+
+    @Override
+    public boolean dispatchKeyEvent(KeyEvent event) {
+        return mProvider.getViewDelegate().dispatchKeyEvent(event);
+    }
+
+    @Override
+    public boolean requestFocus(int direction, Rect previouslyFocusedRect) {
+        return mProvider.getViewDelegate().requestFocus(direction, previouslyFocusedRect);
+    }
+
+    @Deprecated
+    @Override
+    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+        mProvider.getViewDelegate().onMeasure(widthMeasureSpec, heightMeasureSpec);
+    }
+
+    @Override
+    public boolean requestChildRectangleOnScreen(View child, Rect rect, boolean immediate) {
+        return mProvider.getViewDelegate().requestChildRectangleOnScreen(child, rect, immediate);
+    }
+
+    @Override
+    public void setBackgroundColor(int color) {
+        mProvider.getViewDelegate().setBackgroundColor(color);
+    }
 }
diff --git a/core/java/android/webkit/WebViewClassic.java b/core/java/android/webkit/WebViewClassic.java
new file mode 100644
index 0000000..72aed4b
--- /dev/null
+++ b/core/java/android/webkit/WebViewClassic.java
@@ -0,0 +1,9173 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.webkit;
+
+import android.animation.ObjectAnimator;
+import android.annotation.Widget;
+import android.app.ActivityManager;
+import android.app.AlertDialog;
+import android.content.BroadcastReceiver;
+import android.content.ClipData;
+import android.content.ClipboardManager;
+import android.content.ComponentCallbacks2;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.DialogInterface.OnCancelListener;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.PackageManager;
+import android.content.res.Configuration;
+import android.database.DataSetObserver;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.BitmapShader;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.ColorFilter;
+import android.graphics.DrawFilter;
+import android.graphics.Paint;
+import android.graphics.PaintFlagsDrawFilter;
+import android.graphics.Picture;
+import android.graphics.Point;
+import android.graphics.Rect;
+import android.graphics.RectF;
+import android.graphics.Region;
+import android.graphics.RegionIterator;
+import android.graphics.Shader;
+import android.graphics.drawable.Drawable;
+import android.net.Proxy;
+import android.net.ProxyProperties;
+import android.net.Uri;
+import android.net.http.SslCertificate;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.os.StrictMode;
+import android.os.SystemClock;
+import android.provider.Settings;
+import android.security.KeyChain;
+import android.speech.tts.TextToSpeech;
+import android.text.Editable;
+import android.text.InputType;
+import android.text.Selection;
+import android.text.TextUtils;
+import android.util.DisplayMetrics;
+import android.util.EventLog;
+import android.util.Log;
+import android.view.Display;
+import android.view.Gravity;
+import android.view.HapticFeedbackConstants;
+import android.view.HardwareCanvas;
+import android.view.InputDevice;
+import android.view.KeyCharacterMap;
+import android.view.KeyEvent;
+import android.view.LayoutInflater;
+import android.view.MotionEvent;
+import android.view.ScaleGestureDetector;
+import android.view.SoundEffectConstants;
+import android.view.VelocityTracker;
+import android.view.View;
+import android.view.View.MeasureSpec;
+import android.view.ViewConfiguration;
+import android.view.ViewGroup;
+import android.view.ViewParent;
+import android.view.ViewTreeObserver;
+import android.view.WindowManager;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityManager;
+import android.view.accessibility.AccessibilityNodeInfo;
+import android.view.inputmethod.BaseInputConnection;
+import android.view.inputmethod.EditorInfo;
+import android.view.inputmethod.InputConnection;
+import android.view.inputmethod.InputMethodManager;
+import android.webkit.WebView.HitTestResult;
+import android.webkit.WebView.PictureListener;
+import android.webkit.WebViewCore.DrawData;
+import android.webkit.WebViewCore.EventHub;
+import android.webkit.WebViewCore.TextFieldInitData;
+import android.webkit.WebViewCore.TouchEventData;
+import android.webkit.WebViewCore.TouchHighlightData;
+import android.webkit.WebViewCore.WebKitHitTest;
+import android.widget.AbsoluteLayout;
+import android.widget.Adapter;
+import android.widget.AdapterView;
+import android.widget.AdapterView.OnItemClickListener;
+import android.widget.ArrayAdapter;
+import android.widget.CheckedTextView;
+import android.widget.LinearLayout;
+import android.widget.ListView;
+import android.widget.OverScroller;
+import android.widget.PopupWindow;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import junit.framework.Assert;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.URLDecoder;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.Vector;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * <p>A View that displays web pages. This class is the basis upon which you
+ * can roll your own web browser or simply display some online content within your Activity.
+ * It uses the WebKit rendering engine to display
+ * web pages and includes methods to navigate forward and backward
+ * through a history, zoom in and out, perform text searches and more.</p>
+ * <p>To enable the built-in zoom, set
+ * {@link #getSettings() WebSettings}.{@link WebSettings#setBuiltInZoomControls(boolean)}
+ * (introduced in API version 3).
+ * <p>Note that, in order for your Activity to access the Internet and load web pages
+ * in a WebView, you must add the {@code INTERNET} permissions to your
+ * Android Manifest file:</p>
+ * <pre>&lt;uses-permission android:name="android.permission.INTERNET" /></pre>
+ *
+ * <p>This must be a child of the <a
+ * href="{@docRoot}guide/topics/manifest/manifest-element.html">{@code <manifest>}</a>
+ * element.</p>
+ *
+ * <p>See the <a href="{@docRoot}resources/tutorials/views/hello-webview.html">Web View
+ * tutorial</a>.</p>
+ *
+ * <h3>Basic usage</h3>
+ *
+ * <p>By default, a WebView provides no browser-like widgets, does not
+ * enable JavaScript and web page errors are ignored. If your goal is only
+ * to display some HTML as a part of your UI, this is probably fine;
+ * the user won't need to interact with the web page beyond reading
+ * it, and the web page won't need to interact with the user. If you
+ * actually want a full-blown web browser, then you probably want to
+ * invoke the Browser application with a URL Intent rather than show it
+ * with a WebView. For example:
+ * <pre>
+ * Uri uri = Uri.parse("http://www.example.com");
+ * Intent intent = new Intent(Intent.ACTION_VIEW, uri);
+ * startActivity(intent);
+ * </pre>
+ * <p>See {@link android.content.Intent} for more information.</p>
+ *
+ * <p>To provide a WebView in your own Activity, include a {@code <WebView>} in your layout,
+ * or set the entire Activity window as a WebView during {@link
+ * android.app.Activity#onCreate(Bundle) onCreate()}:</p>
+ * <pre class="prettyprint">
+ * WebView webview = new WebView(this);
+ * setContentView(webview);
+ * </pre>
+ *
+ * <p>Then load the desired web page:</p>
+ * <pre>
+ * // Simplest usage: note that an exception will NOT be thrown
+ * // if there is an error loading this page (see below).
+ * webview.loadUrl("http://slashdot.org/");
+ *
+ * // OR, you can also load from an HTML string:
+ * String summary = "&lt;html>&lt;body>You scored &lt;b>192&lt;/b> points.&lt;/body>&lt;/html>";
+ * webview.loadData(summary, "text/html", null);
+ * // ... although note that there are restrictions on what this HTML can do.
+ * // See the JavaDocs for {@link #loadData(String,String,String) loadData()} and {@link
+ * #loadDataWithBaseURL(String,String,String,String,String) loadDataWithBaseURL()} for more info.
+ * </pre>
+ *
+ * <p>A WebView has several customization points where you can add your
+ * own behavior. These are:</p>
+ *
+ * <ul>
+ *   <li>Creating and setting a {@link android.webkit.WebChromeClient} subclass.
+ *       This class is called when something that might impact a
+ *       browser UI happens, for instance, progress updates and
+ *       JavaScript alerts are sent here (see <a
+ * href="{@docRoot}guide/developing/debug-tasks.html#DebuggingWebPages">Debugging Tasks</a>).
+ *   </li>
+ *   <li>Creating and setting a {@link android.webkit.WebViewClient} subclass.
+ *       It will be called when things happen that impact the
+ *       rendering of the content, eg, errors or form submissions. You
+ *       can also intercept URL loading here (via {@link
+ * android.webkit.WebViewClient#shouldOverrideUrlLoading(WebView,String)
+ * shouldOverrideUrlLoading()}).</li>
+ *   <li>Modifying the {@link android.webkit.WebSettings}, such as
+ * enabling JavaScript with {@link android.webkit.WebSettings#setJavaScriptEnabled(boolean)
+ * setJavaScriptEnabled()}. </li>
+ *   <li>Injecting Java objects into the WebView using the
+ *       {@link android.webkit.WebView#addJavascriptInterface} method. This
+ *       method allows you to inject Java objects into a page's JavaScript
+ *       context, so that they can be accessed by JavaScript in the page.</li>
+ * </ul>
+ *
+ * <p>Here's a more complicated example, showing error handling,
+ *    settings, and progress notification:</p>
+ *
+ * <pre class="prettyprint">
+ * // Let's display the progress in the activity title bar, like the
+ * // browser app does.
+ * getWindow().requestFeature(Window.FEATURE_PROGRESS);
+ *
+ * webview.getSettings().setJavaScriptEnabled(true);
+ *
+ * final Activity activity = this;
+ * webview.setWebChromeClient(new WebChromeClient() {
+ *   public void onProgressChanged(WebView view, int progress) {
+ *     // Activities and WebViews measure progress with different scales.
+ *     // The progress meter will automatically disappear when we reach 100%
+ *     activity.setProgress(progress * 1000);
+ *   }
+ * });
+ * webview.setWebViewClient(new WebViewClient() {
+ *   public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
+ *     Toast.makeText(activity, "Oh no! " + description, Toast.LENGTH_SHORT).show();
+ *   }
+ * });
+ *
+ * webview.loadUrl("http://slashdot.org/");
+ * </pre>
+ *
+ * <h3>Cookie and window management</h3>
+ *
+ * <p>For obvious security reasons, your application has its own
+ * cache, cookie store etc.&mdash;it does not share the Browser
+ * application's data. Cookies are managed on a separate thread, so
+ * operations like index building don't block the UI
+ * thread. Follow the instructions in {@link android.webkit.CookieSyncManager}
+ * if you want to use cookies in your application.
+ * </p>
+ *
+ * <p>By default, requests by the HTML to open new windows are
+ * ignored. This is true whether they be opened by JavaScript or by
+ * the target attribute on a link. You can customize your
+ * {@link WebChromeClient} to provide your own behaviour for opening multiple windows,
+ * and render them in whatever manner you want.</p>
+ *
+ * <p>The standard behavior for an Activity is to be destroyed and
+ * recreated when the device orientation or any other configuration changes. This will cause
+ * the WebView to reload the current page. If you don't want that, you
+ * can set your Activity to handle the {@code orientation} and {@code keyboardHidden}
+ * changes, and then just leave the WebView alone. It'll automatically
+ * re-orient itself as appropriate. Read <a
+ * href="{@docRoot}guide/topics/resources/runtime-changes.html">Handling Runtime Changes</a> for
+ * more information about how to handle configuration changes during runtime.</p>
+ *
+ *
+ * <h3>Building web pages to support different screen densities</h3>
+ *
+ * <p>The screen density of a device is based on the screen resolution. A screen with low density
+ * has fewer available pixels per inch, where a screen with high density
+ * has more &mdash; sometimes significantly more &mdash; pixels per inch. The density of a
+ * screen is important because, other things being equal, a UI element (such as a button) whose
+ * height and width are defined in terms of screen pixels will appear larger on the lower density
+ * screen and smaller on the higher density screen.
+ * For simplicity, Android collapses all actual screen densities into three generalized densities:
+ * high, medium, and low.</p>
+ * <p>By default, WebView scales a web page so that it is drawn at a size that matches the default
+ * appearance on a medium density screen. So, it applies 1.5x scaling on a high density screen
+ * (because its pixels are smaller) and 0.75x scaling on a low density screen (because its pixels
+ * are bigger).
+ * Starting with API Level 5 (Android 2.0), WebView supports DOM, CSS, and meta tag features to help
+ * you (as a web developer) target screens with different screen densities.</p>
+ * <p>Here's a summary of the features you can use to handle different screen densities:</p>
+ * <ul>
+ * <li>The {@code window.devicePixelRatio} DOM property. The value of this property specifies the
+ * default scaling factor used for the current device. For example, if the value of {@code
+ * window.devicePixelRatio} is "1.0", then the device is considered a medium density (mdpi) device
+ * and default scaling is not applied to the web page; if the value is "1.5", then the device is
+ * considered a high density device (hdpi) and the page content is scaled 1.5x; if the
+ * value is "0.75", then the device is considered a low density device (ldpi) and the content is
+ * scaled 0.75x. However, if you specify the {@code "target-densitydpi"} meta property
+ * (discussed below), then you can stop this default scaling behavior.</li>
+ * <li>The {@code -webkit-device-pixel-ratio} CSS media query. Use this to specify the screen
+ * densities for which this style sheet is to be used. The corresponding value should be either
+ * "0.75", "1", or "1.5", to indicate that the styles are for devices with low density, medium
+ * density, or high density screens, respectively. For example:
+ * <pre>
+ * &lt;link rel="stylesheet" media="screen and (-webkit-device-pixel-ratio:1.5)" href="hdpi.css" /&gt;</pre>
+ * <p>The {@code hdpi.css} stylesheet is only used for devices with a screen pixel ration of 1.5,
+ * which is the high density pixel ratio.</p>
+ * </li>
+ * <li>The {@code target-densitydpi} property for the {@code viewport} meta tag. You can use
+ * this to specify the target density for which the web page is designed, using the following
+ * values:
+ * <ul>
+ * <li>{@code device-dpi} - Use the device's native dpi as the target dpi. Default scaling never
+ * occurs.</li>
+ * <li>{@code high-dpi} - Use hdpi as the target dpi. Medium and low density screens scale down
+ * as appropriate.</li>
+ * <li>{@code medium-dpi} - Use mdpi as the target dpi. High density screens scale up and
+ * low density screens scale down. This is also the default behavior.</li>
+ * <li>{@code low-dpi} - Use ldpi as the target dpi. Medium and high density screens scale up
+ * as appropriate.</li>
+ * <li><em>{@code <value>}</em> - Specify a dpi value to use as the target dpi (accepted
+ * values are 70-400).</li>
+ * </ul>
+ * <p>Here's an example meta tag to specify the target density:</p>
+ * <pre>&lt;meta name="viewport" content="target-densitydpi=device-dpi" /&gt;</pre></li>
+ * </ul>
+ * <p>If you want to modify your web page for different densities, by using the {@code
+ * -webkit-device-pixel-ratio} CSS media query and/or the {@code
+ * window.devicePixelRatio} DOM property, then you should set the {@code target-densitydpi} meta
+ * property to {@code device-dpi}. This stops Android from performing scaling in your web page and
+ * allows you to make the necessary adjustments for each density via CSS and JavaScript.</p>
+ *
+ * <h3>HTML5 Video support</h3>
+ *
+ * <p>In order to support inline HTML5 video in your application, you need to have hardware
+ * acceleration turned on, and set a {@link android.webkit.WebChromeClient}. For full screen support,
+ * implementations of {@link WebChromeClient#onShowCustomView(View, WebChromeClient.CustomViewCallback)}
+ * and {@link WebChromeClient#onHideCustomView()} are required,
+ * {@link WebChromeClient#getVideoLoadingProgressView()} is optional.
+ * </p>
+ *
+ * @hide
+ */
+// TODO: Remove duplicated API documentation and @hide from fields and methods, and
+// checkThread() call. (All left in for now to ease branch merging.)
+// TODO: Check if any WebView published API methods are called from within here, and if so
+// we should bounce the call out via the proxy to enable any sub-class to override it.
+@Widget
+@SuppressWarnings("deprecation")
+public final class WebViewClassic implements WebViewProvider, WebViewProvider.ScrollDelegate,
+        WebViewProvider.ViewDelegate {
+    private class InnerGlobalLayoutListener implements ViewTreeObserver.OnGlobalLayoutListener {
+        @Override
+        public void onGlobalLayout() {
+            if (mWebView.isShown()) {
+                setGLRectViewport();
+            }
+        }
+    }
+
+    private class InnerScrollChangedListener implements ViewTreeObserver.OnScrollChangedListener {
+        @Override
+        public void onScrollChanged() {
+            if (mWebView.isShown()) {
+                setGLRectViewport();
+            }
+        }
+    }
+
+    /**
+     * InputConnection used for ContentEditable. This captures changes
+     * to the text and sends them either as key strokes or text changes.
+     */
+    private class WebViewInputConnection extends BaseInputConnection {
+        // Used for mapping characters to keys typed.
+        private KeyCharacterMap mKeyCharacterMap;
+        private boolean mIsKeySentByMe;
+        private int mInputType;
+        private int mImeOptions;
+        private String mHint;
+        private int mMaxLength;
+
+        public WebViewInputConnection() {
+            super(mWebView, true);
+        }
+
+        @Override
+        public boolean sendKeyEvent(KeyEvent event) {
+            // Some IMEs send key events directly using sendKeyEvents.
+            // WebViewInputConnection should treat these as text changes.
+            if (!mIsKeySentByMe) {
+                if (event.getAction() == KeyEvent.ACTION_UP) {
+                    if (event.getKeyCode() == KeyEvent.KEYCODE_DEL) {
+                        return deleteSurroundingText(1, 0);
+                    } else if (event.getKeyCode() == KeyEvent.KEYCODE_FORWARD_DEL) {
+                        return deleteSurroundingText(0, 1);
+                    } else if (event.getUnicodeChar() != 0){
+                        String newComposingText =
+                                Character.toString((char)event.getUnicodeChar());
+                        return commitText(newComposingText, 1);
+                    }
+                } else if (event.getAction() == KeyEvent.ACTION_DOWN &&
+                        (event.getKeyCode() == KeyEvent.KEYCODE_DEL
+                        || event.getKeyCode() == KeyEvent.KEYCODE_FORWARD_DEL
+                        || event.getUnicodeChar() != 0)) {
+                    return true; // only act on action_down
+                }
+            }
+            return super.sendKeyEvent(event);
+        }
+
+        public void setTextAndKeepSelection(CharSequence text) {
+            Editable editable = getEditable();
+            int selectionStart = Selection.getSelectionStart(editable);
+            int selectionEnd = Selection.getSelectionEnd(editable);
+            text = limitReplaceTextByMaxLength(text, editable.length());
+            editable.replace(0, editable.length(), text);
+            restartInput();
+            // Keep the previous selection.
+            selectionStart = Math.min(selectionStart, editable.length());
+            selectionEnd = Math.min(selectionEnd, editable.length());
+            setSelection(selectionStart, selectionEnd);
+        }
+
+        public void replaceSelection(CharSequence text) {
+            Editable editable = getEditable();
+            int selectionStart = Selection.getSelectionStart(editable);
+            int selectionEnd = Selection.getSelectionEnd(editable);
+            text = limitReplaceTextByMaxLength(text, selectionEnd - selectionStart);
+            setNewText(selectionStart, selectionEnd, text);
+            editable.replace(selectionStart, selectionEnd, text);
+            restartInput();
+            // Move caret to the end of the new text
+            int newCaret = selectionStart + text.length();
+            setSelection(newCaret, newCaret);
+        }
+
+        @Override
+        public boolean setComposingText(CharSequence text, int newCursorPosition) {
+            Editable editable = getEditable();
+            int start = getComposingSpanStart(editable);
+            int end = getComposingSpanEnd(editable);
+            if (start < 0 || end < 0) {
+                start = Selection.getSelectionStart(editable);
+                end = Selection.getSelectionEnd(editable);
+            }
+            if (end < start) {
+                int temp = end;
+                end = start;
+                start = temp;
+            }
+            CharSequence limitedText = limitReplaceTextByMaxLength(text, end - start);
+            setNewText(start, end, limitedText);
+            if (limitedText != text) {
+                newCursorPosition -= text.length() - limitedText.length();
+            }
+            super.setComposingText(limitedText, newCursorPosition);
+            if (limitedText != text) {
+                restartInput();
+                int lastCaret = start + limitedText.length();
+                finishComposingText();
+                setSelection(lastCaret, lastCaret);
+            }
+            return true;
+        }
+
+        @Override
+        public boolean commitText(CharSequence text, int newCursorPosition) {
+            setComposingText(text, newCursorPosition);
+            int cursorPosition = Selection.getSelectionEnd(getEditable());
+            setComposingRegion(cursorPosition, cursorPosition);
+            return true;
+        }
+
+        @Override
+        public boolean deleteSurroundingText(int leftLength, int rightLength) {
+            Editable editable = getEditable();
+            int cursorPosition = Selection.getSelectionEnd(editable);
+            int startDelete = Math.max(0, cursorPosition - leftLength);
+            int endDelete = Math.min(editable.length(),
+                    cursorPosition + rightLength);
+            setNewText(startDelete, endDelete, "");
+            return super.deleteSurroundingText(leftLength, rightLength);
+        }
+
+        @Override
+        public boolean performEditorAction(int editorAction) {
+
+            boolean handled = true;
+            switch (editorAction) {
+            case EditorInfo.IME_ACTION_NEXT:
+                mWebView.requestFocus(View.FOCUS_FORWARD);
+                break;
+            case EditorInfo.IME_ACTION_PREVIOUS:
+                mWebView.requestFocus(View.FOCUS_BACKWARD);
+                break;
+            case EditorInfo.IME_ACTION_DONE:
+                WebViewClassic.this.hideSoftKeyboard();
+                break;
+            case EditorInfo.IME_ACTION_GO:
+            case EditorInfo.IME_ACTION_SEARCH:
+                WebViewClassic.this.hideSoftKeyboard();
+                String text = getEditable().toString();
+                passToJavaScript(text, new KeyEvent(KeyEvent.ACTION_DOWN,
+                        KeyEvent.KEYCODE_ENTER));
+                passToJavaScript(text, new KeyEvent(KeyEvent.ACTION_UP,
+                        KeyEvent.KEYCODE_ENTER));
+                break;
+
+            default:
+                handled = super.performEditorAction(editorAction);
+                break;
+            }
+
+            return handled;
+        }
+
+        public void initEditorInfo(WebViewCore.TextFieldInitData initData) {
+            int type = initData.mType;
+            int inputType = InputType.TYPE_CLASS_TEXT
+                    | InputType.TYPE_TEXT_VARIATION_WEB_EDIT_TEXT;
+            int imeOptions = EditorInfo.IME_FLAG_NO_EXTRACT_UI
+                    | EditorInfo.IME_FLAG_NO_FULLSCREEN;
+            if (!initData.mIsSpellCheckEnabled) {
+                inputType |= InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS;
+            }
+            if (WebTextView.TEXT_AREA != type
+                    && initData.mIsTextFieldNext) {
+                imeOptions |= EditorInfo.IME_FLAG_NAVIGATE_NEXT;
+            }
+            switch (type) {
+                case WebTextView.NORMAL_TEXT_FIELD:
+                    imeOptions |= EditorInfo.IME_ACTION_GO;
+                    break;
+                case WebTextView.TEXT_AREA:
+                    inputType |= InputType.TYPE_TEXT_FLAG_MULTI_LINE
+                            | InputType.TYPE_TEXT_FLAG_CAP_SENTENCES
+                            | InputType.TYPE_TEXT_FLAG_AUTO_CORRECT;
+                    imeOptions |= EditorInfo.IME_ACTION_NONE;
+                    break;
+                case WebTextView.PASSWORD:
+                    inputType |= EditorInfo.TYPE_TEXT_VARIATION_WEB_PASSWORD;
+                    imeOptions |= EditorInfo.IME_ACTION_GO;
+                    break;
+                case WebTextView.SEARCH:
+                    imeOptions |= EditorInfo.IME_ACTION_SEARCH;
+                    break;
+                case WebTextView.EMAIL:
+                    // inputType needs to be overwritten because of the different text variation.
+                    inputType = InputType.TYPE_CLASS_TEXT
+                            | InputType.TYPE_TEXT_VARIATION_WEB_EMAIL_ADDRESS;
+                    imeOptions |= EditorInfo.IME_ACTION_GO;
+                    break;
+                case WebTextView.NUMBER:
+                    // inputType needs to be overwritten because of the different class.
+                    inputType = InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_VARIATION_NORMAL
+                            | InputType.TYPE_NUMBER_FLAG_SIGNED | InputType.TYPE_NUMBER_FLAG_DECIMAL;
+                    // Number and telephone do not have both a Tab key and an
+                    // action, so set the action to NEXT
+                    imeOptions |= EditorInfo.IME_ACTION_NEXT;
+                    break;
+                case WebTextView.TELEPHONE:
+                    // inputType needs to be overwritten because of the different class.
+                    inputType = InputType.TYPE_CLASS_PHONE;
+                    imeOptions |= EditorInfo.IME_ACTION_NEXT;
+                    break;
+                case WebTextView.URL:
+                    // TYPE_TEXT_VARIATION_URI prevents Tab key from showing, so
+                    // exclude it for now.
+                    imeOptions |= EditorInfo.IME_ACTION_GO;
+                    inputType |= InputType.TYPE_TEXT_VARIATION_URI;
+                    break;
+                default:
+                    imeOptions |= EditorInfo.IME_ACTION_GO;
+                    break;
+            }
+            mHint = initData.mLabel;
+            mInputType = inputType;
+            mImeOptions = imeOptions;
+            mMaxLength = initData.mMaxLength;
+        }
+
+        public void setupEditorInfo(EditorInfo outAttrs) {
+            outAttrs.inputType = mInputType;
+            outAttrs.imeOptions = mImeOptions;
+            outAttrs.hintText = mHint;
+            outAttrs.initialCapsMode = getCursorCapsMode(InputType.TYPE_CLASS_TEXT);
+        }
+
+        /**
+         * Sends a text change to webkit indirectly. If it is a single-
+         * character add or delete, it sends it as a key stroke. If it cannot
+         * be represented as a key stroke, it sends it as a field change.
+         * @param start The start offset (inclusive) of the text being changed.
+         * @param end The end offset (exclusive) of the text being changed.
+         * @param text The new text to replace the changed text.
+         */
+        private void setNewText(int start, int end, CharSequence text) {
+            mIsKeySentByMe = true;
+            Editable editable = getEditable();
+            CharSequence original = editable.subSequence(start, end);
+            boolean isCharacterAdd = false;
+            boolean isCharacterDelete = false;
+            int textLength = text.length();
+            int originalLength = original.length();
+            if (textLength > originalLength) {
+                isCharacterAdd = (textLength == originalLength + 1)
+                        && TextUtils.regionMatches(text, 0, original, 0,
+                                originalLength);
+            } else if (originalLength > textLength) {
+                isCharacterDelete = (textLength == originalLength - 1)
+                        && TextUtils.regionMatches(text, 0, original, 0,
+                                textLength);
+            }
+            if (isCharacterAdd) {
+                sendCharacter(text.charAt(textLength - 1));
+            } else if (isCharacterDelete) {
+                sendKey(KeyEvent.KEYCODE_DEL);
+            } else if ((textLength != originalLength) ||
+                    !TextUtils.regionMatches(text, 0, original, 0,
+                            textLength)) {
+                // Send a message so that key strokes and text replacement
+                // do not come out of order.
+                Message replaceMessage = mPrivateHandler.obtainMessage(
+                        REPLACE_TEXT, start,  end, text.toString());
+                mPrivateHandler.sendMessage(replaceMessage);
+            }
+            mIsKeySentByMe = false;
+        }
+
+        /**
+         * Send a single character to the WebView as a key down and up event.
+         * @param c The character to be sent.
+         */
+        private void sendCharacter(char c) {
+            if (mKeyCharacterMap == null) {
+                mKeyCharacterMap = KeyCharacterMap.load(KeyCharacterMap.VIRTUAL_KEYBOARD);
+            }
+            char[] chars = new char[1];
+            chars[0] = c;
+            KeyEvent[] events = mKeyCharacterMap.getEvents(chars);
+            if (events != null) {
+                for (KeyEvent event : events) {
+                    sendKeyEvent(event);
+                }
+            } else {
+                Message msg = mPrivateHandler.obtainMessage(KEY_PRESS, (int) c, 0);
+                mPrivateHandler.sendMessage(msg);
+            }
+        }
+
+        /**
+         * Send a key event for a specific key code, not a standard
+         * unicode character.
+         * @param keyCode The key code to send.
+         */
+        private void sendKey(int keyCode) {
+            long eventTime = SystemClock.uptimeMillis();
+            sendKeyEvent(new KeyEvent(eventTime, eventTime,
+                    KeyEvent.ACTION_DOWN, keyCode, 0, 0,
+                    KeyCharacterMap.VIRTUAL_KEYBOARD, 0,
+                    KeyEvent.FLAG_SOFT_KEYBOARD));
+            sendKeyEvent(new KeyEvent(SystemClock.uptimeMillis(), eventTime,
+                    KeyEvent.ACTION_UP, keyCode, 0, 0,
+                    KeyCharacterMap.VIRTUAL_KEYBOARD, 0,
+                    KeyEvent.FLAG_SOFT_KEYBOARD));
+        }
+
+        private CharSequence limitReplaceTextByMaxLength(CharSequence text,
+                int numReplaced) {
+            if (mMaxLength > 0) {
+                Editable editable = getEditable();
+                int maxReplace = mMaxLength - editable.length() + numReplaced;
+                if (maxReplace < text.length()) {
+                    maxReplace = Math.max(maxReplace, 0);
+                    // New length is greater than the maximum. trim it down.
+                    text = text.subSequence(0, maxReplace);
+                }
+            }
+            return text;
+        }
+
+        private void restartInput() {
+            InputMethodManager imm = InputMethodManager.peekInstance();
+            if (imm != null) {
+                // Since the text has changed, do not allow the IME to replace the
+                // existing text as though it were a completion.
+                imm.restartInput(mWebView);
+            }
+        }
+    }
+
+    private class PastePopupWindow extends PopupWindow implements View.OnClickListener {
+        private ViewGroup mContentView;
+        private TextView mPasteTextView;
+
+        public PastePopupWindow() {
+            super(mContext, null,
+                    com.android.internal.R.attr.textSelectHandleWindowStyle);
+            setClippingEnabled(true);
+            LinearLayout linearLayout = new LinearLayout(mContext);
+            linearLayout.setOrientation(LinearLayout.HORIZONTAL);
+            mContentView = linearLayout;
+            mContentView.setBackgroundResource(
+                    com.android.internal.R.drawable.text_edit_paste_window);
+
+            LayoutInflater inflater = (LayoutInflater)mContext.
+                    getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+
+            ViewGroup.LayoutParams wrapContent = new ViewGroup.LayoutParams(
+                    ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
+
+            mPasteTextView = (TextView) inflater.inflate(
+                    com.android.internal.R.layout.text_edit_action_popup_text, null);
+            mPasteTextView.setLayoutParams(wrapContent);
+            mContentView.addView(mPasteTextView);
+            mPasteTextView.setText(com.android.internal.R.string.paste);
+            mPasteTextView.setOnClickListener(this);
+            this.setContentView(mContentView);
+        }
+
+        public void show(Rect cursorRect, int windowLeft, int windowTop) {
+            measureContent();
+
+            int width = mContentView.getMeasuredWidth();
+            int height = mContentView.getMeasuredHeight();
+            int y = cursorRect.top - height;
+            if (y < windowTop) {
+                // There's not enough room vertically, move it below the
+                // handle.
+                // The selection handle is vertically offset by 1/4 of the
+                // line height.
+                ensureSelectionHandles();
+                y = cursorRect.bottom - (cursorRect.height() / 4) +
+                        mSelectHandleCenter.getIntrinsicHeight();
+            }
+            int x = cursorRect.centerX() - (width / 2);
+            if (x < windowLeft) {
+                x = windowLeft;
+            }
+            if (!isShowing()) {
+                showAtLocation(mWebView, Gravity.NO_GRAVITY, x, y);
+            }
+            update(x, y, width, height);
+        }
+
+        public void hide() {
+            dismiss();
+        }
+
+        @Override
+        public void onClick(View view) {
+            pasteFromClipboard();
+            selectionDone();
+        }
+
+        protected void measureContent() {
+            final DisplayMetrics displayMetrics = mContext.getResources().getDisplayMetrics();
+            mContentView.measure(
+                    View.MeasureSpec.makeMeasureSpec(displayMetrics.widthPixels,
+                            View.MeasureSpec.AT_MOST),
+                    View.MeasureSpec.makeMeasureSpec(displayMetrics.heightPixels,
+                            View.MeasureSpec.AT_MOST));
+        }
+    }
+
+    // The listener to capture global layout change event.
+    private InnerGlobalLayoutListener mGlobalLayoutListener = null;
+
+    // The listener to capture scroll event.
+    private InnerScrollChangedListener mScrollChangedListener = null;
+
+    // if AUTO_REDRAW_HACK is true, then the CALL key will toggle redrawing
+    // the screen all-the-time. Good for profiling our drawing code
+    static private final boolean AUTO_REDRAW_HACK = false;
+    // true means redraw the screen all-the-time. Only with AUTO_REDRAW_HACK
+    private boolean mAutoRedraw;
+
+    // Reference to the AlertDialog displayed by InvokeListBox.
+    // It's used to dismiss the dialog in destroy if not done before.
+    private AlertDialog mListBoxDialog = null;
+
+    static final String LOGTAG = "webview";
+
+    private ZoomManager mZoomManager;
+
+    private final Rect mGLRectViewport = new Rect();
+    private final Rect mViewRectViewport = new Rect();
+    private final RectF mVisibleContentRect = new RectF();
+    private boolean mGLViewportEmpty = false;
+    WebViewInputConnection mInputConnection = null;
+    private int mFieldPointer;
+    private PastePopupWindow mPasteWindow;
+
+    private static class OnTrimMemoryListener implements ComponentCallbacks2 {
+        private static OnTrimMemoryListener sInstance = null;
+
+        static void init(Context c) {
+            if (sInstance == null) {
+                sInstance = new OnTrimMemoryListener(c.getApplicationContext());
+            }
+        }
+
+        private OnTrimMemoryListener(Context c) {
+            c.registerComponentCallbacks(this);
+        }
+
+        @Override
+        public void onConfigurationChanged(Configuration newConfig) {
+            // Ignore
+        }
+
+        @Override
+        public void onLowMemory() {
+            // Ignore
+        }
+
+        @Override
+        public void onTrimMemory(int level) {
+            if (DebugFlags.WEB_VIEW) {
+                Log.d("WebView", "onTrimMemory: " + level);
+            }
+            // When framework reset EGL context during high memory pressure, all
+            // the existing GL resources for the html5 video will be destroyed
+            // at native side.
+            // Here we just need to clean up the Surface Texture which is static.
+            HTML5VideoInline.cleanupSurfaceTexture();
+            WebViewClassic.nativeOnTrimMemory(level);
+        }
+
+    }
+
+    // A final CallbackProxy shared by WebViewCore and BrowserFrame.
+    private CallbackProxy mCallbackProxy;
+
+    private WebViewDatabase mDatabase;
+
+    // SSL certificate for the main top-level page (if secure)
+    private SslCertificate mCertificate;
+
+    // Native WebView pointer that is 0 until the native object has been
+    // created.
+    private int mNativeClass;
+    // This would be final but it needs to be set to null when the WebView is
+    // destroyed.
+    private WebViewCore mWebViewCore;
+    // Handler for dispatching UI messages.
+    /* package */ final Handler mPrivateHandler = new PrivateHandler();
+    // Used to ignore changes to webkit text that arrives to the UI side after
+    // more key events.
+    private int mTextGeneration;
+
+    /* package */ void incrementTextGeneration() { mTextGeneration++; }
+
+    // Used by WebViewCore to create child views.
+    /* package */ ViewManager mViewManager;
+
+    // Used to display in full screen mode
+    PluginFullScreenHolder mFullScreenHolder;
+
+    /**
+     * Position of the last touch event in pixels.
+     * Use integer to prevent loss of dragging delta calculation accuracy;
+     * which was done in float and converted to integer, and resulted in gradual
+     * and compounding touch position and view dragging mismatch.
+     */
+    private int mLastTouchX;
+    private int mLastTouchY;
+    private int mStartTouchX;
+    private int mStartTouchY;
+    private float mAverageAngle;
+
+    /**
+     * Time of the last touch event.
+     */
+    private long mLastTouchTime;
+
+    /**
+     * Time of the last time sending touch event to WebViewCore
+     */
+    private long mLastSentTouchTime;
+
+    /**
+     * The minimum elapsed time before sending another ACTION_MOVE event to
+     * WebViewCore. This really should be tuned for each type of the devices.
+     * For example in Google Map api test case, it takes Dream device at least
+     * 150ms to do a full cycle in the WebViewCore by processing a touch event,
+     * triggering the layout and drawing the picture. While the same process
+     * takes 60+ms on the current high speed device. If we make
+     * TOUCH_SENT_INTERVAL too small, there will be multiple touch events sent
+     * to WebViewCore queue and the real layout and draw events will be pushed
+     * to further, which slows down the refresh rate. Choose 50 to favor the
+     * current high speed devices. For Dream like devices, 100 is a better
+     * choice. Maybe make this in the buildspec later.
+     * (Update 12/14/2010: changed to 0 since current device should be able to
+     * handle the raw events and Map team voted to have the raw events too.
+     */
+    private static final int TOUCH_SENT_INTERVAL = 0;
+    private int mCurrentTouchInterval = TOUCH_SENT_INTERVAL;
+
+    /**
+     * Helper class to get velocity for fling
+     */
+    VelocityTracker mVelocityTracker;
+    private int mMaximumFling;
+    private float mLastVelocity;
+    private float mLastVelX;
+    private float mLastVelY;
+
+    // The id of the native layer being scrolled.
+    private int mCurrentScrollingLayerId;
+    private Rect mScrollingLayerRect = new Rect();
+
+    // only trigger accelerated fling if the new velocity is at least
+    // MINIMUM_VELOCITY_RATIO_FOR_ACCELERATION times of the previous velocity
+    private static final float MINIMUM_VELOCITY_RATIO_FOR_ACCELERATION = 0.2f;
+
+    /**
+     * Touch mode
+     */
+    private int mTouchMode = TOUCH_DONE_MODE;
+    private static final int TOUCH_INIT_MODE = 1;
+    private static final int TOUCH_DRAG_START_MODE = 2;
+    private static final int TOUCH_DRAG_MODE = 3;
+    private static final int TOUCH_SHORTPRESS_START_MODE = 4;
+    private static final int TOUCH_SHORTPRESS_MODE = 5;
+    private static final int TOUCH_DOUBLE_TAP_MODE = 6;
+    private static final int TOUCH_DONE_MODE = 7;
+    private static final int TOUCH_PINCH_DRAG = 8;
+    private static final int TOUCH_DRAG_LAYER_MODE = 9;
+
+    // Whether to forward the touch events to WebCore
+    // Can only be set by WebKit via JNI.
+    private boolean mForwardTouchEvents = false;
+
+    // Whether to prevent default during touch. The initial value depends on
+    // mForwardTouchEvents. If WebCore wants all the touch events, it says yes
+    // for touch down. Otherwise UI will wait for the answer of the first
+    // confirmed move before taking over the control.
+    private static final int PREVENT_DEFAULT_NO = 0;
+    private static final int PREVENT_DEFAULT_MAYBE_YES = 1;
+    private static final int PREVENT_DEFAULT_NO_FROM_TOUCH_DOWN = 2;
+    private static final int PREVENT_DEFAULT_YES = 3;
+    private static final int PREVENT_DEFAULT_IGNORE = 4;
+    private int mPreventDefault = PREVENT_DEFAULT_IGNORE;
+
+    // true when the touch movement exceeds the slop
+    private boolean mConfirmMove;
+
+    // if true, touch events will be first processed by WebCore, if prevent
+    // default is not set, the UI will continue handle them.
+    private boolean mDeferTouchProcess;
+
+    // to avoid interfering with the current touch events, track them
+    // separately. Currently no snapping or fling in the deferred process mode
+    private int mDeferTouchMode = TOUCH_DONE_MODE;
+    private float mLastDeferTouchX;
+    private float mLastDeferTouchY;
+
+    // Whether or not to draw the cursor ring.
+    private boolean mDrawCursorRing = true;
+
+    // true if onPause has been called (and not onResume)
+    private boolean mIsPaused;
+
+    private HitTestResult mInitialHitTestResult;
+    private WebKitHitTest mFocusedNode;
+
+    /**
+     * Customizable constant
+     */
+    // pre-computed square of ViewConfiguration.getScaledTouchSlop()
+    private int mTouchSlopSquare;
+    // pre-computed square of ViewConfiguration.getScaledDoubleTapSlop()
+    private int mDoubleTapSlopSquare;
+    // pre-computed density adjusted navigation slop
+    private int mNavSlop;
+    // This should be ViewConfiguration.getTapTimeout()
+    // But system time out is 100ms, which is too short for the browser.
+    // In the browser, if it switches out of tap too soon, jump tap won't work.
+    // In addition, a double tap on a trackpad will always have a duration of
+    // 300ms, so this value must be at least that (otherwise we will timeout the
+    // first tap and convert it to a long press).
+    private static final int TAP_TIMEOUT = 300;
+    // This should be ViewConfiguration.getLongPressTimeout()
+    // But system time out is 500ms, which is too short for the browser.
+    // With a short timeout, it's difficult to treat trigger a short press.
+    private static final int LONG_PRESS_TIMEOUT = 1000;
+    // needed to avoid flinging after a pause of no movement
+    private static final int MIN_FLING_TIME = 250;
+    // draw unfiltered after drag is held without movement
+    private static final int MOTIONLESS_TIME = 100;
+    // The amount of content to overlap between two screens when going through
+    // pages with the space bar, in pixels.
+    private static final int PAGE_SCROLL_OVERLAP = 24;
+
+    /**
+     * These prevent calling requestLayout if either dimension is fixed. This
+     * depends on the layout parameters and the measure specs.
+     */
+    boolean mWidthCanMeasure;
+    boolean mHeightCanMeasure;
+
+    // Remember the last dimensions we sent to the native side so we can avoid
+    // sending the same dimensions more than once.
+    int mLastWidthSent;
+    int mLastHeightSent;
+    // Since view height sent to webkit could be fixed to avoid relayout, this
+    // value records the last sent actual view height.
+    int mLastActualHeightSent;
+
+    private int mContentWidth;   // cache of value from WebViewCore
+    private int mContentHeight;  // cache of value from WebViewCore
+
+    // Need to have the separate control for horizontal and vertical scrollbar
+    // style than the View's single scrollbar style
+    private boolean mOverlayHorizontalScrollbar = true;
+    private boolean mOverlayVerticalScrollbar = false;
+
+    // our standard speed. this way small distances will be traversed in less
+    // time than large distances, but we cap the duration, so that very large
+    // distances won't take too long to get there.
+    private static final int STD_SPEED = 480;  // pixels per second
+    // time for the longest scroll animation
+    private static final int MAX_DURATION = 750;   // milliseconds
+    private static final int SLIDE_TITLE_DURATION = 500;   // milliseconds
+
+    // Used by OverScrollGlow
+    OverScroller mScroller;
+
+    private boolean mInOverScrollMode = false;
+    private static Paint mOverScrollBackground;
+    private static Paint mOverScrollBorder;
+
+    private boolean mWrapContent;
+    private static final int MOTIONLESS_FALSE           = 0;
+    private static final int MOTIONLESS_PENDING         = 1;
+    private static final int MOTIONLESS_TRUE            = 2;
+    private static final int MOTIONLESS_IGNORE          = 3;
+    private int mHeldMotionless;
+
+    // An instance for injecting accessibility in WebViews with disabled
+    // JavaScript or ones for which no accessibility script exists
+    private AccessibilityInjector mAccessibilityInjector;
+
+    // flag indicating if accessibility script is injected so we
+    // know to handle Shift and arrows natively first
+    private boolean mAccessibilityScriptInjected;
+
+
+    /**
+     * How long the caret handle will last without being touched.
+     */
+    private static final long CARET_HANDLE_STAMINA_MS = 3000;
+
+    private Drawable mSelectHandleLeft;
+    private Drawable mSelectHandleRight;
+    private Drawable mSelectHandleCenter;
+    private Rect mSelectCursorBase = new Rect();
+    private int mSelectCursorBaseLayerId;
+    private Rect mSelectCursorExtent = new Rect();
+    private int mSelectCursorExtentLayerId;
+    private Rect mSelectDraggingCursor;
+    private Point mSelectDraggingOffset = new Point();
+    private boolean mIsCaretSelection;
+    static final int HANDLE_ID_START = 0;
+    static final int HANDLE_ID_END = 1;
+    static final int HANDLE_ID_BASE = 2;
+    static final int HANDLE_ID_EXTENT = 3;
+
+    // the color used to highlight the touch rectangles
+    static final int HIGHLIGHT_COLOR = 0x6633b5e5;
+    // the region indicating where the user touched on the screen
+    private Region mTouchHighlightRegion = new Region();
+    // the paint for the touch highlight
+    private Paint mTouchHightlightPaint = new Paint();
+    // debug only
+    private static final boolean DEBUG_TOUCH_HIGHLIGHT = true;
+    private static final int TOUCH_HIGHLIGHT_ELAPSE_TIME = 2000;
+    private Paint mTouchCrossHairColor;
+    private int mTouchHighlightX;
+    private int mTouchHighlightY;
+    private long mTouchHighlightRequested;
+
+    // Basically this proxy is used to tell the Video to update layer tree at
+    // SetBaseLayer time and to pause when WebView paused.
+    private HTML5VideoViewProxy mHTML5VideoViewProxy;
+
+    // If we are using a set picture, don't send view updates to webkit
+    private boolean mBlockWebkitViewMessages = false;
+
+    // cached value used to determine if we need to switch drawing models
+    private boolean mHardwareAccelSkia = false;
+
+    /*
+     * Private message ids
+     */
+    private static final int REMEMBER_PASSWORD          = 1;
+    private static final int NEVER_REMEMBER_PASSWORD    = 2;
+    private static final int SWITCH_TO_SHORTPRESS       = 3;
+    private static final int SWITCH_TO_LONGPRESS        = 4;
+    private static final int RELEASE_SINGLE_TAP         = 5;
+    private static final int DRAG_HELD_MOTIONLESS       = 8;
+    private static final int AWAKEN_SCROLL_BARS         = 9;
+    private static final int PREVENT_DEFAULT_TIMEOUT    = 10;
+    private static final int SCROLL_SELECT_TEXT         = 11;
+
+
+    private static final int FIRST_PRIVATE_MSG_ID = REMEMBER_PASSWORD;
+    private static final int LAST_PRIVATE_MSG_ID = SCROLL_SELECT_TEXT;
+
+    /*
+     * Package message ids
+     */
+    static final int SCROLL_TO_MSG_ID                   = 101;
+    static final int NEW_PICTURE_MSG_ID                 = 105;
+    static final int WEBCORE_INITIALIZED_MSG_ID         = 107;
+    static final int UPDATE_TEXTFIELD_TEXT_MSG_ID       = 108;
+    static final int UPDATE_ZOOM_RANGE                  = 109;
+    static final int TAKE_FOCUS                         = 110;
+    static final int CLEAR_TEXT_ENTRY                   = 111;
+    static final int UPDATE_TEXT_SELECTION_MSG_ID       = 112;
+    static final int SHOW_RECT_MSG_ID                   = 113;
+    static final int LONG_PRESS_CENTER                  = 114;
+    static final int PREVENT_TOUCH_ID                   = 115;
+    static final int WEBCORE_NEED_TOUCH_EVENTS          = 116;
+    // obj=Rect in doc coordinates
+    static final int INVAL_RECT_MSG_ID                  = 117;
+    static final int REQUEST_KEYBOARD                   = 118;
+    static final int SHOW_FULLSCREEN                    = 120;
+    static final int HIDE_FULLSCREEN                    = 121;
+    static final int REPLACE_BASE_CONTENT               = 123;
+    static final int FORM_DID_BLUR                      = 124;
+    static final int UPDATE_MATCH_COUNT                 = 126;
+    static final int CENTER_FIT_RECT                    = 127;
+    static final int REQUEST_KEYBOARD_WITH_SELECTION_MSG_ID = 128;
+    static final int SET_SCROLLBAR_MODES                = 129;
+    static final int SELECTION_STRING_CHANGED           = 130;
+    static final int HIT_TEST_RESULT                    = 131;
+    static final int SAVE_WEBARCHIVE_FINISHED           = 132;
+
+    static final int SET_AUTOFILLABLE                   = 133;
+    static final int AUTOFILL_COMPLETE                  = 134;
+
+    static final int SCREEN_ON                          = 136;
+    static final int ENTER_FULLSCREEN_VIDEO             = 137;
+    static final int UPDATE_ZOOM_DENSITY                = 139;
+    static final int EXIT_FULLSCREEN_VIDEO              = 140;
+
+    static final int COPY_TO_CLIPBOARD                  = 141;
+    static final int INIT_EDIT_FIELD                    = 142;
+    static final int REPLACE_TEXT                       = 143;
+    static final int CLEAR_CARET_HANDLE                 = 144;
+    static final int KEY_PRESS                          = 145;
+
+    private static final int FIRST_PACKAGE_MSG_ID = SCROLL_TO_MSG_ID;
+    private static final int LAST_PACKAGE_MSG_ID = HIT_TEST_RESULT;
+
+    static final String[] HandlerPrivateDebugString = {
+        "REMEMBER_PASSWORD", //              = 1;
+        "NEVER_REMEMBER_PASSWORD", //        = 2;
+        "SWITCH_TO_SHORTPRESS", //           = 3;
+        "SWITCH_TO_LONGPRESS", //            = 4;
+        "RELEASE_SINGLE_TAP", //             = 5;
+        "REQUEST_FORM_DATA", //              = 6;
+        "RESUME_WEBCORE_PRIORITY", //        = 7;
+        "DRAG_HELD_MOTIONLESS", //           = 8;
+        "AWAKEN_SCROLL_BARS", //             = 9;
+        "PREVENT_DEFAULT_TIMEOUT", //        = 10;
+        "SCROLL_SELECT_TEXT" //              = 11;
+    };
+
+    static final String[] HandlerPackageDebugString = {
+        "SCROLL_TO_MSG_ID", //               = 101;
+        "102", //                            = 102;
+        "103", //                            = 103;
+        "104", //                            = 104;
+        "NEW_PICTURE_MSG_ID", //             = 105;
+        "UPDATE_TEXT_ENTRY_MSG_ID", //       = 106;
+        "WEBCORE_INITIALIZED_MSG_ID", //     = 107;
+        "UPDATE_TEXTFIELD_TEXT_MSG_ID", //   = 108;
+        "UPDATE_ZOOM_RANGE", //              = 109;
+        "UNHANDLED_NAV_KEY", //              = 110;
+        "CLEAR_TEXT_ENTRY", //               = 111;
+        "UPDATE_TEXT_SELECTION_MSG_ID", //   = 112;
+        "SHOW_RECT_MSG_ID", //               = 113;
+        "LONG_PRESS_CENTER", //              = 114;
+        "PREVENT_TOUCH_ID", //               = 115;
+        "WEBCORE_NEED_TOUCH_EVENTS", //      = 116;
+        "INVAL_RECT_MSG_ID", //              = 117;
+        "REQUEST_KEYBOARD", //               = 118;
+        "DO_MOTION_UP", //                   = 119;
+        "SHOW_FULLSCREEN", //                = 120;
+        "HIDE_FULLSCREEN", //                = 121;
+        "DOM_FOCUS_CHANGED", //              = 122;
+        "REPLACE_BASE_CONTENT", //           = 123;
+        "FORM_DID_BLUR", //                  = 124;
+        "RETURN_LABEL", //                   = 125;
+        "UPDATE_MATCH_COUNT", //             = 126;
+        "CENTER_FIT_RECT", //                = 127;
+        "REQUEST_KEYBOARD_WITH_SELECTION_MSG_ID", // = 128;
+        "SET_SCROLLBAR_MODES", //            = 129;
+        "SELECTION_STRING_CHANGED", //       = 130;
+        "SET_TOUCH_HIGHLIGHT_RECTS", //      = 131;
+        "SAVE_WEBARCHIVE_FINISHED", //       = 132;
+        "SET_AUTOFILLABLE", //               = 133;
+        "AUTOFILL_COMPLETE", //              = 134;
+        "SELECT_AT", //                      = 135;
+        "SCREEN_ON", //                      = 136;
+        "ENTER_FULLSCREEN_VIDEO", //         = 137;
+        "UPDATE_SELECTION", //               = 138;
+        "UPDATE_ZOOM_DENSITY" //             = 139;
+    };
+
+    // If the site doesn't use the viewport meta tag to specify the viewport,
+    // use DEFAULT_VIEWPORT_WIDTH as the default viewport width
+    static final int DEFAULT_VIEWPORT_WIDTH = 980;
+
+    // normally we try to fit the content to the minimum preferred width
+    // calculated by the Webkit. To avoid the bad behavior when some site's
+    // minimum preferred width keeps growing when changing the viewport width or
+    // the minimum preferred width is huge, an upper limit is needed.
+    static int sMaxViewportWidth = DEFAULT_VIEWPORT_WIDTH;
+
+    // initial scale in percent. 0 means using default.
+    private int mInitialScaleInPercent = 0;
+
+    // Whether or not a scroll event should be sent to webkit.  This is only set
+    // to false when restoring the scroll position.
+    private boolean mSendScrollEvent = true;
+
+    private int mSnapScrollMode = SNAP_NONE;
+    private static final int SNAP_NONE = 0;
+    private static final int SNAP_LOCK = 1; // not a separate state
+    private static final int SNAP_X = 2; // may be combined with SNAP_LOCK
+    private static final int SNAP_Y = 4; // may be combined with SNAP_LOCK
+    private boolean mSnapPositive;
+
+    // keep these in sync with their counterparts in WebView.cpp
+    private static final int DRAW_EXTRAS_NONE = 0;
+    private static final int DRAW_EXTRAS_SELECTION = 1;
+    private static final int DRAW_EXTRAS_CURSOR_RING = 2;
+
+    // keep this in sync with WebCore:ScrollbarMode in WebKit
+    private static final int SCROLLBAR_AUTO = 0;
+    private static final int SCROLLBAR_ALWAYSOFF = 1;
+    // as we auto fade scrollbar, this is ignored.
+    private static final int SCROLLBAR_ALWAYSON = 2;
+    private int mHorizontalScrollBarMode = SCROLLBAR_AUTO;
+    private int mVerticalScrollBarMode = SCROLLBAR_AUTO;
+
+    // constants for determining script injection strategy
+    private static final int ACCESSIBILITY_SCRIPT_INJECTION_UNDEFINED = -1;
+    private static final int ACCESSIBILITY_SCRIPT_INJECTION_OPTED_OUT = 0;
+    private static final int ACCESSIBILITY_SCRIPT_INJECTION_PROVIDED = 1;
+
+    // the alias via which accessibility JavaScript interface is exposed
+    private static final String ALIAS_ACCESSIBILITY_JS_INTERFACE = "accessibility";
+
+    // Template for JavaScript that injects a screen-reader.
+    private static final String ACCESSIBILITY_SCREEN_READER_JAVASCRIPT_TEMPLATE =
+        "javascript:(function() {" +
+        "    var chooser = document.createElement('script');" +
+        "    chooser.type = 'text/javascript';" +
+        "    chooser.src = '%1s';" +
+        "    document.getElementsByTagName('head')[0].appendChild(chooser);" +
+        "  })();";
+
+    // Regular expression that matches the "axs" URL parameter.
+    // The value of 0 means the accessibility script is opted out
+    // The value of 1 means the accessibility script is already injected
+    private static final String PATTERN_MATCH_AXS_URL_PARAMETER = "(\\?axs=(0|1))|(&axs=(0|1))";
+
+    // TextToSpeech instance exposed to JavaScript to the injected screenreader.
+    private TextToSpeech mTextToSpeech;
+
+    // variable to cache the above pattern in case accessibility is enabled.
+    private Pattern mMatchAxsUrlParameterPattern;
+
+    /**
+     * Max distance to overscroll by in pixels.
+     * This how far content can be pulled beyond its normal bounds by the user.
+     */
+    private int mOverscrollDistance;
+
+    /**
+     * Max distance to overfling by in pixels.
+     * This is how far flinged content can move beyond the end of its normal bounds.
+     */
+    private int mOverflingDistance;
+
+    private OverScrollGlow mOverScrollGlow;
+
+    // Used to match key downs and key ups
+    private Vector<Integer> mKeysPressed;
+
+    /* package */ static boolean mLogEvent = true;
+
+    // for event log
+    private long mLastTouchUpTime = 0;
+
+    private WebViewCore.AutoFillData mAutoFillData;
+
+    private static boolean sNotificationsEnabled = true;
+
+    /**
+     * URI scheme for telephone number
+     */
+    public static final String SCHEME_TEL = "tel:";
+    /**
+     * URI scheme for email address
+     */
+    public static final String SCHEME_MAILTO = "mailto:";
+    /**
+     * URI scheme for map address
+     */
+    public static final String SCHEME_GEO = "geo:0,0?q=";
+
+    private int mBackgroundColor = Color.WHITE;
+
+    private static final long SELECT_SCROLL_INTERVAL = 1000 / 60; // 60 / second
+    private int mAutoScrollX = 0;
+    private int mAutoScrollY = 0;
+    private int mMinAutoScrollX = 0;
+    private int mMaxAutoScrollX = 0;
+    private int mMinAutoScrollY = 0;
+    private int mMaxAutoScrollY = 0;
+    private Rect mScrollingLayerBounds = new Rect();
+    private boolean mSentAutoScrollMessage = false;
+
+    // used for serializing asynchronously handled touch events.
+    private final TouchEventQueue mTouchEventQueue = new TouchEventQueue();
+
+    // Used to track whether picture updating was paused due to a window focus change.
+    private boolean mPictureUpdatePausedForFocusChange = false;
+
+    // Used to notify listeners of a new picture.
+    private PictureListener mPictureListener;
+
+    /**
+     * Refer to {@link WebView#requestFocusNodeHref(Message)} for more information
+     */
+    static class FocusNodeHref {
+        static final String TITLE = "title";
+        static final String URL = "url";
+        static final String SRC = "src";
+    }
+
+    public WebViewClassic(WebView webView, WebView.PrivateAccess privateAccess) {
+        mWebView = webView;
+        mWebViewPrivate = privateAccess;
+        mContext = webView.getContext();
+    }
+
+    /**
+     * See {@link WebViewProvider#init(Map, boolean)}
+     */
+    @Override
+    public void init(Map<String, Object> javaScriptInterfaces, boolean privateBrowsing) {
+        checkThread();
+
+        Context context = mContext;
+
+        // Used by the chrome stack to find application paths
+        JniUtil.setContext(context);
+
+        mCallbackProxy = new CallbackProxy(context, this);
+        mViewManager = new ViewManager(this);
+        L10nUtils.setApplicationContext(context.getApplicationContext());
+        mWebViewCore = new WebViewCore(context, this, mCallbackProxy, javaScriptInterfaces);
+        mDatabase = WebViewDatabase.getInstance(context);
+        mScroller = new OverScroller(context, null, 0, 0, false); //TODO Use OverScroller's flywheel
+        mZoomManager = new ZoomManager(this, mCallbackProxy);
+
+        /* The init method must follow the creation of certain member variables,
+         * such as the mZoomManager.
+         */
+        init();
+        setupPackageListener(context);
+        setupProxyListener(context);
+        setupTrustStorageListener(context);
+        updateMultiTouchSupport(context);
+
+        if (privateBrowsing) {
+            startPrivateBrowsing();
+        }
+
+        mAutoFillData = new WebViewCore.AutoFillData();
+    }
+
+    // === START: WebView Proxy binding ===
+    // Keep the webview proxy / SPI related stuff in this section, to minimize merge conflicts.
+
+    static class Factory implements WebViewFactoryProvider,  WebViewFactoryProvider.Statics {
+        @Override
+        public WebViewProvider createWebView(WebView webView, WebView.PrivateAccess privateAccess) {
+            return new WebViewClassic(webView, privateAccess);
+        }
+
+        @Override
+        public Statics getStatics() { return this; }
+
+        @Override
+        public String findAddress(String addr) {
+            return WebViewClassic.findAddress(addr);
+        }
+        @Override
+        public void setPlatformNotificationsEnabled(boolean enable) {
+            if (enable) {
+                WebViewClassic.enablePlatformNotifications();
+            } else {
+                WebViewClassic.disablePlatformNotifications();
+            }
+        }
+
+    }
+
+    // The webview that is bound to this WebViewClassic instance. Primarily needed for supplying
+    // as the first param in the WebViewClient and WebChromeClient callbacks.
+    final private WebView mWebView;
+    // Callback interface, provides priviledged access into the WebView instance.
+    final private WebView.PrivateAccess mWebViewPrivate;
+    // Cached reference to mWebView.getContext(), for convenience.
+    final private Context mContext;
+
+    /**
+     * @return The webview proxy that this classic webview is bound to.
+     */
+    public WebView getWebView() {
+        return mWebView;
+    }
+
+    @Override
+    public ViewDelegate getViewDelegate() {
+        return this;
+    }
+
+    @Override
+    public ScrollDelegate getScrollDelegate() {
+        return this;
+    }
+
+    public static WebViewClassic fromWebView(WebView webView) {
+        return webView == null ? null : (WebViewClassic) webView.getWebViewProvider();
+    }
+
+    // Accessors, purely for convenience (and to reduce code churn during webview proxy migration).
+    int getScrollX() {
+        return mWebView.getScrollX();
+    }
+
+    int getScrollY() {
+        return mWebView.getScrollY();
+    }
+
+    int getWidth() {
+        return mWebView.getWidth();
+    }
+
+    int getHeight() {
+        return mWebView.getHeight();
+    }
+
+    Context getContext() {
+        return mContext;
+    }
+
+    void invalidate() {
+        mWebView.invalidate();
+    }
+
+    // Setters for the Scroll X & Y, without invoking the onScrollChanged etc code paths.
+    void setScrollXRaw(int mScrollX) {
+        mWebViewPrivate.setScrollXRaw(mScrollX);
+    }
+
+    void setScrollYRaw(int mScrollY) {
+        mWebViewPrivate.setScrollYRaw(mScrollY);
+    }
+
+    // === END: WebView Proxy binding ===
+
+    private static class TrustStorageListener extends BroadcastReceiver {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            if (intent.getAction().equals(KeyChain.ACTION_STORAGE_CHANGED)) {
+                handleCertTrustChanged();
+            }
+        }
+    }
+    private static TrustStorageListener sTrustStorageListener;
+
+    /**
+     * Handles update to the trust storage.
+     */
+    private static void handleCertTrustChanged() {
+        // send a message for indicating trust storage change
+        WebViewCore.sendStaticMessage(EventHub.TRUST_STORAGE_UPDATED, null);
+    }
+
+    /*
+     * @param context This method expects this to be a valid context.
+     */
+    private static void setupTrustStorageListener(Context context) {
+        if (sTrustStorageListener != null ) {
+            return;
+        }
+        IntentFilter filter = new IntentFilter();
+        filter.addAction(KeyChain.ACTION_STORAGE_CHANGED);
+        sTrustStorageListener = new TrustStorageListener();
+        Intent current =
+            context.getApplicationContext().registerReceiver(sTrustStorageListener, filter);
+        if (current != null) {
+            handleCertTrustChanged();
+        }
+    }
+
+    private static class ProxyReceiver extends BroadcastReceiver {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            if (intent.getAction().equals(Proxy.PROXY_CHANGE_ACTION)) {
+                handleProxyBroadcast(intent);
+            }
+        }
+    }
+
+    /*
+     * Receiver for PROXY_CHANGE_ACTION, will be null when it is not added handling broadcasts.
+     */
+    private static ProxyReceiver sProxyReceiver;
+
+    /*
+     * @param context This method expects this to be a valid context
+     */
+    private static synchronized void setupProxyListener(Context context) {
+        if (sProxyReceiver != null || sNotificationsEnabled == false) {
+            return;
+        }
+        IntentFilter filter = new IntentFilter();
+        filter.addAction(Proxy.PROXY_CHANGE_ACTION);
+        sProxyReceiver = new ProxyReceiver();
+        Intent currentProxy = context.getApplicationContext().registerReceiver(
+                sProxyReceiver, filter);
+        if (currentProxy != null) {
+            handleProxyBroadcast(currentProxy);
+        }
+    }
+
+    /*
+     * @param context This method expects this to be a valid context
+     */
+    private static synchronized void disableProxyListener(Context context) {
+        if (sProxyReceiver == null)
+            return;
+
+        context.getApplicationContext().unregisterReceiver(sProxyReceiver);
+        sProxyReceiver = null;
+    }
+
+    private static void handleProxyBroadcast(Intent intent) {
+        ProxyProperties proxyProperties = (ProxyProperties)intent.getExtra(Proxy.EXTRA_PROXY_INFO);
+        if (proxyProperties == null || proxyProperties.getHost() == null) {
+            WebViewCore.sendStaticMessage(EventHub.PROXY_CHANGED, null);
+            return;
+        }
+        WebViewCore.sendStaticMessage(EventHub.PROXY_CHANGED, proxyProperties);
+    }
+
+    /*
+     * A variable to track if there is a receiver added for ACTION_PACKAGE_ADDED
+     * or ACTION_PACKAGE_REMOVED.
+     */
+    private static boolean sPackageInstallationReceiverAdded = false;
+
+    /*
+     * A set of Google packages we monitor for the
+     * navigator.isApplicationInstalled() API. Add additional packages as
+     * needed.
+     */
+    private static Set<String> sGoogleApps;
+    static {
+        sGoogleApps = new HashSet<String>();
+        sGoogleApps.add("com.google.android.youtube");
+    }
+
+    private static class PackageListener extends BroadcastReceiver {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            final String action = intent.getAction();
+            final String packageName = intent.getData().getSchemeSpecificPart();
+            final boolean replacing = intent.getBooleanExtra(Intent.EXTRA_REPLACING, false);
+            if (Intent.ACTION_PACKAGE_REMOVED.equals(action) && replacing) {
+                // if it is replacing, refreshPlugins() when adding
+                return;
+            }
+
+            if (sGoogleApps.contains(packageName)) {
+                if (Intent.ACTION_PACKAGE_ADDED.equals(action)) {
+                    WebViewCore.sendStaticMessage(EventHub.ADD_PACKAGE_NAME, packageName);
+                } else {
+                    WebViewCore.sendStaticMessage(EventHub.REMOVE_PACKAGE_NAME, packageName);
+                }
+            }
+
+            PluginManager pm = PluginManager.getInstance(context);
+            if (pm.containsPluginPermissionAndSignatures(packageName)) {
+                pm.refreshPlugins(Intent.ACTION_PACKAGE_ADDED.equals(action));
+            }
+        }
+    }
+
+    private void setupPackageListener(Context context) {
+
+        /*
+         * we must synchronize the instance check and the creation of the
+         * receiver to ensure that only ONE receiver exists for all WebView
+         * instances.
+         */
+        synchronized (WebViewClassic.class) {
+
+            // if the receiver already exists then we do not need to register it
+            // again
+            if (sPackageInstallationReceiverAdded) {
+                return;
+            }
+
+            IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);
+            filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
+            filter.addDataScheme("package");
+            BroadcastReceiver packageListener = new PackageListener();
+            context.getApplicationContext().registerReceiver(packageListener, filter);
+            sPackageInstallationReceiverAdded = true;
+        }
+
+        // check if any of the monitored apps are already installed
+        AsyncTask<Void, Void, Set<String>> task = new AsyncTask<Void, Void, Set<String>>() {
+
+            @Override
+            protected Set<String> doInBackground(Void... unused) {
+                Set<String> installedPackages = new HashSet<String>();
+                PackageManager pm = mContext.getPackageManager();
+                for (String name : sGoogleApps) {
+                    try {
+                        pm.getPackageInfo(name,
+                                PackageManager.GET_ACTIVITIES | PackageManager.GET_SERVICES);
+                        installedPackages.add(name);
+                    } catch (PackageManager.NameNotFoundException e) {
+                        // package not found
+                    }
+                }
+                return installedPackages;
+            }
+
+            // Executes on the UI thread
+            @Override
+            protected void onPostExecute(Set<String> installedPackages) {
+                if (mWebViewCore != null) {
+                    mWebViewCore.sendMessage(EventHub.ADD_PACKAGE_NAMES, installedPackages);
+                }
+            }
+        };
+        task.execute();
+    }
+
+    void updateMultiTouchSupport(Context context) {
+        mZoomManager.updateMultiTouchSupport(context);
+    }
+
+    private void init() {
+        OnTrimMemoryListener.init(mContext);
+        mWebView.setWillNotDraw(false);
+        mWebView.setFocusable(true);
+        mWebView.setFocusableInTouchMode(true);
+        mWebView.setClickable(true);
+        mWebView.setLongClickable(true);
+
+        final ViewConfiguration configuration = ViewConfiguration.get(mContext);
+        int slop = configuration.getScaledTouchSlop();
+        mTouchSlopSquare = slop * slop;
+        slop = configuration.getScaledDoubleTapSlop();
+        mDoubleTapSlopSquare = slop * slop;
+        final float density = mContext.getResources().getDisplayMetrics().density;
+        // use one line height, 16 based on our current default font, for how
+        // far we allow a touch be away from the edge of a link
+        mNavSlop = (int) (16 * density);
+        mZoomManager.init(density);
+        mMaximumFling = configuration.getScaledMaximumFlingVelocity();
+
+        // Compute the inverse of the density squared.
+        DRAG_LAYER_INVERSE_DENSITY_SQUARED = 1 / (density * density);
+
+        mOverscrollDistance = configuration.getScaledOverscrollDistance();
+        mOverflingDistance = configuration.getScaledOverflingDistance();
+
+        setScrollBarStyle(mWebViewPrivate.super_getScrollBarStyle());
+        // Initially use a size of two, since the user is likely to only hold
+        // down two keys at a time (shift + another key)
+        mKeysPressed = new Vector<Integer>(2);
+        mHTML5VideoViewProxy = null ;
+    }
+
+    @Override
+    public boolean shouldDelayChildPressedState() {
+        return true;
+    }
+
+    /**
+     * Adds accessibility APIs to JavaScript.
+     *
+     * Note: This method is responsible to performing the necessary
+     *       check if the accessibility APIs should be exposed.
+     */
+    private void addAccessibilityApisToJavaScript() {
+        if (AccessibilityManager.getInstance(mContext).isEnabled()
+                && getSettings().getJavaScriptEnabled()) {
+            // exposing the TTS for now ...
+            final Context ctx = mContext;
+            if (ctx != null) {
+                final String packageName = ctx.getPackageName();
+                if (packageName != null) {
+                    mTextToSpeech = new TextToSpeech(ctx, null, null,
+                            packageName + ".**webview**", true);
+                    addJavascriptInterface(mTextToSpeech, ALIAS_ACCESSIBILITY_JS_INTERFACE);
+                }
+            }
+        }
+    }
+
+    /**
+     * Removes accessibility APIs from JavaScript.
+     */
+    private void removeAccessibilityApisFromJavaScript() {
+        // exposing the TTS for now ...
+        if (mTextToSpeech != null) {
+            removeJavascriptInterface(ALIAS_ACCESSIBILITY_JS_INTERFACE);
+            mTextToSpeech.shutdown();
+            mTextToSpeech = null;
+        }
+    }
+
+    @Override
+    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
+        info.setScrollable(isScrollableForAccessibility());
+    }
+
+    @Override
+    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
+        event.setScrollable(isScrollableForAccessibility());
+        event.setScrollX(getScrollX());
+        event.setScrollY(getScrollY());
+        final int convertedContentWidth = contentToViewX(getContentWidth());
+        final int adjustedViewWidth = getWidth() - mWebView.getPaddingLeft()
+                - mWebView.getPaddingLeft();
+        event.setMaxScrollX(Math.max(convertedContentWidth - adjustedViewWidth, 0));
+        final int convertedContentHeight = contentToViewY(getContentHeight());
+        final int adjustedViewHeight = getHeight() - mWebView.getPaddingTop()
+                - mWebView.getPaddingBottom();
+        event.setMaxScrollY(Math.max(convertedContentHeight - adjustedViewHeight, 0));
+    }
+
+    private boolean isScrollableForAccessibility() {
+        return (contentToViewX(getContentWidth()) > getWidth() - mWebView.getPaddingLeft()
+                - mWebView.getPaddingRight()
+                || contentToViewY(getContentHeight()) > getHeight() - mWebView.getPaddingTop()
+                - mWebView.getPaddingBottom());
+    }
+
+    @Override
+    public void setOverScrollMode(int mode) {
+        if (mode != View.OVER_SCROLL_NEVER) {
+            if (mOverScrollGlow == null) {
+                mOverScrollGlow = new OverScrollGlow(this);
+            }
+        } else {
+            mOverScrollGlow = null;
+        }
+    }
+
+    /* package */ void adjustDefaultZoomDensity(int zoomDensity) {
+        final float density = mContext.getResources().getDisplayMetrics().density
+                * 100 / zoomDensity;
+        updateDefaultZoomDensity(density);
+    }
+
+    /* package */ void updateDefaultZoomDensity(float density) {
+        mNavSlop = (int) (16 * density);
+        mZoomManager.updateDefaultZoomDensity(density);
+    }
+
+    /* package */ boolean onSavePassword(String schemePlusHost, String username,
+            String password, final Message resumeMsg) {
+       boolean rVal = false;
+       if (resumeMsg == null) {
+           // null resumeMsg implies saving password silently
+           mDatabase.setUsernamePassword(schemePlusHost, username, password);
+       } else {
+            final Message remember = mPrivateHandler.obtainMessage(
+                    REMEMBER_PASSWORD);
+            remember.getData().putString("host", schemePlusHost);
+            remember.getData().putString("username", username);
+            remember.getData().putString("password", password);
+            remember.obj = resumeMsg;
+
+            final Message neverRemember = mPrivateHandler.obtainMessage(
+                    NEVER_REMEMBER_PASSWORD);
+            neverRemember.getData().putString("host", schemePlusHost);
+            neverRemember.getData().putString("username", username);
+            neverRemember.getData().putString("password", password);
+            neverRemember.obj = resumeMsg;
+
+            new AlertDialog.Builder(mContext)
+                    .setTitle(com.android.internal.R.string.save_password_label)
+                    .setMessage(com.android.internal.R.string.save_password_message)
+                    .setPositiveButton(com.android.internal.R.string.save_password_notnow,
+                    new DialogInterface.OnClickListener() {
+                        @Override
+                        public void onClick(DialogInterface dialog, int which) {
+                            resumeMsg.sendToTarget();
+                        }
+                    })
+                    .setNeutralButton(com.android.internal.R.string.save_password_remember,
+                    new DialogInterface.OnClickListener() {
+                        @Override
+                        public void onClick(DialogInterface dialog, int which) {
+                            remember.sendToTarget();
+                        }
+                    })
+                    .setNegativeButton(com.android.internal.R.string.save_password_never,
+                    new DialogInterface.OnClickListener() {
+                        @Override
+                        public void onClick(DialogInterface dialog, int which) {
+                            neverRemember.sendToTarget();
+                        }
+                    })
+                    .setOnCancelListener(new OnCancelListener() {
+                        @Override
+                        public void onCancel(DialogInterface dialog) {
+                            resumeMsg.sendToTarget();
+                        }
+                    }).show();
+            // Return true so that WebViewCore will pause while the dialog is
+            // up.
+            rVal = true;
+        }
+       return rVal;
+    }
+
+    @Override
+    public void setScrollBarStyle(int style) {
+        if (style == View.SCROLLBARS_INSIDE_INSET
+                || style == View.SCROLLBARS_OUTSIDE_INSET) {
+            mOverlayHorizontalScrollbar = mOverlayVerticalScrollbar = false;
+        } else {
+            mOverlayHorizontalScrollbar = mOverlayVerticalScrollbar = true;
+        }
+    }
+
+    /**
+     * See {@link WebView#setHorizontalScrollbarOverlay(boolean)}
+     */
+    @Override
+    public void setHorizontalScrollbarOverlay(boolean overlay) {
+        checkThread();
+        mOverlayHorizontalScrollbar = overlay;
+    }
+
+    /**
+     * See {@link WebView#setVerticalScrollbarOverlay(boolean)
+     */
+    @Override
+    public void setVerticalScrollbarOverlay(boolean overlay) {
+        checkThread();
+        mOverlayVerticalScrollbar = overlay;
+    }
+
+    /**
+     * See {@link WebView#overlayHorizontalScrollbar()}
+     */
+    @Override
+    public boolean overlayHorizontalScrollbar() {
+        checkThread();
+        return mOverlayHorizontalScrollbar;
+    }
+
+    /**
+     * See {@link WebView#overlayVerticalScrollbar()}
+     */
+    @Override
+    public boolean overlayVerticalScrollbar() {
+        checkThread();
+        return mOverlayVerticalScrollbar;
+    }
+
+    /*
+     * Return the width of the view where the content of WebView should render
+     * to.
+     * Note: this can be called from WebCoreThread.
+     */
+    /* package */ int getViewWidth() {
+        if (!mWebView.isVerticalScrollBarEnabled() || mOverlayVerticalScrollbar) {
+            return getWidth();
+        } else {
+            return Math.max(0, getWidth() - mWebView.getVerticalScrollbarWidth());
+        }
+    }
+
+    // Interface to enable the browser to override title bar handling.
+    public interface TitleBarDelegate {
+        int getTitleHeight();
+        public void onSetEmbeddedTitleBar(final View title);
+    }
+
+    /**
+     * Returns the height (in pixels) of the embedded title bar (if any). Does not care about
+     * scrolling
+     * @hide
+     */
+    protected int getTitleHeight() {
+        if (mWebView instanceof TitleBarDelegate) {
+            return ((TitleBarDelegate) mWebView).getTitleHeight();
+        }
+        return mTitleBar != null ? mTitleBar.getHeight() : 0;
+    }
+
+    /**
+     * See {@link WebView#getVisibleTitleHeight()}
+     */
+    @Override
+    @Deprecated
+    public int getVisibleTitleHeight() {
+        // Actually, this method returns the height of the embedded title bar if one is set via the
+        // hidden setEmbeddedTitleBar method.
+        checkThread();
+        return getVisibleTitleHeightImpl();
+    }
+
+    private int getVisibleTitleHeightImpl() {
+        // need to restrict mScrollY due to over scroll
+        return Math.max(getTitleHeight() - Math.max(0, getScrollY()),
+                getOverlappingActionModeHeight());
+    }
+
+    private int mCachedOverlappingActionModeHeight = -1;
+
+    private int getOverlappingActionModeHeight() {
+        if (mFindCallback == null) {
+            return 0;
+        }
+        if (mCachedOverlappingActionModeHeight < 0) {
+            mWebView.getGlobalVisibleRect(mGlobalVisibleRect, mGlobalVisibleOffset);
+            mCachedOverlappingActionModeHeight = Math.max(0,
+                    mFindCallback.getActionModeGlobalBottom() - mGlobalVisibleRect.top);
+        }
+        return mCachedOverlappingActionModeHeight;
+    }
+
+    /*
+     * Return the height of the view where the content of WebView should render
+     * to.  Note that this excludes mTitleBar, if there is one.
+     * Note: this can be called from WebCoreThread.
+     */
+    /* package */ int getViewHeight() {
+        return getViewHeightWithTitle() - getVisibleTitleHeightImpl();
+    }
+
+    int getViewHeightWithTitle() {
+        int height = getHeight();
+        if (mWebView.isHorizontalScrollBarEnabled() && !mOverlayHorizontalScrollbar) {
+            height -= mWebViewPrivate.getHorizontalScrollbarHeight();
+        }
+        return height;
+    }
+
+    /**
+     * See {@link WebView#getCertificate()}
+     */
+    @Override
+    public SslCertificate getCertificate() {
+        checkThread();
+        return mCertificate;
+    }
+
+    /**
+     * See {@link WebView#setCertificate(SslCertificate)}
+     */
+    @Override
+    public void setCertificate(SslCertificate certificate) {
+        checkThread();
+        if (DebugFlags.WEB_VIEW) {
+            Log.v(LOGTAG, "setCertificate=" + certificate);
+        }
+        // here, the certificate can be null (if the site is not secure)
+        mCertificate = certificate;
+    }
+
+    //-------------------------------------------------------------------------
+    // Methods called by activity
+    //-------------------------------------------------------------------------
+
+    /**
+     * See {@link WebView#savePassword(String, String, String)}
+     */
+    @Override
+    public void savePassword(String host, String username, String password) {
+        checkThread();
+        mDatabase.setUsernamePassword(host, username, password);
+    }
+
+    /**
+     * See {@link WebView#setHttpAuthUsernamePassword(String, String, String, String)}
+     */
+    @Override
+    public void setHttpAuthUsernamePassword(String host, String realm,
+            String username, String password) {
+        checkThread();
+        mDatabase.setHttpAuthUsernamePassword(host, realm, username, password);
+    }
+
+    /**
+     * See {@link WebView#getHttpAuthUsernamePassword(String, String)}
+     */
+    @Override
+    public String[] getHttpAuthUsernamePassword(String host, String realm) {
+        checkThread();
+        return mDatabase.getHttpAuthUsernamePassword(host, realm);
+    }
+
+    /**
+     * Remove Find or Select ActionModes, if active.
+     */
+    private void clearActionModes() {
+        if (mSelectCallback != null) {
+            mSelectCallback.finish();
+        }
+        if (mFindCallback != null) {
+            mFindCallback.finish();
+        }
+    }
+
+    /**
+     * Called to clear state when moving from one page to another, or changing
+     * in some other way that makes elements associated with the current page
+     * (such as ActionModes) no longer relevant.
+     */
+    private void clearHelpers() {
+        hideSoftKeyboard();
+        clearActionModes();
+        dismissFullScreenMode();
+        cancelSelectDialog();
+    }
+
+    private void cancelSelectDialog() {
+        if (mListBoxDialog != null) {
+            mListBoxDialog.cancel();
+            mListBoxDialog = null;
+        }
+    }
+
+    /**
+     * See {@link WebView#destroy()}
+     */
+    @Override
+    public void destroy() {
+        checkThread();
+        destroyImpl();
+    }
+
+    private void destroyImpl() {
+        clearHelpers();
+        if (mListBoxDialog != null) {
+            mListBoxDialog.dismiss();
+            mListBoxDialog = null;
+        }
+        if (mNativeClass != 0) nativeStopGL();
+        if (mWebViewCore != null) {
+            // Tell WebViewCore to destroy itself
+            synchronized (this) {
+                WebViewCore webViewCore = mWebViewCore;
+                mWebViewCore = null; // prevent using partial webViewCore
+                webViewCore.destroy();
+            }
+            // Remove any pending messages that might not be serviced yet.
+            mPrivateHandler.removeCallbacksAndMessages(null);
+        }
+        if (mNativeClass != 0) {
+            nativeDestroy();
+            mNativeClass = 0;
+        }
+    }
+
+    /**
+     * See {@link WebView#enablePlatformNotifications()}
+     */
+    @Deprecated
+    public static void enablePlatformNotifications() {
+        checkThread();
+        synchronized (WebViewClassic.class) {
+            sNotificationsEnabled = true;
+            Context context = JniUtil.getContext();
+            if (context != null)
+                setupProxyListener(context);
+        }
+    }
+
+    /**
+     * See {@link WebView#disablePlatformNotifications()}
+     */
+    @Deprecated
+    public static void disablePlatformNotifications() {
+        checkThread();
+        synchronized (WebViewClassic.class) {
+            sNotificationsEnabled = false;
+            Context context = JniUtil.getContext();
+            if (context != null)
+                disableProxyListener(context);
+        }
+    }
+
+    /**
+     * Sets JavaScript engine flags.
+     *
+     * @param flags JS engine flags in a String
+     *
+     * @hide This is an implementation detail.
+     */
+    public void setJsFlags(String flags) {
+        checkThread();
+        mWebViewCore.sendMessage(EventHub.SET_JS_FLAGS, flags);
+    }
+
+    /**
+     * See {@link WebView#setNetworkAvailable(boolean)}
+     */
+    @Override
+    public void setNetworkAvailable(boolean networkUp) {
+        checkThread();
+        mWebViewCore.sendMessage(EventHub.SET_NETWORK_STATE,
+                networkUp ? 1 : 0, 0);
+    }
+
+    /**
+     * Inform WebView about the current network type.
+     * {@hide}
+     */
+    public void setNetworkType(String type, String subtype) {
+        checkThread();
+        Map<String, String> map = new HashMap<String, String>();
+        map.put("type", type);
+        map.put("subtype", subtype);
+        mWebViewCore.sendMessage(EventHub.SET_NETWORK_TYPE, map);
+    }
+
+    /**
+     * See {@link WebView#saveState(Bundle)}
+     */
+    @Override
+    public WebBackForwardList saveState(Bundle outState) {
+        checkThread();
+        if (outState == null) {
+            return null;
+        }
+        // We grab a copy of the back/forward list because a client of WebView
+        // may have invalidated the history list by calling clearHistory.
+        WebBackForwardList list = copyBackForwardList();
+        final int currentIndex = list.getCurrentIndex();
+        final int size = list.getSize();
+        // We should fail saving the state if the list is empty or the index is
+        // not in a valid range.
+        if (currentIndex < 0 || currentIndex >= size || size == 0) {
+            return null;
+        }
+        outState.putInt("index", currentIndex);
+        // FIXME: This should just be a byte[][] instead of ArrayList but
+        // Parcel.java does not have the code to handle multi-dimensional
+        // arrays.
+        ArrayList<byte[]> history = new ArrayList<byte[]>(size);
+        for (int i = 0; i < size; i++) {
+            WebHistoryItem item = list.getItemAtIndex(i);
+            if (null == item) {
+                // FIXME: this shouldn't happen
+                // need to determine how item got set to null
+                Log.w(LOGTAG, "saveState: Unexpected null history item.");
+                return null;
+            }
+            byte[] data = item.getFlattenedData();
+            if (data == null) {
+                // It would be very odd to not have any data for a given history
+                // item. And we will fail to rebuild the history list without
+                // flattened data.
+                return null;
+            }
+            history.add(data);
+        }
+        outState.putSerializable("history", history);
+        if (mCertificate != null) {
+            outState.putBundle("certificate",
+                               SslCertificate.saveState(mCertificate));
+        }
+        outState.putBoolean("privateBrowsingEnabled", isPrivateBrowsingEnabled());
+        mZoomManager.saveZoomState(outState);
+        return list;
+    }
+
+    /**
+     * See {@link WebView#savePicture(Bundle, File)}
+     */
+    @Override
+    @Deprecated
+    public boolean savePicture(Bundle b, final File dest) {
+        checkThread();
+        if (dest == null || b == null) {
+            return false;
+        }
+        final Picture p = capturePicture();
+        // Use a temporary file while writing to ensure the destination file
+        // contains valid data.
+        final File temp = new File(dest.getPath() + ".writing");
+        new Thread(new Runnable() {
+            @Override
+            public void run() {
+                FileOutputStream out = null;
+                try {
+                    out = new FileOutputStream(temp);
+                    p.writeToStream(out);
+                    // Writing the picture succeeded, rename the temporary file
+                    // to the destination.
+                    temp.renameTo(dest);
+                } catch (Exception e) {
+                    // too late to do anything about it.
+                } finally {
+                    if (out != null) {
+                        try {
+                            out.close();
+                        } catch (Exception e) {
+                            // Can't do anything about that
+                        }
+                    }
+                    temp.delete();
+                }
+            }
+        }).start();
+        // now update the bundle
+        b.putInt("scrollX", getScrollX());
+        b.putInt("scrollY", getScrollY());
+        mZoomManager.saveZoomState(b);
+        return true;
+    }
+
+    private void restoreHistoryPictureFields(Picture p, Bundle b) {
+        int sx = b.getInt("scrollX", 0);
+        int sy = b.getInt("scrollY", 0);
+
+        mDrawHistory = true;
+        mHistoryPicture = p;
+
+        setScrollXRaw(sx);
+        setScrollYRaw(sy);
+        mZoomManager.restoreZoomState(b);
+        final float scale = mZoomManager.getScale();
+        mHistoryWidth = Math.round(p.getWidth() * scale);
+        mHistoryHeight = Math.round(p.getHeight() * scale);
+
+        invalidate();
+    }
+
+    /**
+     * See {@link WebView#restorePicture(Bundle, File)};
+     */
+    @Override
+    @Deprecated
+    public boolean restorePicture(Bundle b, File src) {
+        checkThread();
+        if (src == null || b == null) {
+            return false;
+        }
+        if (!src.exists()) {
+            return false;
+        }
+        try {
+            final FileInputStream in = new FileInputStream(src);
+            final Bundle copy = new Bundle(b);
+            new Thread(new Runnable() {
+                @Override
+                public void run() {
+                    try {
+                        final Picture p = Picture.createFromStream(in);
+                        if (p != null) {
+                            // Post a runnable on the main thread to update the
+                            // history picture fields.
+                            mPrivateHandler.post(new Runnable() {
+                                @Override
+                                public void run() {
+                                    restoreHistoryPictureFields(p, copy);
+                                }
+                            });
+                        }
+                    } finally {
+                        try {
+                            in.close();
+                        } catch (Exception e) {
+                            // Nothing we can do now.
+                        }
+                    }
+                }
+            }).start();
+        } catch (FileNotFoundException e){
+            e.printStackTrace();
+        }
+        return true;
+    }
+
+    /**
+     * Saves the view data to the output stream. The output is highly
+     * version specific, and may not be able to be loaded by newer versions
+     * of WebView.
+     * @param stream The {@link OutputStream} to save to
+     * @return True if saved successfully
+     * @hide
+     */
+    public boolean saveViewState(OutputStream stream) {
+        try {
+            return ViewStateSerializer.serializeViewState(stream, this);
+        } catch (IOException e) {
+            Log.w(LOGTAG, "Failed to saveViewState", e);
+        }
+        return false;
+    }
+
+    /**
+     * Loads the view data from the input stream. See
+     * {@link #saveViewState(OutputStream)} for more information.
+     * @param stream The {@link InputStream} to load from
+     * @return True if loaded successfully
+     * @hide
+     */
+    public boolean loadViewState(InputStream stream) {
+        try {
+            mLoadedPicture = ViewStateSerializer.deserializeViewState(stream, this);
+            mBlockWebkitViewMessages = true;
+            setNewPicture(mLoadedPicture, true);
+            mLoadedPicture.mViewState = null;
+            return true;
+        } catch (IOException e) {
+            Log.w(LOGTAG, "Failed to loadViewState", e);
+        }
+        return false;
+    }
+
+    /**
+     * Clears the view state set with {@link #loadViewState(InputStream)}.
+     * This WebView will then switch to showing the content from webkit
+     */
+    public void clearViewState() {
+        mBlockWebkitViewMessages = false;
+        mLoadedPicture = null;
+        invalidate();
+    }
+
+    /**
+     * See {@link WebView#restoreState(Bundle)}
+     */
+    @Override
+    public WebBackForwardList restoreState(Bundle inState) {
+        checkThread();
+        WebBackForwardList returnList = null;
+        if (inState == null) {
+            return returnList;
+        }
+        if (inState.containsKey("index") && inState.containsKey("history")) {
+            mCertificate = SslCertificate.restoreState(
+                inState.getBundle("certificate"));
+
+            final WebBackForwardList list = mCallbackProxy.getBackForwardList();
+            final int index = inState.getInt("index");
+            // We can't use a clone of the list because we need to modify the
+            // shared copy, so synchronize instead to prevent concurrent
+            // modifications.
+            synchronized (list) {
+                final List<byte[]> history =
+                        (List<byte[]>) inState.getSerializable("history");
+                final int size = history.size();
+                // Check the index bounds so we don't crash in native code while
+                // restoring the history index.
+                if (index < 0 || index >= size) {
+                    return null;
+                }
+                for (int i = 0; i < size; i++) {
+                    byte[] data = history.remove(0);
+                    if (data == null) {
+                        // If we somehow have null data, we cannot reconstruct
+                        // the item and thus our history list cannot be rebuilt.
+                        return null;
+                    }
+                    WebHistoryItem item = new WebHistoryItem(data);
+                    list.addHistoryItem(item);
+                }
+                // Grab the most recent copy to return to the caller.
+                returnList = copyBackForwardList();
+                // Update the copy to have the correct index.
+                returnList.setCurrentIndex(index);
+            }
+            // Restore private browsing setting.
+            if (inState.getBoolean("privateBrowsingEnabled")) {
+                getSettings().setPrivateBrowsingEnabled(true);
+            }
+            mZoomManager.restoreZoomState(inState);
+            // Remove all pending messages because we are restoring previous
+            // state.
+            mWebViewCore.removeMessages();
+            // Send a restore state message.
+            mWebViewCore.sendMessage(EventHub.RESTORE_STATE, index);
+        }
+        return returnList;
+    }
+
+    /**
+     * See {@link WebView#loadUrl(String, Map)}
+     */
+    @Override
+    public void loadUrl(String url, Map<String, String> additionalHttpHeaders) {
+        checkThread();
+        loadUrlImpl(url, additionalHttpHeaders);
+    }
+
+    private void loadUrlImpl(String url, Map<String, String> extraHeaders) {
+        switchOutDrawHistory();
+        WebViewCore.GetUrlData arg = new WebViewCore.GetUrlData();
+        arg.mUrl = url;
+        arg.mExtraHeaders = extraHeaders;
+        mWebViewCore.sendMessage(EventHub.LOAD_URL, arg);
+        clearHelpers();
+    }
+
+    /**
+     * See {@link WebView#loadUrl(String)}
+     */
+    @Override
+    public void loadUrl(String url) {
+        checkThread();
+        loadUrlImpl(url);
+    }
+
+    private void loadUrlImpl(String url) {
+        if (url == null) {
+            return;
+        }
+        loadUrlImpl(url, null);
+    }
+
+    /**
+     * See {@link WebView#postUrl(String, byte[])}
+     */
+    @Override
+    public void postUrl(String url, byte[] postData) {
+        checkThread();
+        if (URLUtil.isNetworkUrl(url)) {
+            switchOutDrawHistory();
+            WebViewCore.PostUrlData arg = new WebViewCore.PostUrlData();
+            arg.mUrl = url;
+            arg.mPostData = postData;
+            mWebViewCore.sendMessage(EventHub.POST_URL, arg);
+            clearHelpers();
+        } else {
+            loadUrlImpl(url);
+        }
+    }
+
+    /**
+     * See {@link WebView#loadData(String, String, String)}
+     */
+    @Override
+    public void loadData(String data, String mimeType, String encoding) {
+        checkThread();
+        loadDataImpl(data, mimeType, encoding);
+    }
+
+    private void loadDataImpl(String data, String mimeType, String encoding) {
+        StringBuilder dataUrl = new StringBuilder("data:");
+        dataUrl.append(mimeType);
+        if ("base64".equals(encoding)) {
+            dataUrl.append(";base64");
+        }
+        dataUrl.append(",");
+        dataUrl.append(data);
+        loadUrlImpl(dataUrl.toString());
+    }
+
+    /**
+     * See {@link WebView#loadDataWithBaseURL(String, String, String, String, String)}
+     */
+    @Override
+    public void loadDataWithBaseURL(String baseUrl, String data,
+            String mimeType, String encoding, String historyUrl) {
+        checkThread();
+
+        if (baseUrl != null && baseUrl.toLowerCase().startsWith("data:")) {
+            loadDataImpl(data, mimeType, encoding);
+            return;
+        }
+        switchOutDrawHistory();
+        WebViewCore.BaseUrlData arg = new WebViewCore.BaseUrlData();
+        arg.mBaseUrl = baseUrl;
+        arg.mData = data;
+        arg.mMimeType = mimeType;
+        arg.mEncoding = encoding;
+        arg.mHistoryUrl = historyUrl;
+        mWebViewCore.sendMessage(EventHub.LOAD_DATA, arg);
+        clearHelpers();
+    }
+
+    /**
+     * See {@link WebView#saveWebArchive(String)}
+     */
+    @Override
+    public void saveWebArchive(String filename) {
+        checkThread();
+        saveWebArchiveImpl(filename, false, null);
+    }
+
+    /* package */ static class SaveWebArchiveMessage {
+        SaveWebArchiveMessage (String basename, boolean autoname, ValueCallback<String> callback) {
+            mBasename = basename;
+            mAutoname = autoname;
+            mCallback = callback;
+        }
+
+        /* package */ final String mBasename;
+        /* package */ final boolean mAutoname;
+        /* package */ final ValueCallback<String> mCallback;
+        /* package */ String mResultFile;
+    }
+
+    /**
+     * See {@link WebView#saveWebArchive(String, boolean, ValueCallback)}
+     */
+    @Override
+    public void saveWebArchive(String basename, boolean autoname, ValueCallback<String> callback) {
+        checkThread();
+        saveWebArchiveImpl(basename, autoname, callback);
+    }
+
+    private void saveWebArchiveImpl(String basename, boolean autoname,
+            ValueCallback<String> callback) {
+        mWebViewCore.sendMessage(EventHub.SAVE_WEBARCHIVE,
+            new SaveWebArchiveMessage(basename, autoname, callback));
+    }
+
+    /**
+     * See {@link WebView#stopLoading()}
+     */
+    @Override
+    public void stopLoading() {
+        checkThread();
+        // TODO: should we clear all the messages in the queue before sending
+        // STOP_LOADING?
+        switchOutDrawHistory();
+        mWebViewCore.sendMessage(EventHub.STOP_LOADING);
+    }
+
+    /**
+     * See {@link WebView#reload()}
+     */
+    @Override
+    public void reload() {
+        checkThread();
+        clearHelpers();
+        switchOutDrawHistory();
+        mWebViewCore.sendMessage(EventHub.RELOAD);
+    }
+
+    /**
+     * See {@link WebView#canGoBack()}
+     */
+    @Override
+    public boolean canGoBack() {
+        checkThread();
+        WebBackForwardList l = mCallbackProxy.getBackForwardList();
+        synchronized (l) {
+            if (l.getClearPending()) {
+                return false;
+            } else {
+                return l.getCurrentIndex() > 0;
+            }
+        }
+    }
+
+    /**
+     * See {@link WebView#goBack()}
+     */
+    @Override
+    public void goBack() {
+        checkThread();
+        goBackOrForwardImpl(-1);
+    }
+
+    /**
+     * See {@link WebView#canGoForward()}
+     */
+    @Override
+    public boolean canGoForward() {
+        checkThread();
+        WebBackForwardList l = mCallbackProxy.getBackForwardList();
+        synchronized (l) {
+            if (l.getClearPending()) {
+                return false;
+            } else {
+                return l.getCurrentIndex() < l.getSize() - 1;
+            }
+        }
+    }
+
+    /**
+     * See {@link WebView#goForward()}
+     */
+    @Override
+    public void goForward() {
+        checkThread();
+        goBackOrForwardImpl(1);
+    }
+
+    /**
+     * See {@link WebView#canGoBackOrForward(int)}
+     */
+    @Override
+    public boolean canGoBackOrForward(int steps) {
+        checkThread();
+        WebBackForwardList l = mCallbackProxy.getBackForwardList();
+        synchronized (l) {
+            if (l.getClearPending()) {
+                return false;
+            } else {
+                int newIndex = l.getCurrentIndex() + steps;
+                return newIndex >= 0 && newIndex < l.getSize();
+            }
+        }
+    }
+
+    /**
+     * See {@link WebView#goBackOrForward(int)}
+     */
+    @Override
+    public void goBackOrForward(int steps) {
+        checkThread();
+        goBackOrForwardImpl(steps);
+    }
+
+    private void goBackOrForwardImpl(int steps) {
+        goBackOrForward(steps, false);
+    }
+
+    private void goBackOrForward(int steps, boolean ignoreSnapshot) {
+        if (steps != 0) {
+            clearHelpers();
+            mWebViewCore.sendMessage(EventHub.GO_BACK_FORWARD, steps,
+                    ignoreSnapshot ? 1 : 0);
+        }
+    }
+
+    /**
+     * See {@link WebView#isPrivateBrowsingEnabled()}
+     */
+    @Override
+    public boolean isPrivateBrowsingEnabled() {
+        checkThread();
+        return getSettings().isPrivateBrowsingEnabled();
+    }
+
+    private void startPrivateBrowsing() {
+        getSettings().setPrivateBrowsingEnabled(true);
+    }
+
+    private boolean extendScroll(int y) {
+        int finalY = mScroller.getFinalY();
+        int newY = pinLocY(finalY + y);
+        if (newY == finalY) return false;
+        mScroller.setFinalY(newY);
+        mScroller.extendDuration(computeDuration(0, y));
+        return true;
+    }
+
+    /**
+     * See {@link WebView#pageUp(boolean)}
+     */
+    @Override
+    public boolean pageUp(boolean top) {
+        checkThread();
+        if (mNativeClass == 0) {
+            return false;
+        }
+        if (top) {
+            // go to the top of the document
+            return pinScrollTo(getScrollX(), 0, true, 0);
+        }
+        // Page up
+        int h = getHeight();
+        int y;
+        if (h > 2 * PAGE_SCROLL_OVERLAP) {
+            y = -h + PAGE_SCROLL_OVERLAP;
+        } else {
+            y = -h / 2;
+        }
+        return mScroller.isFinished() ? pinScrollBy(0, y, true, 0)
+                : extendScroll(y);
+    }
+
+    /**
+     * See {@link WebView#pageDown(boolean)}
+     */
+    @Override
+    public boolean pageDown(boolean bottom) {
+        checkThread();
+        if (mNativeClass == 0) {
+            return false;
+        }
+        if (bottom) {
+            return pinScrollTo(getScrollX(), computeRealVerticalScrollRange(), true, 0);
+        }
+        // Page down.
+        int h = getHeight();
+        int y;
+        if (h > 2 * PAGE_SCROLL_OVERLAP) {
+            y = h - PAGE_SCROLL_OVERLAP;
+        } else {
+            y = h / 2;
+        }
+        return mScroller.isFinished() ? pinScrollBy(0, y, true, 0)
+                : extendScroll(y);
+    }
+
+    /**
+     * See {@link WebView#clearView()}
+     */
+    @Override
+    public void clearView() {
+        checkThread();
+        mContentWidth = 0;
+        mContentHeight = 0;
+        setBaseLayer(0, null, false, false);
+        mWebViewCore.sendMessage(EventHub.CLEAR_CONTENT);
+    }
+
+    /**
+     * See {@link WebView#capturePicture()}
+     */
+    @Override
+    public Picture capturePicture() {
+        checkThread();
+        if (mNativeClass == 0) return null;
+        Picture result = new Picture();
+        nativeCopyBaseContentToPicture(result);
+        return result;
+    }
+
+    /**
+     * See {@link WebView#getScale()}
+     */
+    @Override
+    public float getScale() {
+        checkThread();
+        return mZoomManager.getScale();
+    }
+
+    /**
+     * Compute the reading level scale of the WebView
+     * @param scale The current scale.
+     * @return The reading level scale.
+     */
+    /*package*/ float computeReadingLevelScale(float scale) {
+        return mZoomManager.computeReadingLevelScale(scale);
+    }
+
+    /**
+     * See {@link WebView#setInitialScale(int)}
+     */
+    @Override
+    public void setInitialScale(int scaleInPercent) {
+        checkThread();
+        mZoomManager.setInitialScaleInPercent(scaleInPercent);
+    }
+
+    /**
+     * See {@link WebView#invokeZoomPicker()}
+     */
+    @Override
+    public void invokeZoomPicker() {
+        checkThread();
+        if (!getSettings().supportZoom()) {
+            Log.w(LOGTAG, "This WebView doesn't support zoom.");
+            return;
+        }
+        clearHelpers();
+        mZoomManager.invokeZoomPicker();
+    }
+
+    /**
+     * See {@link WebView#getHitTestResult()}
+     */
+    @Override
+    public HitTestResult getHitTestResult() {
+        checkThread();
+        return mInitialHitTestResult;
+    }
+
+    // No left edge for double-tap zoom alignment
+    static final int NO_LEFTEDGE = -1;
+
+    int getBlockLeftEdge(int x, int y, float readingScale) {
+        float invReadingScale = 1.0f / readingScale;
+        int readingWidth = (int) (getViewWidth() * invReadingScale);
+        int left = NO_LEFTEDGE;
+        if (mFocusedNode != null) {
+            final int length = mFocusedNode.mEnclosingParentRects.length;
+            for (int i = 0; i < length; i++) {
+                Rect rect = mFocusedNode.mEnclosingParentRects[i];
+                if (rect.width() < mFocusedNode.mHitTestSlop) {
+                    // ignore bounding boxes that are too small
+                    continue;
+                } else if (left != NO_LEFTEDGE && rect.width() > readingWidth) {
+                    // stop when bounding box doesn't fit the screen width
+                    // at reading scale
+                    break;
+                }
+
+                left = rect.left;
+            }
+        }
+
+        return left;
+    }
+
+    /**
+     * See {@link WebView#requestFocusNodeHref(Message)}
+     */
+    @Override
+    public void requestFocusNodeHref(Message hrefMsg) {
+        checkThread();
+        if (hrefMsg == null) {
+            return;
+        }
+        int contentX = viewToContentX(mLastTouchX + getScrollX());
+        int contentY = viewToContentY(mLastTouchY + getScrollY());
+        if (mFocusedNode != null && mFocusedNode.mHitTestX == contentX
+                && mFocusedNode.mHitTestY == contentY) {
+            hrefMsg.getData().putString(FocusNodeHref.URL, mFocusedNode.mLinkUrl);
+            hrefMsg.getData().putString(FocusNodeHref.TITLE, mFocusedNode.mAnchorText);
+            hrefMsg.getData().putString(FocusNodeHref.SRC, mFocusedNode.mImageUrl);
+            hrefMsg.sendToTarget();
+            return;
+        }
+        mWebViewCore.sendMessage(EventHub.REQUEST_CURSOR_HREF,
+                contentX, contentY, hrefMsg);
+    }
+
+    /**
+     * See {@link WebView#requestImageRef(Message)}
+     */
+    @Override
+    public void requestImageRef(Message msg) {
+        checkThread();
+        if (0 == mNativeClass) return; // client isn't initialized
+        String url = mFocusedNode != null ? mFocusedNode.mImageUrl : null;
+        Bundle data = msg.getData();
+        data.putString("url", url);
+        msg.setData(data);
+        msg.sendToTarget();
+    }
+
+    static int pinLoc(int x, int viewMax, int docMax) {
+//        Log.d(LOGTAG, "-- pinLoc " + x + " " + viewMax + " " + docMax);
+        if (docMax < viewMax) {   // the doc has room on the sides for "blank"
+            // pin the short document to the top/left of the screen
+            x = 0;
+//            Log.d(LOGTAG, "--- center " + x);
+        } else if (x < 0) {
+            x = 0;
+//            Log.d(LOGTAG, "--- zero");
+        } else if (x + viewMax > docMax) {
+            x = docMax - viewMax;
+//            Log.d(LOGTAG, "--- pin " + x);
+        }
+        return x;
+    }
+
+    // Expects x in view coordinates
+    int pinLocX(int x) {
+        if (mInOverScrollMode) return x;
+        return pinLoc(x, getViewWidth(), computeRealHorizontalScrollRange());
+    }
+
+    // Expects y in view coordinates
+    int pinLocY(int y) {
+        if (mInOverScrollMode) return y;
+        return pinLoc(y, getViewHeightWithTitle(),
+                      computeRealVerticalScrollRange() + getTitleHeight());
+    }
+
+    /**
+     * A title bar which is embedded in this WebView, and scrolls along with it
+     * vertically, but not horizontally.
+     */
+    private View mTitleBar;
+
+    /**
+     * the title bar rendering gravity
+     */
+    private int mTitleGravity;
+
+    /**
+     * Add or remove a title bar to be embedded into the WebView, and scroll
+     * along with it vertically, while remaining in view horizontally. Pass
+     * null to remove the title bar from the WebView, and return to drawing
+     * the WebView normally without translating to account for the title bar.
+     * @hide
+     */
+    public void setEmbeddedTitleBar(View v) {
+        if (mWebView instanceof TitleBarDelegate) {
+            ((TitleBarDelegate) mWebView).onSetEmbeddedTitleBar(v);
+        }
+        if (mTitleBar == v) return;
+        if (mTitleBar != null) {
+            mWebView.removeView(mTitleBar);
+        }
+        if (null != v) {
+            mWebView.addView(v, new AbsoluteLayout.LayoutParams(
+                    ViewGroup.LayoutParams.MATCH_PARENT,
+                    ViewGroup.LayoutParams.WRAP_CONTENT, 0, 0));
+        }
+        mTitleBar = v;
+    }
+
+    /**
+     * Set where to render the embedded title bar
+     * NO_GRAVITY at the top of the page
+     * TOP        at the top of the screen
+     * @hide
+     */
+    public void setTitleBarGravity(int gravity) {
+        mTitleGravity = gravity;
+        // force refresh
+        invalidate();
+    }
+
+    /**
+     * Given a distance in view space, convert it to content space. Note: this
+     * does not reflect translation, just scaling, so this should not be called
+     * with coordinates, but should be called for dimensions like width or
+     * height.
+     */
+    private int viewToContentDimension(int d) {
+        return Math.round(d * mZoomManager.getInvScale());
+    }
+
+    /**
+     * Given an x coordinate in view space, convert it to content space.  Also
+     * may be used for absolute heights.
+     */
+    /*package*/ int viewToContentX(int x) {
+        return viewToContentDimension(x);
+    }
+
+    /**
+     * Given a y coordinate in view space, convert it to content space.
+     * Takes into account the height of the title bar if there is one
+     * embedded into the WebView.
+     */
+    /*package*/ int viewToContentY(int y) {
+        return viewToContentDimension(y - getTitleHeight());
+    }
+
+    /**
+     * Given a x coordinate in view space, convert it to content space.
+     * Returns the result as a float.
+     */
+    private float viewToContentXf(int x) {
+        return x * mZoomManager.getInvScale();
+    }
+
+    /**
+     * Given a y coordinate in view space, convert it to content space.
+     * Takes into account the height of the title bar if there is one
+     * embedded into the WebView. Returns the result as a float.
+     */
+    private float viewToContentYf(int y) {
+        return (y - getTitleHeight()) * mZoomManager.getInvScale();
+    }
+
+    /**
+     * Given a distance in content space, convert it to view space. Note: this
+     * does not reflect translation, just scaling, so this should not be called
+     * with coordinates, but should be called for dimensions like width or
+     * height.
+     */
+    /*package*/ int contentToViewDimension(int d) {
+        return Math.round(d * mZoomManager.getScale());
+    }
+
+    /**
+     * Given an x coordinate in content space, convert it to view
+     * space.
+     */
+    /*package*/ int contentToViewX(int x) {
+        return contentToViewDimension(x);
+    }
+
+    /**
+     * Given a y coordinate in content space, convert it to view
+     * space.  Takes into account the height of the title bar.
+     */
+    /*package*/ int contentToViewY(int y) {
+        return contentToViewDimension(y) + getTitleHeight();
+    }
+
+    private Rect contentToViewRect(Rect x) {
+        return new Rect(contentToViewX(x.left), contentToViewY(x.top),
+                        contentToViewX(x.right), contentToViewY(x.bottom));
+    }
+
+    /*  To invalidate a rectangle in content coordinates, we need to transform
+        the rect into view coordinates, so we can then call invalidate(...).
+
+        Normally, we would just call contentToView[XY](...), which eventually
+        calls Math.round(coordinate * mActualScale). However, for invalidates,
+        we need to account for the slop that occurs with antialiasing. To
+        address that, we are a little more liberal in the size of the rect that
+        we invalidate.
+
+        This liberal calculation calls floor() for the top/left, and ceil() for
+        the bottom/right coordinates. This catches the possible extra pixels of
+        antialiasing that we might have missed with just round().
+     */
+
+    // Called by JNI to invalidate the View, given rectangle coordinates in
+    // content space
+    private void viewInvalidate(int l, int t, int r, int b) {
+        final float scale = mZoomManager.getScale();
+        final int dy = getTitleHeight();
+        mWebView.invalidate((int)Math.floor(l * scale),
+                (int)Math.floor(t * scale) + dy,
+                (int)Math.ceil(r * scale),
+                (int)Math.ceil(b * scale) + dy);
+    }
+
+    // Called by JNI to invalidate the View after a delay, given rectangle
+    // coordinates in content space
+    private void viewInvalidateDelayed(long delay, int l, int t, int r, int b) {
+        final float scale = mZoomManager.getScale();
+        final int dy = getTitleHeight();
+        mWebView.postInvalidateDelayed(delay,
+                (int)Math.floor(l * scale),
+                (int)Math.floor(t * scale) + dy,
+                (int)Math.ceil(r * scale),
+                (int)Math.ceil(b * scale) + dy);
+    }
+
+    private void invalidateContentRect(Rect r) {
+        viewInvalidate(r.left, r.top, r.right, r.bottom);
+    }
+
+    // stop the scroll animation, and don't let a subsequent fling add
+    // to the existing velocity
+    private void abortAnimation() {
+        mScroller.abortAnimation();
+        mLastVelocity = 0;
+    }
+
+    /* call from webcoreview.draw(), so we're still executing in the UI thread
+    */
+    private void recordNewContentSize(int w, int h, boolean updateLayout) {
+
+        // premature data from webkit, ignore
+        if ((w | h) == 0) {
+            return;
+        }
+
+        // don't abort a scroll animation if we didn't change anything
+        if (mContentWidth != w || mContentHeight != h) {
+            // record new dimensions
+            mContentWidth = w;
+            mContentHeight = h;
+            // If history Picture is drawn, don't update scroll. They will be
+            // updated when we get out of that mode.
+            if (!mDrawHistory) {
+                // repin our scroll, taking into account the new content size
+                updateScrollCoordinates(pinLocX(getScrollX()), pinLocY(getScrollY()));
+                if (!mScroller.isFinished()) {
+                    // We are in the middle of a scroll.  Repin the final scroll
+                    // position.
+                    mScroller.setFinalX(pinLocX(mScroller.getFinalX()));
+                    mScroller.setFinalY(pinLocY(mScroller.getFinalY()));
+                }
+            }
+        }
+        contentSizeChanged(updateLayout);
+    }
+
+    // Used to avoid sending many visible rect messages.
+    private Rect mLastVisibleRectSent = new Rect();
+    private Rect mLastGlobalRect = new Rect();
+    private Rect mVisibleRect = new Rect();
+    private Rect mGlobalVisibleRect = new Rect();
+    private Point mScrollOffset = new Point();
+
+    Rect sendOurVisibleRect() {
+        if (mZoomManager.isPreventingWebkitUpdates()) return mLastVisibleRectSent;
+        calcOurContentVisibleRect(mVisibleRect);
+        // Rect.equals() checks for null input.
+        if (!mVisibleRect.equals(mLastVisibleRectSent)) {
+            if (!mBlockWebkitViewMessages) {
+                mScrollOffset.set(mVisibleRect.left, mVisibleRect.top);
+                mWebViewCore.removeMessages(EventHub.SET_SCROLL_OFFSET);
+                mWebViewCore.sendMessage(EventHub.SET_SCROLL_OFFSET,
+                        mSendScrollEvent ? 1 : 0, mScrollOffset);
+            }
+            mLastVisibleRectSent.set(mVisibleRect);
+            mPrivateHandler.removeMessages(SWITCH_TO_LONGPRESS);
+        }
+        if (mWebView.getGlobalVisibleRect(mGlobalVisibleRect)
+                && !mGlobalVisibleRect.equals(mLastGlobalRect)) {
+            if (DebugFlags.WEB_VIEW) {
+                Log.v(LOGTAG, "sendOurVisibleRect=(" + mGlobalVisibleRect.left + ","
+                        + mGlobalVisibleRect.top + ",r=" + mGlobalVisibleRect.right + ",b="
+                        + mGlobalVisibleRect.bottom);
+            }
+            // TODO: the global offset is only used by windowRect()
+            // in ChromeClientAndroid ; other clients such as touch
+            // and mouse events could return view + screen relative points.
+            if (!mBlockWebkitViewMessages) {
+                mWebViewCore.sendMessage(EventHub.SET_GLOBAL_BOUNDS, mGlobalVisibleRect);
+            }
+            mLastGlobalRect.set(mGlobalVisibleRect);
+        }
+        return mVisibleRect;
+    }
+
+    private Point mGlobalVisibleOffset = new Point();
+    // Sets r to be the visible rectangle of our webview in view coordinates
+    private void calcOurVisibleRect(Rect r) {
+        mWebView.getGlobalVisibleRect(r, mGlobalVisibleOffset);
+        r.offset(-mGlobalVisibleOffset.x, -mGlobalVisibleOffset.y);
+    }
+
+    // Sets r to be our visible rectangle in content coordinates
+    private void calcOurContentVisibleRect(Rect r) {
+        calcOurVisibleRect(r);
+        r.left = viewToContentX(r.left);
+        // viewToContentY will remove the total height of the title bar.  Add
+        // the visible height back in to account for the fact that if the title
+        // bar is partially visible, the part of the visible rect which is
+        // displaying our content is displaced by that amount.
+        r.top = viewToContentY(r.top + getVisibleTitleHeightImpl());
+        r.right = viewToContentX(r.right);
+        r.bottom = viewToContentY(r.bottom);
+    }
+
+    private Rect mContentVisibleRect = new Rect();
+    // Sets r to be our visible rectangle in content coordinates. We use this
+    // method on the native side to compute the position of the fixed layers.
+    // Uses floating coordinates (necessary to correctly place elements when
+    // the scale factor is not 1)
+    private void calcOurContentVisibleRectF(RectF r) {
+        calcOurVisibleRect(mContentVisibleRect);
+        r.left = viewToContentXf(mContentVisibleRect.left);
+        // viewToContentY will remove the total height of the title bar.  Add
+        // the visible height back in to account for the fact that if the title
+        // bar is partially visible, the part of the visible rect which is
+        // displaying our content is displaced by that amount.
+        r.top = viewToContentYf(mContentVisibleRect.top + getVisibleTitleHeightImpl());
+        r.right = viewToContentXf(mContentVisibleRect.right);
+        r.bottom = viewToContentYf(mContentVisibleRect.bottom);
+    }
+
+    static class ViewSizeData {
+        int mWidth;
+        int mHeight;
+        float mHeightWidthRatio;
+        int mActualViewHeight;
+        int mTextWrapWidth;
+        int mAnchorX;
+        int mAnchorY;
+        float mScale;
+        boolean mIgnoreHeight;
+    }
+
+    /**
+     * Compute unzoomed width and height, and if they differ from the last
+     * values we sent, send them to webkit (to be used as new viewport)
+     *
+     * @param force ensures that the message is sent to webkit even if the width
+     * or height has not changed since the last message
+     *
+     * @return true if new values were sent
+     */
+    boolean sendViewSizeZoom(boolean force) {
+        if (mBlockWebkitViewMessages) return false;
+        if (mZoomManager.isPreventingWebkitUpdates()) return false;
+
+        int viewWidth = getViewWidth();
+        int newWidth = Math.round(viewWidth * mZoomManager.getInvScale());
+        // This height could be fixed and be different from actual visible height.
+        int viewHeight = getViewHeightWithTitle() - getTitleHeight();
+        int newHeight = Math.round(viewHeight * mZoomManager.getInvScale());
+        // Make the ratio more accurate than (newHeight / newWidth), since the
+        // latter both are calculated and rounded.
+        float heightWidthRatio = (float) viewHeight / viewWidth;
+        /*
+         * Because the native side may have already done a layout before the
+         * View system was able to measure us, we have to send a height of 0 to
+         * remove excess whitespace when we grow our width. This will trigger a
+         * layout and a change in content size. This content size change will
+         * mean that contentSizeChanged will either call this method directly or
+         * indirectly from onSizeChanged.
+         */
+        if (newWidth > mLastWidthSent && mWrapContent) {
+            newHeight = 0;
+            heightWidthRatio = 0;
+        }
+        // Actual visible content height.
+        int actualViewHeight = Math.round(getViewHeight() * mZoomManager.getInvScale());
+        // Avoid sending another message if the dimensions have not changed.
+        if (newWidth != mLastWidthSent || newHeight != mLastHeightSent || force ||
+                actualViewHeight != mLastActualHeightSent) {
+            ViewSizeData data = new ViewSizeData();
+            data.mWidth = newWidth;
+            data.mHeight = newHeight;
+            data.mHeightWidthRatio = heightWidthRatio;
+            data.mActualViewHeight = actualViewHeight;
+            data.mTextWrapWidth = Math.round(viewWidth / mZoomManager.getTextWrapScale());
+            data.mScale = mZoomManager.getScale();
+            data.mIgnoreHeight = mZoomManager.isFixedLengthAnimationInProgress()
+                    && !mHeightCanMeasure;
+            data.mAnchorX = mZoomManager.getDocumentAnchorX();
+            data.mAnchorY = mZoomManager.getDocumentAnchorY();
+            mWebViewCore.sendMessage(EventHub.VIEW_SIZE_CHANGED, data);
+            mLastWidthSent = newWidth;
+            mLastHeightSent = newHeight;
+            mLastActualHeightSent = actualViewHeight;
+            mZoomManager.clearDocumentAnchor();
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * Update the double-tap zoom.
+     */
+    /* package */ void updateDoubleTapZoom(int doubleTapZoom) {
+        mZoomManager.updateDoubleTapZoom(doubleTapZoom);
+    }
+
+    private int computeRealHorizontalScrollRange() {
+        if (mDrawHistory) {
+            return mHistoryWidth;
+        } else {
+            // to avoid rounding error caused unnecessary scrollbar, use floor
+            return (int) Math.floor(mContentWidth * mZoomManager.getScale());
+        }
+    }
+
+    @Override
+    public int computeHorizontalScrollRange() {
+        int range = computeRealHorizontalScrollRange();
+
+        // Adjust reported range if overscrolled to compress the scroll bars
+        final int scrollX = getScrollX();
+        final int overscrollRight = computeMaxScrollX();
+        if (scrollX < 0) {
+            range -= scrollX;
+        } else if (scrollX > overscrollRight) {
+            range += scrollX - overscrollRight;
+        }
+
+        return range;
+    }
+
+    @Override
+    public int computeHorizontalScrollOffset() {
+        return Math.max(getScrollX(), 0);
+    }
+
+    private int computeRealVerticalScrollRange() {
+        if (mDrawHistory) {
+            return mHistoryHeight;
+        } else {
+            // to avoid rounding error caused unnecessary scrollbar, use floor
+            return (int) Math.floor(mContentHeight * mZoomManager.getScale());
+        }
+    }
+
+    @Override
+    public int computeVerticalScrollRange() {
+        int range = computeRealVerticalScrollRange();
+
+        // Adjust reported range if overscrolled to compress the scroll bars
+        final int scrollY = getScrollY();
+        final int overscrollBottom = computeMaxScrollY();
+        if (scrollY < 0) {
+            range -= scrollY;
+        } else if (scrollY > overscrollBottom) {
+            range += scrollY - overscrollBottom;
+        }
+
+        return range;
+    }
+
+    @Override
+    public int computeVerticalScrollOffset() {
+        return Math.max(getScrollY() - getTitleHeight(), 0);
+    }
+
+    @Override
+    public int computeVerticalScrollExtent() {
+        return getViewHeight();
+    }
+
+    /** @hide */
+    @Override
+    public void onDrawVerticalScrollBar(Canvas canvas,
+                                           Drawable scrollBar,
+                                           int l, int t, int r, int b) {
+        if (getScrollY() < 0) {
+            t -= getScrollY();
+        }
+        scrollBar.setBounds(l, t + getVisibleTitleHeightImpl(), r, b);
+        scrollBar.draw(canvas);
+    }
+
+    @Override
+    public void onOverScrolled(int scrollX, int scrollY, boolean clampedX,
+            boolean clampedY) {
+        // Special-case layer scrolling so that we do not trigger normal scroll
+        // updating.
+        if (mTouchMode == TOUCH_DRAG_LAYER_MODE) {
+            scrollLayerTo(scrollX, scrollY);
+            return;
+        }
+        mInOverScrollMode = false;
+        int maxX = computeMaxScrollX();
+        int maxY = computeMaxScrollY();
+        if (maxX == 0) {
+            // do not over scroll x if the page just fits the screen
+            scrollX = pinLocX(scrollX);
+        } else if (scrollX < 0 || scrollX > maxX) {
+            mInOverScrollMode = true;
+        }
+        if (scrollY < 0 || scrollY > maxY) {
+            mInOverScrollMode = true;
+        }
+
+        int oldX = getScrollX();
+        int oldY = getScrollY();
+
+        mWebViewPrivate.super_scrollTo(scrollX, scrollY);
+
+        if (mOverScrollGlow != null) {
+            mOverScrollGlow.pullGlow(getScrollX(), getScrollY(), oldX, oldY, maxX, maxY);
+        }
+    }
+
+    /**
+     * See {@link WebView#getUrl()}
+     */
+    @Override
+    public String getUrl() {
+        checkThread();
+        WebHistoryItem h = mCallbackProxy.getBackForwardList().getCurrentItem();
+        return h != null ? h.getUrl() : null;
+    }
+
+    /**
+     * See {@link WebView#getOriginalUrl()}
+     */
+    @Override
+    public String getOriginalUrl() {
+        checkThread();
+        WebHistoryItem h = mCallbackProxy.getBackForwardList().getCurrentItem();
+        return h != null ? h.getOriginalUrl() : null;
+    }
+
+    /**
+     * See {@link WebView#getTitle()}
+     */
+    @Override
+    public String getTitle() {
+        checkThread();
+        WebHistoryItem h = mCallbackProxy.getBackForwardList().getCurrentItem();
+        return h != null ? h.getTitle() : null;
+    }
+
+    /**
+     * See {@link WebView#getFavicon()}
+     */
+    @Override
+    public Bitmap getFavicon() {
+        checkThread();
+        WebHistoryItem h = mCallbackProxy.getBackForwardList().getCurrentItem();
+        return h != null ? h.getFavicon() : null;
+    }
+
+    /**
+     * See {@link WebView#getTouchIconUrl()}
+     */
+    @Override
+    public String getTouchIconUrl() {
+        WebHistoryItem h = mCallbackProxy.getBackForwardList().getCurrentItem();
+        return h != null ? h.getTouchIconUrl() : null;
+    }
+
+    /**
+     * See {@link WebView#getProgress()}
+     */
+    @Override
+    public int getProgress() {
+        checkThread();
+        return mCallbackProxy.getProgress();
+    }
+
+    /**
+     * See {@link WebView#getContentHeight()}
+     */
+    @Override
+    public int getContentHeight() {
+        checkThread();
+        return mContentHeight;
+    }
+
+    /**
+     * See {@link WebView#getContentWidth()}
+     */
+    @Override
+    public int getContentWidth() {
+        return mContentWidth;
+    }
+
+    /**
+     * @hide
+     */
+    public int getPageBackgroundColor() {
+        return nativeGetBackgroundColor();
+    }
+
+    /**
+     * See {@link WebView#pauseTimers()}
+     */
+    @Override
+    public void pauseTimers() {
+        checkThread();
+        mWebViewCore.sendMessage(EventHub.PAUSE_TIMERS);
+    }
+
+    /**
+     * See {@link WebView#resumeTimers()}
+     */
+    @Override
+    public void resumeTimers() {
+        checkThread();
+        mWebViewCore.sendMessage(EventHub.RESUME_TIMERS);
+    }
+
+    /**
+     * See {@link WebView#onPause()}
+     */
+    @Override
+    public void onPause() {
+        checkThread();
+        if (!mIsPaused) {
+            mIsPaused = true;
+            mWebViewCore.sendMessage(EventHub.ON_PAUSE);
+            // We want to pause the current playing video when switching out
+            // from the current WebView/tab.
+            if (mHTML5VideoViewProxy != null) {
+                mHTML5VideoViewProxy.pauseAndDispatch();
+            }
+            if (mNativeClass != 0) {
+                nativeSetPauseDrawing(mNativeClass, true);
+            }
+
+            cancelSelectDialog();
+            WebCoreThreadWatchdog.pause();
+        }
+    }
+
+    @Override
+    public void onWindowVisibilityChanged(int visibility) {
+        updateDrawingState();
+    }
+
+    void updateDrawingState() {
+        if (mNativeClass == 0 || mIsPaused) return;
+        if (mWebView.getWindowVisibility() != View.VISIBLE) {
+            nativeSetPauseDrawing(mNativeClass, true);
+        } else if (mWebView.getVisibility() != View.VISIBLE) {
+            nativeSetPauseDrawing(mNativeClass, true);
+        } else {
+            nativeSetPauseDrawing(mNativeClass, false);
+        }
+    }
+
+    /**
+     * See {@link WebView#onResume()}
+     */
+    @Override
+    public void onResume() {
+        checkThread();
+        if (mIsPaused) {
+            mIsPaused = false;
+            mWebViewCore.sendMessage(EventHub.ON_RESUME);
+            if (mNativeClass != 0) {
+                nativeSetPauseDrawing(mNativeClass, false);
+            }
+        }
+        // Ensure that the watchdog has a currently valid Context to be able to display
+        // a prompt dialog. For example, if the Activity was finished whilst the WebCore
+        // thread was blocked and the Activity is started again, we may reuse the blocked
+        // thread, but we'll have a new Activity.
+        WebCoreThreadWatchdog.updateContext(mContext);
+        // We get a call to onResume for new WebViews (i.e. mIsPaused will be false). We need
+        // to ensure that the Watchdog thread is running for the new WebView, so call
+        // it outside the if block above.
+        WebCoreThreadWatchdog.resume();
+    }
+
+    /**
+     * See {@link WebView#isPaused()}
+     */
+    @Override
+    public boolean isPaused() {
+        return mIsPaused;
+    }
+
+    /**
+     * See {@link WebView#freeMemory()}
+     */
+    @Override
+    public void freeMemory() {
+        checkThread();
+        mWebViewCore.sendMessage(EventHub.FREE_MEMORY);
+    }
+
+    /**
+     * See {@link WebView#clearCache(boolean)}
+     */
+    @Override
+    public void clearCache(boolean includeDiskFiles) {
+        checkThread();
+        // Note: this really needs to be a static method as it clears cache for all
+        // WebView. But we need mWebViewCore to send message to WebCore thread, so
+        // we can't make this static.
+        mWebViewCore.sendMessage(EventHub.CLEAR_CACHE,
+                includeDiskFiles ? 1 : 0, 0);
+    }
+
+    /**
+     * See {@link WebView#clearFormData()}
+     */
+    @Override
+    public void clearFormData() {
+        checkThread();
+        // TODO: Implement b/6083041
+    }
+
+    /**
+     * See {@link WebView#clearHistory()}
+     */
+    @Override
+    public void clearHistory() {
+        checkThread();
+        mCallbackProxy.getBackForwardList().setClearPending();
+        mWebViewCore.sendMessage(EventHub.CLEAR_HISTORY);
+    }
+
+    /**
+     * See {@link WebView#clearSslPreferences()}
+     */
+    @Override
+    public void clearSslPreferences() {
+        checkThread();
+        mWebViewCore.sendMessage(EventHub.CLEAR_SSL_PREF_TABLE);
+    }
+
+    /**
+     * See {@link WebView#copyBackForwardList()}
+     */
+    @Override
+    public WebBackForwardList copyBackForwardList() {
+        checkThread();
+        return mCallbackProxy.getBackForwardList().clone();
+    }
+
+    /**
+     * See {@link WebView#findNext(boolean)}
+     */
+    @Override
+    public void findNext(boolean forward) {
+        checkThread();
+        if (0 == mNativeClass) return; // client isn't initialized
+        mWebViewCore.sendMessage(EventHub.FIND_NEXT, forward ? 1 : 0);
+    }
+
+    /**
+     * See {@link WebView#findAll(String)}
+     */
+    @Override
+    public int findAll(String find) {
+        return findAllBody(find, false);
+    }
+
+    /**
+     * @hide
+     */
+    public void findAllAsync(String find) {
+        findAllBody(find, true);
+    }
+
+    private int findAllBody(String find, boolean isAsync) {
+        checkThread();
+        if (0 == mNativeClass) return 0; // client isn't initialized
+        mLastFind = find;
+        mWebViewCore.removeMessages(EventHub.FIND_ALL);
+        WebViewCore.FindAllRequest request = new
+            WebViewCore.FindAllRequest(find);
+        if (isAsync) {
+            mWebViewCore.sendMessage(EventHub.FIND_ALL, request);
+            return 0; // no need to wait for response
+        }
+        synchronized(request) {
+            try {
+                mWebViewCore.sendMessageAtFrontOfQueue(EventHub.FIND_ALL,
+                    request);
+                while (request.mMatchCount == -1) {
+                    request.wait();
+                }
+            }
+            catch (InterruptedException e) {
+                return 0;
+            }
+        }
+        return request.mMatchCount;
+    }
+
+    /**
+     * Start an ActionMode for finding text in this WebView.  Only works if this
+     *              WebView is attached to the view system.
+     * @param text If non-null, will be the initial text to search for.
+     *             Otherwise, the last String searched for in this WebView will
+     *             be used to start.
+     * @param showIme If true, show the IME, assuming the user will begin typing.
+     *             If false and text is non-null, perform a find all.
+     * @return boolean True if the find dialog is shown, false otherwise.
+     */
+    public boolean showFindDialog(String text, boolean showIme) {
+        checkThread();
+        FindActionModeCallback callback = new FindActionModeCallback(mContext);
+        if (mWebView.getParent() == null || mWebView.startActionMode(callback) == null) {
+            // Could not start the action mode, so end Find on page
+            return false;
+        }
+        mCachedOverlappingActionModeHeight = -1;
+        mFindCallback = callback;
+        setFindIsUp(true);
+        mFindCallback.setWebView(this);
+        if (showIme) {
+            mFindCallback.showSoftInput();
+        } else if (text != null) {
+            mFindCallback.setText(text);
+            mFindCallback.findAll();
+            return true;
+        }
+        if (text == null) {
+            text = mLastFind;
+        }
+        if (text != null) {
+            mFindCallback.setText(text);
+            mFindCallback.findAll();
+        }
+        return true;
+    }
+
+    /**
+     * Keep track of the find callback so that we can remove its titlebar if
+     * necessary.
+     */
+    private FindActionModeCallback mFindCallback;
+
+    /**
+     * Toggle whether the find dialog is showing, for both native and Java.
+     */
+    private void setFindIsUp(boolean isUp) {
+        mFindIsUp = isUp;
+    }
+
+    // Used to know whether the find dialog is open.  Affects whether
+    // or not we draw the highlights for matches.
+    private boolean mFindIsUp;
+
+    // Keep track of the last string sent, so we can search again when find is
+    // reopened.
+    private String mLastFind;
+
+    /**
+     * Return the first substring consisting of the address of a physical
+     * location. Currently, only addresses in the United States are detected,
+     * and consist of:
+     * - a house number
+     * - a street name
+     * - a street type (Road, Circle, etc), either spelled out or abbreviated
+     * - a city name
+     * - a state or territory, either spelled out or two-letter abbr.
+     * - an optional 5 digit or 9 digit zip code.
+     *
+     * All names must be correctly capitalized, and the zip code, if present,
+     * must be valid for the state. The street type must be a standard USPS
+     * spelling or abbreviation. The state or territory must also be spelled
+     * or abbreviated using USPS standards. The house number may not exceed
+     * five digits.
+     * @param addr The string to search for addresses.
+     *
+     * @return the address, or if no address is found, return null.
+     */
+    public static String findAddress(String addr) {
+        checkThread();
+        return findAddress(addr, false);
+    }
+
+    /**
+     * @hide
+     * Return the first substring consisting of the address of a physical
+     * location. Currently, only addresses in the United States are detected,
+     * and consist of:
+     * - a house number
+     * - a street name
+     * - a street type (Road, Circle, etc), either spelled out or abbreviated
+     * - a city name
+     * - a state or territory, either spelled out or two-letter abbr.
+     * - an optional 5 digit or 9 digit zip code.
+     *
+     * Names are optionally capitalized, and the zip code, if present,
+     * must be valid for the state. The street type must be a standard USPS
+     * spelling or abbreviation. The state or territory must also be spelled
+     * or abbreviated using USPS standards. The house number may not exceed
+     * five digits.
+     * @param addr The string to search for addresses.
+     * @param caseInsensitive addr Set to true to make search ignore case.
+     *
+     * @return the address, or if no address is found, return null.
+     */
+    public static String findAddress(String addr, boolean caseInsensitive) {
+        return WebViewCore.nativeFindAddress(addr, caseInsensitive);
+    }
+
+    /**
+     * See {@link WebView#clearMatches()}
+     */
+    @Override
+    public void clearMatches() {
+        checkThread();
+        if (mNativeClass == 0)
+            return;
+        mWebViewCore.removeMessages(EventHub.FIND_ALL);
+        mWebViewCore.sendMessage(EventHub.FIND_ALL, null);
+    }
+
+
+    /**
+     * Called when the find ActionMode ends.
+     */
+    void notifyFindDialogDismissed() {
+        mFindCallback = null;
+        mCachedOverlappingActionModeHeight = -1;
+        if (mWebViewCore == null) {
+            return;
+        }
+        clearMatches();
+        setFindIsUp(false);
+        // Now that the dialog has been removed, ensure that we scroll to a
+        // location that is not beyond the end of the page.
+        pinScrollTo(getScrollX(), getScrollY(), false, 0);
+        invalidate();
+    }
+
+    /**
+     * See {@link WebView#documentHasImages(Message)}
+     */
+    @Override
+    public void documentHasImages(Message response) {
+        checkThread();
+        if (response == null) {
+            return;
+        }
+        mWebViewCore.sendMessage(EventHub.DOC_HAS_IMAGES, response);
+    }
+
+    /**
+     * Request the scroller to abort any ongoing animation
+     *
+     * @hide
+     */
+    public void stopScroll() {
+        mScroller.forceFinished(true);
+        mLastVelocity = 0;
+    }
+
+    @Override
+    public void computeScroll() {
+        if (mScroller.computeScrollOffset()) {
+            int oldX = getScrollX();
+            int oldY = getScrollY();
+            int x = mScroller.getCurrX();
+            int y = mScroller.getCurrY();
+            invalidate();  // So we draw again
+
+            if (!mScroller.isFinished()) {
+                int rangeX = computeMaxScrollX();
+                int rangeY = computeMaxScrollY();
+                int overflingDistance = mOverflingDistance;
+
+                // Use the layer's scroll data if needed.
+                if (mTouchMode == TOUCH_DRAG_LAYER_MODE) {
+                    oldX = mScrollingLayerRect.left;
+                    oldY = mScrollingLayerRect.top;
+                    rangeX = mScrollingLayerRect.right;
+                    rangeY = mScrollingLayerRect.bottom;
+                    // No overscrolling for layers.
+                    overflingDistance = 0;
+                }
+
+                mWebViewPrivate.overScrollBy(x - oldX, y - oldY, oldX, oldY,
+                        rangeX, rangeY,
+                        overflingDistance, overflingDistance, false);
+
+                if (mOverScrollGlow != null) {
+                    mOverScrollGlow.absorbGlow(x, y, oldX, oldY, rangeX, rangeY);
+                }
+            } else {
+                if (mTouchMode != TOUCH_DRAG_LAYER_MODE) {
+                    setScrollXRaw(x);
+                    setScrollYRaw(y);
+                } else {
+                    // Update the layer position instead of WebView.
+                    scrollLayerTo(x, y);
+                }
+                abortAnimation();
+                nativeSetIsScrolling(false);
+                if (!mBlockWebkitViewMessages) {
+                    WebViewCore.resumePriority();
+                    if (!mSelectingText) {
+                        WebViewCore.resumeUpdatePicture(mWebViewCore);
+                    }
+                }
+                if (oldX != getScrollX() || oldY != getScrollY()) {
+                    sendOurVisibleRect();
+                }
+            }
+        } else {
+            mWebViewPrivate.super_computeScroll();
+        }
+    }
+
+    private void scrollLayerTo(int x, int y) {
+        if (x == mScrollingLayerRect.left && y == mScrollingLayerRect.top) {
+            return;
+        }
+        if (mSelectingText) {
+            int dx = mScrollingLayerRect.left - x;
+            int dy = mScrollingLayerRect.top - y;
+            if (mSelectCursorBaseLayerId == mCurrentScrollingLayerId) {
+                mSelectCursorBase.offset(dx, dy);
+            }
+            if (mSelectCursorExtentLayerId == mCurrentScrollingLayerId) {
+                mSelectCursorExtent.offset(dx, dy);
+            }
+        }
+        nativeScrollLayer(mCurrentScrollingLayerId, x, y);
+        mScrollingLayerRect.left = x;
+        mScrollingLayerRect.top = y;
+        mWebViewCore.sendMessage(WebViewCore.EventHub.SCROLL_LAYER, mCurrentScrollingLayerId,
+                mScrollingLayerRect);
+        mWebViewPrivate.onScrollChanged(getScrollX(), getScrollY(), getScrollX(), getScrollY());
+        invalidate();
+    }
+
+    private static int computeDuration(int dx, int dy) {
+        int distance = Math.max(Math.abs(dx), Math.abs(dy));
+        int duration = distance * 1000 / STD_SPEED;
+        return Math.min(duration, MAX_DURATION);
+    }
+
+    // helper to pin the scrollBy parameters (already in view coordinates)
+    // returns true if the scroll was changed
+    private boolean pinScrollBy(int dx, int dy, boolean animate, int animationDuration) {
+        return pinScrollTo(getScrollX() + dx, getScrollY() + dy, animate, animationDuration);
+    }
+    // helper to pin the scrollTo parameters (already in view coordinates)
+    // returns true if the scroll was changed
+    private boolean pinScrollTo(int x, int y, boolean animate, int animationDuration) {
+        x = pinLocX(x);
+        y = pinLocY(y);
+        int dx = x - getScrollX();
+        int dy = y - getScrollY();
+
+        if ((dx | dy) == 0) {
+            return false;
+        }
+        abortAnimation();
+        if (animate) {
+            //        Log.d(LOGTAG, "startScroll: " + dx + " " + dy);
+            mScroller.startScroll(getScrollX(), getScrollY(), dx, dy,
+                    animationDuration > 0 ? animationDuration : computeDuration(dx, dy));
+            mWebViewPrivate.awakenScrollBars(mScroller.getDuration());
+            invalidate();
+        } else {
+            mWebView.scrollTo(x, y);
+        }
+        return true;
+    }
+
+    // Scale from content to view coordinates, and pin.
+    // Also called by jni webview.cpp
+    private boolean setContentScrollBy(int cx, int cy, boolean animate) {
+        if (mDrawHistory) {
+            // disallow WebView to change the scroll position as History Picture
+            // is used in the view system.
+            // TODO: as we switchOutDrawHistory when trackball or navigation
+            // keys are hit, this should be safe. Right?
+            return false;
+        }
+        cx = contentToViewDimension(cx);
+        cy = contentToViewDimension(cy);
+        if (mHeightCanMeasure) {
+            // move our visible rect according to scroll request
+            if (cy != 0) {
+                Rect tempRect = new Rect();
+                calcOurVisibleRect(tempRect);
+                tempRect.offset(cx, cy);
+                mWebView.requestRectangleOnScreen(tempRect);
+            }
+            // FIXME: We scroll horizontally no matter what because currently
+            // ScrollView and ListView will not scroll horizontally.
+            // FIXME: Why do we only scroll horizontally if there is no
+            // vertical scroll?
+//                Log.d(LOGTAG, "setContentScrollBy cy=" + cy);
+            return cy == 0 && cx != 0 && pinScrollBy(cx, 0, animate, 0);
+        } else {
+            return pinScrollBy(cx, cy, animate, 0);
+        }
+    }
+
+    /**
+     * Called by CallbackProxy when the page starts loading.
+     * @param url The URL of the page which has started loading.
+     */
+    /* package */ void onPageStarted(String url) {
+        // every time we start a new page, we want to reset the
+        // WebView certificate:  if the new site is secure, we
+        // will reload it and get a new certificate set;
+        // if the new site is not secure, the certificate must be
+        // null, and that will be the case
+        mWebView.setCertificate(null);
+
+        // reset the flag since we set to true in if need after
+        // loading is see onPageFinished(Url)
+        mAccessibilityScriptInjected = false;
+    }
+
+    /**
+     * Called by CallbackProxy when the page finishes loading.
+     * @param url The URL of the page which has finished loading.
+     */
+    /* package */ void onPageFinished(String url) {
+        if (mPageThatNeedsToSlideTitleBarOffScreen != null) {
+            // If the user is now on a different page, or has scrolled the page
+            // past the point where the title bar is offscreen, ignore the
+            // scroll request.
+            if (mPageThatNeedsToSlideTitleBarOffScreen.equals(url)
+                    && getScrollX() == 0 && getScrollY() == 0) {
+                pinScrollTo(0, mYDistanceToSlideTitleOffScreen, true,
+                        SLIDE_TITLE_DURATION);
+            }
+            mPageThatNeedsToSlideTitleBarOffScreen = null;
+        }
+        mZoomManager.onPageFinished(url);
+        injectAccessibilityForUrl(url);
+    }
+
+    /**
+     * This method injects accessibility in the loaded document if accessibility
+     * is enabled. If JavaScript is enabled we try to inject a URL specific script.
+     * If no URL specific script is found or JavaScript is disabled we fallback to
+     * the default {@link AccessibilityInjector} implementation.
+     * </p>
+     * If the URL has the "axs" paramter set to 1 it has already done the
+     * script injection so we do nothing. If the parameter is set to 0
+     * the URL opts out accessibility script injection so we fall back to
+     * the default {@link AccessibilityInjector}.
+     * </p>
+     * Note: If the user has not opted-in the accessibility script injection no scripts
+     * are injected rather the default {@link AccessibilityInjector} implementation
+     * is used.
+     *
+     * @param url The URL loaded by this {@link WebView}.
+     */
+    private void injectAccessibilityForUrl(String url) {
+        if (mWebViewCore == null) {
+            return;
+        }
+        AccessibilityManager accessibilityManager = AccessibilityManager.getInstance(mContext);
+
+        if (!accessibilityManager.isEnabled()) {
+            // it is possible that accessibility was turned off between reloads
+            ensureAccessibilityScriptInjectorInstance(false);
+            return;
+        }
+
+        if (!getSettings().getJavaScriptEnabled()) {
+            // no JS so we fallback to the basic buil-in support
+            ensureAccessibilityScriptInjectorInstance(true);
+            return;
+        }
+
+        // check the URL "axs" parameter to choose appropriate action
+        int axsParameterValue = getAxsUrlParameterValue(url);
+        if (axsParameterValue == ACCESSIBILITY_SCRIPT_INJECTION_UNDEFINED) {
+            boolean onDeviceScriptInjectionEnabled = (Settings.Secure.getInt(mContext
+                    .getContentResolver(), Settings.Secure.ACCESSIBILITY_SCRIPT_INJECTION, 0) == 1);
+            if (onDeviceScriptInjectionEnabled) {
+                ensureAccessibilityScriptInjectorInstance(false);
+                // neither script injected nor script injection opted out => we inject
+                mWebView.loadUrl(getScreenReaderInjectingJs());
+                // TODO: Set this flag after successfull script injection. Maybe upon injection
+                // the chooser should update the meta tag and we check it to declare success
+                mAccessibilityScriptInjected = true;
+            } else {
+                // injection disabled so we fallback to the basic built-in support
+                ensureAccessibilityScriptInjectorInstance(true);
+            }
+        } else if (axsParameterValue == ACCESSIBILITY_SCRIPT_INJECTION_OPTED_OUT) {
+            // injection opted out so we fallback to the basic buil-in support
+            ensureAccessibilityScriptInjectorInstance(true);
+        } else if (axsParameterValue == ACCESSIBILITY_SCRIPT_INJECTION_PROVIDED) {
+            ensureAccessibilityScriptInjectorInstance(false);
+            // the URL provides accessibility but we still need to add our generic script
+            mWebView.loadUrl(getScreenReaderInjectingJs());
+        } else {
+            Log.e(LOGTAG, "Unknown URL value for the \"axs\" URL parameter: " + axsParameterValue);
+        }
+    }
+
+    /**
+     * Ensures the instance of the {@link AccessibilityInjector} to be present ot not.
+     *
+     * @param present True to ensure an insance, false to ensure no instance.
+     */
+    private void ensureAccessibilityScriptInjectorInstance(boolean present) {
+        if (present) {
+            if (mAccessibilityInjector == null) {
+                mAccessibilityInjector = new AccessibilityInjector(this);
+            }
+        } else {
+            mAccessibilityInjector = null;
+        }
+    }
+
+    /**
+     * Gets JavaScript that injects a screen-reader.
+     *
+     * @return The JavaScript snippet.
+     */
+    private String getScreenReaderInjectingJs() {
+        String screenReaderUrl = Settings.Secure.getString(mContext.getContentResolver(),
+                Settings.Secure.ACCESSIBILITY_SCREEN_READER_URL);
+        return String.format(ACCESSIBILITY_SCREEN_READER_JAVASCRIPT_TEMPLATE, screenReaderUrl);
+    }
+
+    /**
+     * Gets the "axs" URL parameter value.
+     *
+     * @param url A url to fetch the paramter from.
+     * @return The parameter value if such, -1 otherwise.
+     */
+    private int getAxsUrlParameterValue(String url) {
+        if (mMatchAxsUrlParameterPattern == null) {
+            mMatchAxsUrlParameterPattern = Pattern.compile(PATTERN_MATCH_AXS_URL_PARAMETER);
+        }
+        Matcher matcher = mMatchAxsUrlParameterPattern.matcher(url);
+        if (matcher.find()) {
+            String keyValuePair = url.substring(matcher.start(), matcher.end());
+            return Integer.parseInt(keyValuePair.split("=")[1]);
+        }
+        return -1;
+    }
+
+    /**
+     * The URL of a page that sent a message to scroll the title bar off screen.
+     *
+     * Many mobile sites tell the page to scroll to (0,1) in order to scroll the
+     * title bar off the screen.  Sometimes, the scroll position is set before
+     * the page finishes loading.  Rather than scrolling while the page is still
+     * loading, keep track of the URL and new scroll position so we can perform
+     * the scroll once the page finishes loading.
+     */
+    private String mPageThatNeedsToSlideTitleBarOffScreen;
+
+    /**
+     * The destination Y scroll position to be used when the page finishes
+     * loading.  See mPageThatNeedsToSlideTitleBarOffScreen.
+     */
+    private int mYDistanceToSlideTitleOffScreen;
+
+    // scale from content to view coordinates, and pin
+    // return true if pin caused the final x/y different than the request cx/cy,
+    // and a future scroll may reach the request cx/cy after our size has
+    // changed
+    // return false if the view scroll to the exact position as it is requested,
+    // where negative numbers are taken to mean 0
+    private boolean setContentScrollTo(int cx, int cy) {
+        if (mDrawHistory) {
+            // disallow WebView to change the scroll position as History Picture
+            // is used in the view system.
+            // One known case where this is called is that WebCore tries to
+            // restore the scroll position. As history Picture already uses the
+            // saved scroll position, it is ok to skip this.
+            return false;
+        }
+        int vx;
+        int vy;
+        if ((cx | cy) == 0) {
+            // If the page is being scrolled to (0,0), do not add in the title
+            // bar's height, and simply scroll to (0,0). (The only other work
+            // in contentToView_ is to multiply, so this would not change 0.)
+            vx = 0;
+            vy = 0;
+        } else {
+            vx = contentToViewX(cx);
+            vy = contentToViewY(cy);
+        }
+//        Log.d(LOGTAG, "content scrollTo [" + cx + " " + cy + "] view=[" +
+//                      vx + " " + vy + "]");
+        // Some mobile sites attempt to scroll the title bar off the page by
+        // scrolling to (0,1).  If we are at the top left corner of the
+        // page, assume this is an attempt to scroll off the title bar, and
+        // animate the title bar off screen slowly enough that the user can see
+        // it.
+        if (cx == 0 && cy == 1 && getScrollX() == 0 && getScrollY() == 0
+                && mTitleBar != null) {
+            // FIXME: 100 should be defined somewhere as our max progress.
+            if (getProgress() < 100) {
+                // Wait to scroll the title bar off screen until the page has
+                // finished loading.  Keep track of the URL and the destination
+                // Y position
+                mPageThatNeedsToSlideTitleBarOffScreen = getUrl();
+                mYDistanceToSlideTitleOffScreen = vy;
+            } else {
+                pinScrollTo(vx, vy, true, SLIDE_TITLE_DURATION);
+            }
+            // Since we are animating, we have not yet reached the desired
+            // scroll position.  Do not return true to request another attempt
+            return false;
+        }
+        pinScrollTo(vx, vy, false, 0);
+        // If the request was to scroll to a negative coordinate, treat it as if
+        // it was a request to scroll to 0
+        if ((getScrollX() != vx && cx >= 0) || (getScrollY() != vy && cy >= 0)) {
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    // scale from content to view coordinates, and pin
+    private void spawnContentScrollTo(int cx, int cy) {
+        if (mDrawHistory) {
+            // disallow WebView to change the scroll position as History Picture
+            // is used in the view system.
+            return;
+        }
+        int vx = contentToViewX(cx);
+        int vy = contentToViewY(cy);
+        pinScrollTo(vx, vy, true, 0);
+    }
+
+    /**
+     * These are from webkit, and are in content coordinate system (unzoomed)
+     */
+    private void contentSizeChanged(boolean updateLayout) {
+        // suppress 0,0 since we usually see real dimensions soon after
+        // this avoids drawing the prev content in a funny place. If we find a
+        // way to consolidate these notifications, this check may become
+        // obsolete
+        if ((mContentWidth | mContentHeight) == 0) {
+            return;
+        }
+
+        if (mHeightCanMeasure) {
+            if (mWebView.getMeasuredHeight() != contentToViewDimension(mContentHeight)
+                    || updateLayout) {
+                mWebView.requestLayout();
+            }
+        } else if (mWidthCanMeasure) {
+            if (mWebView.getMeasuredWidth() != contentToViewDimension(mContentWidth)
+                    || updateLayout) {
+                mWebView.requestLayout();
+            }
+        } else {
+            // If we don't request a layout, try to send our view size to the
+            // native side to ensure that WebCore has the correct dimensions.
+            sendViewSizeZoom(false);
+        }
+    }
+
+    /**
+     * See {@link WebView#setWebViewClient(WebViewClient)}
+     */
+    @Override
+    public void setWebViewClient(WebViewClient client) {
+        checkThread();
+        mCallbackProxy.setWebViewClient(client);
+    }
+
+    /**
+     * Gets the WebViewClient
+     * @return the current WebViewClient instance.
+     *
+     * @hide This is an implementation detail.
+     */
+    public WebViewClient getWebViewClient() {
+        return mCallbackProxy.getWebViewClient();
+    }
+
+    /**
+     * See {@link WebView#setDownloadListener(DownloadListener)}
+     */
+    @Override
+    public void setDownloadListener(DownloadListener listener) {
+        checkThread();
+        mCallbackProxy.setDownloadListener(listener);
+    }
+
+    /**
+     * See {@link WebView#setWebChromeClient(WebChromeClient)}
+     */
+    @Override
+    public void setWebChromeClient(WebChromeClient client) {
+        checkThread();
+        mCallbackProxy.setWebChromeClient(client);
+    }
+
+    /**
+     * Gets the chrome handler.
+     * @return the current WebChromeClient instance.
+     *
+     * @hide This is an implementation detail.
+     */
+    public WebChromeClient getWebChromeClient() {
+        return mCallbackProxy.getWebChromeClient();
+    }
+
+    /**
+     * Set the back/forward list client. This is an implementation of
+     * WebBackForwardListClient for handling new items and changes in the
+     * history index.
+     * @param client An implementation of WebBackForwardListClient.
+     * {@hide}
+     */
+    public void setWebBackForwardListClient(WebBackForwardListClient client) {
+        mCallbackProxy.setWebBackForwardListClient(client);
+    }
+
+    /**
+     * Gets the WebBackForwardListClient.
+     * {@hide}
+     */
+    public WebBackForwardListClient getWebBackForwardListClient() {
+        return mCallbackProxy.getWebBackForwardListClient();
+    }
+
+    /**
+     * See {@link WebView#setPictureListener(PictureListener)}
+     */
+    @Override
+    @Deprecated
+    public void setPictureListener(PictureListener listener) {
+        checkThread();
+        mPictureListener = listener;
+    }
+
+    /**
+     * {@hide}
+     */
+    /* FIXME: Debug only! Remove for SDK! */
+    public void externalRepresentation(Message callback) {
+        mWebViewCore.sendMessage(EventHub.REQUEST_EXT_REPRESENTATION, callback);
+    }
+
+    /**
+     * {@hide}
+     */
+    /* FIXME: Debug only! Remove for SDK! */
+    public void documentAsText(Message callback) {
+        mWebViewCore.sendMessage(EventHub.REQUEST_DOC_AS_TEXT, callback);
+    }
+
+    /**
+     * See {@link WebView#addJavascriptInterface(Object, String)}
+     */
+    @Override
+    public void addJavascriptInterface(Object object, String name) {
+        checkThread();
+        if (object == null) {
+            return;
+        }
+        WebViewCore.JSInterfaceData arg = new WebViewCore.JSInterfaceData();
+        arg.mObject = object;
+        arg.mInterfaceName = name;
+        mWebViewCore.sendMessage(EventHub.ADD_JS_INTERFACE, arg);
+    }
+
+    /**
+     * See {@link WebView#removeJavascriptInterface(String)}
+     */
+    @Override
+    public void removeJavascriptInterface(String interfaceName) {
+        checkThread();
+        if (mWebViewCore != null) {
+            WebViewCore.JSInterfaceData arg = new WebViewCore.JSInterfaceData();
+            arg.mInterfaceName = interfaceName;
+            mWebViewCore.sendMessage(EventHub.REMOVE_JS_INTERFACE, arg);
+        }
+    }
+
+    /**
+     * See {@link WebView#getSettings()}
+     * Note this returns WebSettingsClassic, a sub-class of WebSettings, which can be used
+     * to access extension APIs.
+     */
+    @Override
+    public WebSettingsClassic getSettings() {
+        checkThread();
+        return (mWebViewCore != null) ? mWebViewCore.getSettings() : null;
+    }
+
+    /**
+     * See {@link WebView#getPluginList()}
+     */
+    @Deprecated
+    public static synchronized PluginList getPluginList() {
+        checkThread();
+        return new PluginList();
+    }
+
+    /**
+     * See {@link WebView#refreshPlugins(boolean)}
+     */
+    @Deprecated
+    public void refreshPlugins(boolean reloadOpenPages) {
+        checkThread();
+    }
+
+    //-------------------------------------------------------------------------
+    // Override View methods
+    //-------------------------------------------------------------------------
+
+    @Override
+    protected void finalize() throws Throwable {
+        try {
+            if (mNativeClass != 0) {
+                mPrivateHandler.post(new Runnable() {
+                    @Override
+                    public void run() {
+                        destroy();
+                    }
+                });
+            }
+        } finally {
+            super.finalize();
+        }
+    }
+
+    @Override
+    public boolean drawChild(Canvas canvas, View child, long drawingTime) {
+        if (child == mTitleBar) {
+            // When drawing the title bar, move it horizontally to always show
+            // at the top of the WebView.
+            mTitleBar.offsetLeftAndRight(getScrollX() - mTitleBar.getLeft());
+            int newTop = 0;
+            if (mTitleGravity == Gravity.NO_GRAVITY) {
+                newTop = Math.min(0, getScrollY());
+            } else if (mTitleGravity == Gravity.TOP) {
+                newTop = getScrollY();
+            }
+            mTitleBar.setBottom(newTop + mTitleBar.getHeight());
+            mTitleBar.setTop(newTop);
+        }
+        return false;  // We never call invalidate(), so unconditionally returning false.
+    }
+
+    private void drawContent(Canvas canvas) {
+        if (mDrawHistory) {
+            canvas.scale(mZoomManager.getScale(), mZoomManager.getScale());
+            canvas.drawPicture(mHistoryPicture);
+            return;
+        }
+        if (mNativeClass == 0) return;
+
+        boolean animateZoom = mZoomManager.isFixedLengthAnimationInProgress();
+        boolean animateScroll = ((!mScroller.isFinished()
+                || mVelocityTracker != null)
+                && (mTouchMode != TOUCH_DRAG_MODE ||
+                mHeldMotionless != MOTIONLESS_TRUE))
+                || mDeferTouchMode == TOUCH_DRAG_MODE;
+        if (mTouchMode == TOUCH_DRAG_MODE) {
+            if (mHeldMotionless == MOTIONLESS_PENDING) {
+                mPrivateHandler.removeMessages(DRAG_HELD_MOTIONLESS);
+                mPrivateHandler.removeMessages(AWAKEN_SCROLL_BARS);
+                mHeldMotionless = MOTIONLESS_FALSE;
+            }
+            if (mHeldMotionless == MOTIONLESS_FALSE) {
+                mPrivateHandler.sendMessageDelayed(mPrivateHandler
+                        .obtainMessage(DRAG_HELD_MOTIONLESS), MOTIONLESS_TIME);
+                mPrivateHandler.sendMessageDelayed(mPrivateHandler
+                        .obtainMessage(AWAKEN_SCROLL_BARS),
+                            ViewConfiguration.getScrollDefaultDelay());
+                mHeldMotionless = MOTIONLESS_PENDING;
+            }
+        }
+        int saveCount = canvas.save();
+        if (animateZoom) {
+            mZoomManager.animateZoom(canvas);
+        } else if (!canvas.isHardwareAccelerated()) {
+            canvas.scale(mZoomManager.getScale(), mZoomManager.getScale());
+        }
+
+        boolean UIAnimationsRunning = false;
+        // Currently for each draw we compute the animation values;
+        // We may in the future decide to do that independently.
+        if (mNativeClass != 0 && !canvas.isHardwareAccelerated()
+                && nativeEvaluateLayersAnimations(mNativeClass)) {
+            UIAnimationsRunning = true;
+            // If we have unfinished (or unstarted) animations,
+            // we ask for a repaint. We only need to do this in software
+            // rendering (with hardware rendering we already have a different
+            // method of requesting a repaint)
+            mWebViewCore.sendMessage(EventHub.NOTIFY_ANIMATION_STARTED);
+            invalidate();
+        }
+
+        // decide which adornments to draw
+        int extras = DRAW_EXTRAS_NONE;
+        if (!mFindIsUp && mSelectingText) {
+            extras = DRAW_EXTRAS_SELECTION;
+        }
+
+        calcOurContentVisibleRectF(mVisibleContentRect);
+        if (canvas.isHardwareAccelerated()) {
+            Rect glRectViewport = mGLViewportEmpty ? null : mGLRectViewport;
+            Rect viewRectViewport = mGLViewportEmpty ? null : mViewRectViewport;
+
+            int functor = nativeGetDrawGLFunction(mNativeClass, glRectViewport,
+                    viewRectViewport, mVisibleContentRect, getScale(), extras);
+            ((HardwareCanvas) canvas).callDrawGLFunction(functor);
+            if (mHardwareAccelSkia != getSettings().getHardwareAccelSkiaEnabled()) {
+                mHardwareAccelSkia = getSettings().getHardwareAccelSkiaEnabled();
+                nativeUseHardwareAccelSkia(mHardwareAccelSkia);
+            }
+
+        } else {
+            DrawFilter df = null;
+            if (mZoomManager.isZoomAnimating() || UIAnimationsRunning) {
+                df = mZoomFilter;
+            } else if (animateScroll) {
+                df = mScrollFilter;
+            }
+            canvas.setDrawFilter(df);
+            // XXX: Revisit splitting content.  Right now it causes a
+            // synchronization problem with layers.
+            int content = nativeDraw(canvas, mVisibleContentRect, mBackgroundColor,
+                    extras, false);
+            canvas.setDrawFilter(null);
+            if (!mBlockWebkitViewMessages && content != 0) {
+                mWebViewCore.sendMessage(EventHub.SPLIT_PICTURE_SET, content, 0);
+            }
+        }
+
+        canvas.restoreToCount(saveCount);
+        if (mSelectingText) {
+            drawTextSelectionHandles(canvas);
+        }
+
+        if (extras == DRAW_EXTRAS_CURSOR_RING) {
+            if (mTouchMode == TOUCH_SHORTPRESS_START_MODE) {
+                mTouchMode = TOUCH_SHORTPRESS_MODE;
+            }
+        }
+    }
+
+    /**
+     * Draw the background when beyond bounds
+     * @param canvas Canvas to draw into
+     */
+    private void drawOverScrollBackground(Canvas canvas) {
+        if (mOverScrollBackground == null) {
+            mOverScrollBackground = new Paint();
+            Bitmap bm = BitmapFactory.decodeResource(
+                    mContext.getResources(),
+                    com.android.internal.R.drawable.status_bar_background);
+            mOverScrollBackground.setShader(new BitmapShader(bm,
+                    Shader.TileMode.REPEAT, Shader.TileMode.REPEAT));
+            mOverScrollBorder = new Paint();
+            mOverScrollBorder.setStyle(Paint.Style.STROKE);
+            mOverScrollBorder.setStrokeWidth(0);
+            mOverScrollBorder.setColor(0xffbbbbbb);
+        }
+
+        int top = 0;
+        int right = computeRealHorizontalScrollRange();
+        int bottom = top + computeRealVerticalScrollRange();
+        // first draw the background and anchor to the top of the view
+        canvas.save();
+        canvas.translate(getScrollX(), getScrollY());
+        canvas.clipRect(-getScrollX(), top - getScrollY(), right - getScrollX(), bottom
+                - getScrollY(), Region.Op.DIFFERENCE);
+        canvas.drawPaint(mOverScrollBackground);
+        canvas.restore();
+        // then draw the border
+        canvas.drawRect(-1, top - 1, right, bottom, mOverScrollBorder);
+        // next clip the region for the content
+        canvas.clipRect(0, top, right, bottom);
+    }
+
+    @Override
+    public void onDraw(Canvas canvas) {
+        if (inFullScreenMode()) {
+            return; // no need to draw anything if we aren't visible.
+        }
+        // if mNativeClass is 0, the WebView is either destroyed or not
+        // initialized. In either case, just draw the background color and return
+        if (mNativeClass == 0) {
+            canvas.drawColor(mBackgroundColor);
+            return;
+        }
+
+        // if both mContentWidth and mContentHeight are 0, it means there is no
+        // valid Picture passed to WebView yet. This can happen when WebView
+        // just starts. Draw the background and return.
+        if ((mContentWidth | mContentHeight) == 0 && mHistoryPicture == null) {
+            canvas.drawColor(mBackgroundColor);
+            return;
+        }
+
+        if (canvas.isHardwareAccelerated()) {
+            mZoomManager.setHardwareAccelerated();
+        } else {
+            mWebViewCore.resumeWebKitDraw();
+        }
+
+        int saveCount = canvas.save();
+        if (mInOverScrollMode && !getSettings()
+                .getUseWebViewBackgroundForOverscrollBackground()) {
+            drawOverScrollBackground(canvas);
+        }
+        if (mTitleBar != null) {
+            canvas.translate(0, getTitleHeight());
+        }
+        drawContent(canvas);
+        canvas.restoreToCount(saveCount);
+
+        if (AUTO_REDRAW_HACK && mAutoRedraw) {
+            invalidate();
+        }
+        mWebViewCore.signalRepaintDone();
+
+        if (mOverScrollGlow != null && mOverScrollGlow.drawEdgeGlows(canvas)) {
+            invalidate();
+        }
+
+        if (mFocusTransition != null) {
+            mFocusTransition.draw(canvas);
+        } else if (shouldDrawHighlightRect()) {
+            RegionIterator iter = new RegionIterator(mTouchHighlightRegion);
+            Rect r = new Rect();
+            while (iter.next(r)) {
+                canvas.drawRect(r, mTouchHightlightPaint);
+            }
+        }
+        if (DEBUG_TOUCH_HIGHLIGHT) {
+            if (getSettings().getNavDump()) {
+                if ((mTouchHighlightX | mTouchHighlightY) != 0) {
+                    if (mTouchCrossHairColor == null) {
+                        mTouchCrossHairColor = new Paint();
+                        mTouchCrossHairColor.setColor(Color.RED);
+                    }
+                    canvas.drawLine(mTouchHighlightX - mNavSlop,
+                            mTouchHighlightY - mNavSlop, mTouchHighlightX
+                                    + mNavSlop + 1, mTouchHighlightY + mNavSlop
+                                    + 1, mTouchCrossHairColor);
+                    canvas.drawLine(mTouchHighlightX + mNavSlop + 1,
+                            mTouchHighlightY - mNavSlop, mTouchHighlightX
+                                    - mNavSlop,
+                            mTouchHighlightY + mNavSlop + 1,
+                            mTouchCrossHairColor);
+                }
+            }
+        }
+    }
+
+    private void removeTouchHighlight() {
+        mWebViewCore.removeMessages(EventHub.HIT_TEST);
+        mPrivateHandler.removeMessages(HIT_TEST_RESULT);
+        setTouchHighlightRects(null);
+    }
+
+    @Override
+    public void setLayoutParams(ViewGroup.LayoutParams params) {
+        if (params.height == AbsoluteLayout.LayoutParams.WRAP_CONTENT) {
+            mWrapContent = true;
+        }
+        mWebViewPrivate.super_setLayoutParams(params);
+    }
+
+    @Override
+    public boolean performLongClick() {
+        // performLongClick() is the result of a delayed message. If we switch
+        // to windows overview, the WebView will be temporarily removed from the
+        // view system. In that case, do nothing.
+        if (mWebView.getParent() == null) return false;
+
+        // A multi-finger gesture can look like a long press; make sure we don't take
+        // long press actions if we're scaling.
+        final ScaleGestureDetector detector = mZoomManager.getMultiTouchGestureDetector();
+        if (detector != null && detector.isInProgress()) {
+            return false;
+        }
+
+        if (mSelectingText) return false; // long click does nothing on selection
+        /* if long click brings up a context menu, the super function
+         * returns true and we're done. Otherwise, nothing happened when
+         * the user clicked. */
+        if (mWebViewPrivate.super_performLongClick()) {
+            return true;
+        }
+        /* In the case where the application hasn't already handled the long
+         * click action, look for a word under the  click. If one is found,
+         * animate the text selection into view.
+         * FIXME: no animation code yet */
+        final boolean isSelecting = selectText();
+        if (isSelecting) {
+            mWebView.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
+        } else if (focusCandidateIsEditableText()) {
+            mSelectCallback = new SelectActionModeCallback();
+            mSelectCallback.setWebView(this);
+            mSelectCallback.setTextSelected(false);
+            mWebView.startActionMode(mSelectCallback);
+        }
+        return isSelecting;
+    }
+
+    /**
+     * Select the word at the last click point.
+     *
+     * @hide This is an implementation detail.
+     */
+    public boolean selectText() {
+        int x = viewToContentX(mLastTouchX + getScrollX());
+        int y = viewToContentY(mLastTouchY + getScrollY());
+        return selectText(x, y);
+    }
+
+    /**
+     * Select the word at the indicated content coordinates.
+     */
+    boolean selectText(int x, int y) {
+        mWebViewCore.sendMessage(EventHub.SELECT_WORD_AT, x, y);
+        return true;
+    }
+
+    private int mOrientation = Configuration.ORIENTATION_UNDEFINED;
+
+    @Override
+    public void onConfigurationChanged(Configuration newConfig) {
+        mCachedOverlappingActionModeHeight = -1;
+        if (mSelectingText && mOrientation != newConfig.orientation) {
+            selectionDone();
+        }
+        mOrientation = newConfig.orientation;
+        if (mWebViewCore != null && !mBlockWebkitViewMessages) {
+            mWebViewCore.sendMessage(EventHub.CLEAR_CONTENT);
+        }
+    }
+
+    /**
+     * Keep track of the Callback so we can end its ActionMode or remove its
+     * titlebar.
+     */
+    private SelectActionModeCallback mSelectCallback;
+
+    void setBaseLayer(int layer, Region invalRegion, boolean showVisualIndicator,
+            boolean isPictureAfterFirstLayout) {
+        if (mNativeClass == 0)
+            return;
+        boolean queueFull;
+        queueFull = nativeSetBaseLayer(mNativeClass, layer, invalRegion,
+                                       showVisualIndicator, isPictureAfterFirstLayout);
+
+        if (layer == 0 || isPictureAfterFirstLayout) {
+            mWebViewCore.resumeWebKitDraw();
+        } else if (queueFull) {
+            mWebViewCore.pauseWebKitDraw();
+        }
+
+        if (mHTML5VideoViewProxy != null) {
+            mHTML5VideoViewProxy.setBaseLayer(layer);
+        }
+    }
+
+    int getBaseLayer() {
+        if (mNativeClass == 0) {
+            return 0;
+        }
+        return nativeGetBaseLayer();
+    }
+
+    private void onZoomAnimationStart() {
+    }
+
+    private void onZoomAnimationEnd() {
+    }
+
+    void onFixedLengthZoomAnimationStart() {
+        WebViewCore.pauseUpdatePicture(getWebViewCore());
+        onZoomAnimationStart();
+    }
+
+    void onFixedLengthZoomAnimationEnd() {
+        if (!mBlockWebkitViewMessages && !mSelectingText) {
+            WebViewCore.resumeUpdatePicture(mWebViewCore);
+        }
+        onZoomAnimationEnd();
+    }
+
+    private static final int ZOOM_BITS = Paint.FILTER_BITMAP_FLAG |
+                                         Paint.DITHER_FLAG |
+                                         Paint.SUBPIXEL_TEXT_FLAG;
+    private static final int SCROLL_BITS = Paint.FILTER_BITMAP_FLAG |
+                                           Paint.DITHER_FLAG;
+
+    private final DrawFilter mZoomFilter =
+            new PaintFlagsDrawFilter(ZOOM_BITS, Paint.LINEAR_TEXT_FLAG);
+    // If we need to trade better quality for speed, set mScrollFilter to null
+    private final DrawFilter mScrollFilter =
+            new PaintFlagsDrawFilter(SCROLL_BITS, 0);
+
+    private void ensureSelectionHandles() {
+        if (mSelectHandleCenter == null) {
+            mSelectHandleCenter = mContext.getResources().getDrawable(
+                    com.android.internal.R.drawable.text_select_handle_middle);
+            mSelectHandleLeft = mContext.getResources().getDrawable(
+                    com.android.internal.R.drawable.text_select_handle_left);
+            mSelectHandleRight = mContext.getResources().getDrawable(
+                    com.android.internal.R.drawable.text_select_handle_right);
+        }
+    }
+
+    private void drawTextSelectionHandles(Canvas canvas) {
+        ensureSelectionHandles();
+        int[] handles = new int[4];
+        getSelectionHandles(handles);
+        int start_x = contentToViewDimension(handles[0]);
+        int start_y = contentToViewDimension(handles[1]);
+        int end_x = contentToViewDimension(handles[2]);
+        int end_y = contentToViewDimension(handles[3]);
+
+        if (mIsCaretSelection) {
+            // Caret handle is centered
+            start_x -= (mSelectHandleCenter.getIntrinsicWidth() / 2);
+            mSelectHandleCenter.setBounds(start_x, start_y,
+                    start_x + mSelectHandleCenter.getIntrinsicWidth(),
+                    start_y + mSelectHandleCenter.getIntrinsicHeight());
+            mSelectHandleCenter.draw(canvas);
+        } else {
+            // Magic formula copied from TextView
+            start_x -= (mSelectHandleLeft.getIntrinsicWidth() * 3) / 4;
+            mSelectHandleLeft.setBounds(start_x, start_y,
+                    start_x + mSelectHandleLeft.getIntrinsicWidth(),
+                    start_y + mSelectHandleLeft.getIntrinsicHeight());
+            end_x -= mSelectHandleRight.getIntrinsicWidth() / 4;
+            mSelectHandleRight.setBounds(end_x, end_y,
+                    end_x + mSelectHandleRight.getIntrinsicWidth(),
+                    end_y + mSelectHandleRight.getIntrinsicHeight());
+            mSelectHandleLeft.draw(canvas);
+            mSelectHandleRight.draw(canvas);
+        }
+    }
+
+    /**
+     * Takes an int[4] array as an output param with the values being
+     * startX, startY, endX, endY
+     */
+    private void getSelectionHandles(int[] handles) {
+        handles[0] = mSelectCursorBase.right;
+        handles[1] = mSelectCursorBase.bottom -
+                (mSelectCursorBase.height() / 4);
+        handles[2] = mSelectCursorExtent.left;
+        handles[3] = mSelectCursorExtent.bottom
+                - (mSelectCursorExtent.height() / 4);
+        if (!nativeIsBaseFirst(mNativeClass)) {
+            int swap = handles[0];
+            handles[0] = handles[2];
+            handles[2] = swap;
+            swap = handles[1];
+            handles[1] = handles[3];
+            handles[3] = swap;
+        }
+    }
+
+    // draw history
+    private boolean mDrawHistory = false;
+    private Picture mHistoryPicture = null;
+    private int mHistoryWidth = 0;
+    private int mHistoryHeight = 0;
+
+    // Only check the flag, can be called from WebCore thread
+    boolean drawHistory() {
+        return mDrawHistory;
+    }
+
+    int getHistoryPictureWidth() {
+        return (mHistoryPicture != null) ? mHistoryPicture.getWidth() : 0;
+    }
+
+    // Should only be called in UI thread
+    void switchOutDrawHistory() {
+        if (null == mWebViewCore) return; // CallbackProxy may trigger this
+        if (mDrawHistory && (getProgress() == 100 || nativeHasContent())) {
+            mDrawHistory = false;
+            mHistoryPicture = null;
+            invalidate();
+            int oldScrollX = getScrollX();
+            int oldScrollY = getScrollY();
+            setScrollXRaw(pinLocX(getScrollX()));
+            setScrollYRaw(pinLocY(getScrollY()));
+            if (oldScrollX != getScrollX() || oldScrollY != getScrollY()) {
+                mWebViewPrivate.onScrollChanged(getScrollX(), getScrollY(), oldScrollX, oldScrollY);
+            } else {
+                sendOurVisibleRect();
+            }
+        }
+    }
+
+    /**
+     *  Delete text from start to end in the focused textfield. If there is no
+     *  focus, or if start == end, silently fail.  If start and end are out of
+     *  order, swap them.
+     *  @param  start   Beginning of selection to delete.
+     *  @param  end     End of selection to delete.
+     */
+    /* package */ void deleteSelection(int start, int end) {
+        mTextGeneration++;
+        WebViewCore.TextSelectionData data
+                = new WebViewCore.TextSelectionData(start, end, 0);
+        mWebViewCore.sendMessage(EventHub.DELETE_SELECTION, mTextGeneration, 0,
+                data);
+    }
+
+    /**
+     *  Set the selection to (start, end) in the focused textfield. If start and
+     *  end are out of order, swap them.
+     *  @param  start   Beginning of selection.
+     *  @param  end     End of selection.
+     */
+    /* package */ void setSelection(int start, int end) {
+        if (mWebViewCore != null) {
+            mWebViewCore.sendMessage(EventHub.SET_SELECTION, start, end);
+        }
+    }
+
+    @Override
+    public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
+        if (mInputConnection == null) {
+            mInputConnection = new WebViewInputConnection();
+        }
+        mInputConnection.setupEditorInfo(outAttrs);
+        return mInputConnection;
+    }
+
+    /**
+     * Called in response to a message from webkit telling us that the soft
+     * keyboard should be launched.
+     */
+    private void displaySoftKeyboard(boolean isTextView) {
+        InputMethodManager imm = (InputMethodManager)
+                mContext.getSystemService(Context.INPUT_METHOD_SERVICE);
+
+        // bring it back to the default level scale so that user can enter text
+        boolean zoom = mZoomManager.getScale() < mZoomManager.getDefaultScale();
+        if (zoom) {
+            mZoomManager.setZoomCenter(mLastTouchX, mLastTouchY);
+            mZoomManager.setZoomScale(mZoomManager.getDefaultScale(), false);
+        }
+        // Used by plugins and contentEditable.
+        // Also used if the navigation cache is out of date, and
+        // does not recognize that a textfield is in focus.  In that
+        // case, use WebView as the targeted view.
+        // see http://b/issue?id=2457459
+        imm.showSoftInput(mWebView, 0);
+    }
+
+    // Called by WebKit to instruct the UI to hide the keyboard
+    private void hideSoftKeyboard() {
+        InputMethodManager imm = InputMethodManager.peekInstance();
+        if (imm != null && (imm.isActive(mWebView))) {
+            imm.hideSoftInputFromWindow(mWebView.getWindowToken(), 0);
+        }
+    }
+
+    /**
+     * Dump the display tree to "/sdcard/displayTree.txt"
+     *
+     * @hide debug only
+     */
+    public void dumpDisplayTree() {
+        nativeDumpDisplayTree(getUrl());
+    }
+
+    /**
+     * Dump the dom tree to adb shell if "toFile" is False, otherwise dump it to
+     * "/sdcard/domTree.txt"
+     *
+     * @hide debug only
+     */
+    public void dumpDomTree(boolean toFile) {
+        mWebViewCore.sendMessage(EventHub.DUMP_DOMTREE, toFile ? 1 : 0, 0);
+    }
+
+    /**
+     * Dump the render tree to adb shell if "toFile" is False, otherwise dump it
+     * to "/sdcard/renderTree.txt"
+     *
+     * @hide debug only
+     */
+    public void dumpRenderTree(boolean toFile) {
+        mWebViewCore.sendMessage(EventHub.DUMP_RENDERTREE, toFile ? 1 : 0, 0);
+    }
+
+    /**
+     * Called by DRT on UI thread, need to proxy to WebCore thread.
+     *
+     * @hide debug only
+     */
+    public void useMockDeviceOrientation() {
+        mWebViewCore.sendMessage(EventHub.USE_MOCK_DEVICE_ORIENTATION);
+    }
+
+    /**
+     * Called by DRT on WebCore thread.
+     *
+     * @hide debug only
+     */
+    public void setMockDeviceOrientation(boolean canProvideAlpha, double alpha,
+            boolean canProvideBeta, double beta, boolean canProvideGamma, double gamma) {
+        mWebViewCore.setMockDeviceOrientation(canProvideAlpha, alpha, canProvideBeta, beta,
+                canProvideGamma, gamma);
+    }
+
+    // This is used to determine long press with the center key.  Does not
+    // affect long press with the trackball/touch.
+    private boolean mGotCenterDown = false;
+
+    @Override
+    public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) {
+        if (mBlockWebkitViewMessages) {
+            return false;
+        }
+        // send complex characters to webkit for use by JS and plugins
+        if (keyCode == KeyEvent.KEYCODE_UNKNOWN && event.getCharacters() != null) {
+            // pass the key to DOM
+            mWebViewCore.sendMessage(EventHub.KEY_DOWN, event);
+            mWebViewCore.sendMessage(EventHub.KEY_UP, event);
+            // return true as DOM handles the key
+            return true;
+        }
+        return false;
+    }
+
+    private boolean isEnterActionKey(int keyCode) {
+        return keyCode == KeyEvent.KEYCODE_DPAD_CENTER
+                || keyCode == KeyEvent.KEYCODE_ENTER
+                || keyCode == KeyEvent.KEYCODE_NUMPAD_ENTER;
+    }
+
+    @Override
+    public boolean onKeyDown(int keyCode, KeyEvent event) {
+        if (DebugFlags.WEB_VIEW) {
+            Log.v(LOGTAG, "keyDown at " + System.currentTimeMillis()
+                    + "keyCode=" + keyCode
+                    + ", " + event + ", unicode=" + event.getUnicodeChar());
+        }
+        if (mIsCaretSelection) {
+            selectionDone();
+        }
+        if (mBlockWebkitViewMessages) {
+            return false;
+        }
+
+        // don't implement accelerator keys here; defer to host application
+        if (event.isCtrlPressed()) {
+            return false;
+        }
+
+        if (mNativeClass == 0) {
+            return false;
+        }
+
+        // do this hack up front, so it always works, regardless of touch-mode
+        if (AUTO_REDRAW_HACK && (keyCode == KeyEvent.KEYCODE_CALL)) {
+            mAutoRedraw = !mAutoRedraw;
+            if (mAutoRedraw) {
+                invalidate();
+            }
+            return true;
+        }
+
+        // Bubble up the key event if
+        // 1. it is a system key; or
+        // 2. the host application wants to handle it;
+        if (event.isSystem()
+                || mCallbackProxy.uiOverrideKeyEvent(event)) {
+            return false;
+        }
+
+        // accessibility support
+        if (accessibilityScriptInjected()) {
+            if (AccessibilityManager.getInstance(mContext).isEnabled()) {
+                // if an accessibility script is injected we delegate to it the key handling.
+                // this script is a screen reader which is a fully fledged solution for blind
+                // users to navigate in and interact with web pages.
+                mWebViewCore.sendMessage(EventHub.KEY_DOWN, event);
+                return true;
+            } else {
+                // Clean up if accessibility was disabled after loading the current URL.
+                mAccessibilityScriptInjected = false;
+            }
+        } else if (mAccessibilityInjector != null) {
+            if (AccessibilityManager.getInstance(mContext).isEnabled()) {
+                if (mAccessibilityInjector.onKeyEvent(event)) {
+                    // if an accessibility injector is present (no JavaScript enabled or the site
+                    // opts out injecting our JavaScript screen reader) we let it decide whether
+                    // to act on and consume the event.
+                    return true;
+                }
+            } else {
+                // Clean up if accessibility was disabled after loading the current URL.
+                mAccessibilityInjector = null;
+            }
+        }
+
+        if (keyCode == KeyEvent.KEYCODE_PAGE_UP) {
+            if (event.hasNoModifiers()) {
+                pageUp(false);
+                return true;
+            } else if (event.hasModifiers(KeyEvent.META_ALT_ON)) {
+                pageUp(true);
+                return true;
+            }
+        }
+
+        if (keyCode == KeyEvent.KEYCODE_PAGE_DOWN) {
+            if (event.hasNoModifiers()) {
+                pageDown(false);
+                return true;
+            } else if (event.hasModifiers(KeyEvent.META_ALT_ON)) {
+                pageDown(true);
+                return true;
+            }
+        }
+
+        if (keyCode == KeyEvent.KEYCODE_MOVE_HOME && event.hasNoModifiers()) {
+            pageUp(true);
+            return true;
+        }
+
+        if (keyCode == KeyEvent.KEYCODE_MOVE_END && event.hasNoModifiers()) {
+            pageDown(true);
+            return true;
+        }
+
+        if (keyCode >= KeyEvent.KEYCODE_DPAD_UP
+                && keyCode <= KeyEvent.KEYCODE_DPAD_RIGHT) {
+            switchOutDrawHistory();
+        }
+
+        if (isEnterActionKey(keyCode)) {
+            switchOutDrawHistory();
+            if (event.getRepeatCount() == 0) {
+                if (mSelectingText) {
+                    return true; // discard press if copy in progress
+                }
+                mGotCenterDown = true;
+                mPrivateHandler.sendMessageDelayed(mPrivateHandler
+                        .obtainMessage(LONG_PRESS_CENTER), LONG_PRESS_TIMEOUT);
+            }
+        }
+
+        if (getSettings().getNavDump()) {
+            switch (keyCode) {
+                case KeyEvent.KEYCODE_4:
+                    dumpDisplayTree();
+                    break;
+                case KeyEvent.KEYCODE_5:
+                case KeyEvent.KEYCODE_6:
+                    dumpDomTree(keyCode == KeyEvent.KEYCODE_5);
+                    break;
+                case KeyEvent.KEYCODE_7:
+                case KeyEvent.KEYCODE_8:
+                    dumpRenderTree(keyCode == KeyEvent.KEYCODE_7);
+                    break;
+            }
+        }
+
+        // pass the key to DOM
+        sendKeyEvent(event);
+        // return true as DOM handles the key
+        return true;
+    }
+
+    @Override
+    public boolean onKeyUp(int keyCode, KeyEvent event) {
+        if (DebugFlags.WEB_VIEW) {
+            Log.v(LOGTAG, "keyUp at " + System.currentTimeMillis()
+                    + ", " + event + ", unicode=" + event.getUnicodeChar());
+        }
+        if (mBlockWebkitViewMessages) {
+            return false;
+        }
+
+        if (mNativeClass == 0) {
+            return false;
+        }
+
+        // special CALL handling when cursor node's href is "tel:XXX"
+        if (keyCode == KeyEvent.KEYCODE_CALL
+                && mInitialHitTestResult != null
+                && mInitialHitTestResult.getType() == HitTestResult.PHONE_TYPE) {
+            String text = mInitialHitTestResult.getExtra();
+            Intent intent = new Intent(Intent.ACTION_DIAL, Uri.parse(text));
+            mContext.startActivity(intent);
+            return true;
+        }
+
+        // Bubble up the key event if
+        // 1. it is a system key; or
+        // 2. the host application wants to handle it;
+        if (event.isSystem()
+                || mCallbackProxy.uiOverrideKeyEvent(event)) {
+            return false;
+        }
+
+        // accessibility support
+        if (accessibilityScriptInjected()) {
+            if (AccessibilityManager.getInstance(mContext).isEnabled()) {
+                // if an accessibility script is injected we delegate to it the key handling.
+                // this script is a screen reader which is a fully fledged solution for blind
+                // users to navigate in and interact with web pages.
+                mWebViewCore.sendMessage(EventHub.KEY_UP, event);
+                return true;
+            } else {
+                // Clean up if accessibility was disabled after loading the current URL.
+                mAccessibilityScriptInjected = false;
+            }
+        } else if (mAccessibilityInjector != null) {
+            if (AccessibilityManager.getInstance(mContext).isEnabled()) {
+                if (mAccessibilityInjector.onKeyEvent(event)) {
+                    // if an accessibility injector is present (no JavaScript enabled or the site
+                    // opts out injecting our JavaScript screen reader) we let it decide whether to
+                    // act on and consume the event.
+                    return true;
+                }
+            } else {
+                // Clean up if accessibility was disabled after loading the current URL.
+                mAccessibilityInjector = null;
+            }
+        }
+
+        if (isEnterActionKey(keyCode)) {
+            // remove the long press message first
+            mPrivateHandler.removeMessages(LONG_PRESS_CENTER);
+            mGotCenterDown = false;
+
+            if (mSelectingText) {
+                copySelection();
+                selectionDone();
+                return true; // discard press if copy in progress
+            }
+        }
+
+        // pass the key to DOM
+        sendKeyEvent(event);
+        // return true as DOM handles the key
+        return true;
+    }
+
+    private boolean startSelectActionMode() {
+        mSelectCallback = new SelectActionModeCallback();
+        mSelectCallback.setTextSelected(!mIsCaretSelection);
+        mSelectCallback.setWebView(this);
+        if (mWebView.startActionMode(mSelectCallback) == null) {
+            // There is no ActionMode, so do not allow the user to modify a
+            // selection.
+            selectionDone();
+            return false;
+        }
+        mWebView.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
+        return true;
+    }
+
+    private void showPasteWindow() {
+        ClipboardManager cm = (ClipboardManager)(mContext
+                .getSystemService(Context.CLIPBOARD_SERVICE));
+        if (cm.hasPrimaryClip()) {
+            Rect cursorRect = contentToViewRect(mSelectCursorBase);
+            int[] location = new int[2];
+            mWebView.getLocationInWindow(location);
+            cursorRect.offset(location[0] - getScrollX(), location[1] - getScrollY());
+            if (mPasteWindow == null) {
+                mPasteWindow = new PastePopupWindow();
+            }
+            mPasteWindow.show(cursorRect, location[0], location[1]);
+        }
+    }
+
+    private void hidePasteButton() {
+        if (mPasteWindow != null) {
+            mPasteWindow.hide();
+        }
+    }
+
+    private void syncSelectionCursors() {
+        mSelectCursorBaseLayerId =
+                nativeGetHandleLayerId(mNativeClass, HANDLE_ID_BASE, mSelectCursorBase);
+        mSelectCursorExtentLayerId =
+                nativeGetHandleLayerId(mNativeClass, HANDLE_ID_EXTENT, mSelectCursorExtent);
+    }
+
+    private boolean setupWebkitSelect() {
+        syncSelectionCursors();
+        if (mIsCaretSelection) {
+            showPasteWindow();
+        } else if (!startSelectActionMode()) {
+            selectionDone();
+            return false;
+        }
+        mSelectingText = true;
+        mTouchMode = TOUCH_DRAG_MODE;
+        return true;
+    }
+
+    private void updateWebkitSelection() {
+        int[] handles = null;
+        if (mIsCaretSelection) {
+            mSelectCursorExtent.set(mSelectCursorBase);
+        }
+        if (mSelectingText) {
+            handles = new int[4];
+            handles[0] = mSelectCursorBase.centerX();
+            handles[1] = mSelectCursorBase.centerY();
+            handles[2] = mSelectCursorExtent.centerX();
+            handles[3] = mSelectCursorExtent.centerY();
+        } else {
+            nativeSetTextSelection(mNativeClass, 0);
+        }
+        mWebViewCore.removeMessages(EventHub.SELECT_TEXT);
+        mWebViewCore.sendMessageAtFrontOfQueue(EventHub.SELECT_TEXT, handles);
+    }
+
+    private void resetCaretTimer() {
+        mPrivateHandler.removeMessages(CLEAR_CARET_HANDLE);
+        if (!mSelectionStarted) {
+            mPrivateHandler.sendEmptyMessageDelayed(CLEAR_CARET_HANDLE,
+                    CARET_HANDLE_STAMINA_MS);
+        }
+    }
+
+    /**
+     * See {@link WebView#emulateShiftHeld()}
+     */
+    @Override
+    @Deprecated
+    public void emulateShiftHeld() {
+        checkThread();
+    }
+
+    /**
+     * Select all of the text in this WebView.
+     *
+     * @hide This is an implementation detail.
+     */
+    public void selectAll() {
+        mWebViewCore.sendMessage(EventHub.SELECT_ALL);
+    }
+
+    /**
+     * Called when the selection has been removed.
+     */
+    void selectionDone() {
+        if (mSelectingText) {
+            hidePasteButton();
+            mSelectingText = false;
+            // finish is idempotent, so this is fine even if selectionDone was
+            // called by mSelectCallback.onDestroyActionMode
+            if (mSelectCallback != null) {
+                mSelectCallback.finish();
+                mSelectCallback = null;
+            }
+            if (!mIsCaretSelection) {
+                updateWebkitSelection();
+            }
+            mIsCaretSelection = false;
+            invalidate(); // redraw without selection
+            mAutoScrollX = 0;
+            mAutoScrollY = 0;
+            mSentAutoScrollMessage = false;
+        }
+    }
+
+    /**
+     * Copy the selection to the clipboard
+     *
+     * @hide This is an implementation detail.
+     */
+    public boolean copySelection() {
+        boolean copiedSomething = false;
+        String selection = getSelection();
+        if (selection != null && selection != "") {
+            if (DebugFlags.WEB_VIEW) {
+                Log.v(LOGTAG, "copySelection \"" + selection + "\"");
+            }
+            Toast.makeText(mContext
+                    , com.android.internal.R.string.text_copied
+                    , Toast.LENGTH_SHORT).show();
+            copiedSomething = true;
+            ClipboardManager cm = (ClipboardManager)mContext
+                    .getSystemService(Context.CLIPBOARD_SERVICE);
+            cm.setText(selection);
+            int[] handles = new int[4];
+            getSelectionHandles(handles);
+            mWebViewCore.sendMessage(EventHub.COPY_TEXT, handles);
+        }
+        invalidate(); // remove selection region and pointer
+        return copiedSomething;
+    }
+
+    /**
+     * Cut the selected text into the clipboard
+     *
+     * @hide This is an implementation detail
+     */
+    public void cutSelection() {
+        copySelection();
+        int[] handles = new int[4];
+        getSelectionHandles(handles);
+        mWebViewCore.sendMessage(EventHub.DELETE_TEXT, handles);
+    }
+
+    /**
+     * Paste text from the clipboard to the cursor position.
+     *
+     * @hide This is an implementation detail
+     */
+    public void pasteFromClipboard() {
+        ClipboardManager cm = (ClipboardManager)mContext
+                .getSystemService(Context.CLIPBOARD_SERVICE);
+        ClipData clipData = cm.getPrimaryClip();
+        if (clipData != null) {
+            ClipData.Item clipItem = clipData.getItemAt(0);
+            CharSequence pasteText = clipItem.getText();
+            if (mInputConnection != null) {
+                mInputConnection.replaceSelection(pasteText);
+            }
+        }
+    }
+
+    /**
+     * @hide This is an implementation detail.
+     */
+    public SearchBox getSearchBox() {
+        if ((mWebViewCore == null) || (mWebViewCore.getBrowserFrame() == null)) {
+            return null;
+        }
+        return mWebViewCore.getBrowserFrame().getSearchBox();
+    }
+
+    /**
+     * Returns the currently highlighted text as a string.
+     */
+    String getSelection() {
+        if (mNativeClass == 0) return "";
+        return nativeGetSelection();
+    }
+
+    @Override
+    public void onAttachedToWindow() {
+        if (mWebView.hasWindowFocus()) setActive(true);
+        final ViewTreeObserver treeObserver = mWebView.getViewTreeObserver();
+        if (mGlobalLayoutListener == null) {
+            mGlobalLayoutListener = new InnerGlobalLayoutListener();
+            treeObserver.addOnGlobalLayoutListener(mGlobalLayoutListener);
+        }
+        if (mScrollChangedListener == null) {
+            mScrollChangedListener = new InnerScrollChangedListener();
+            treeObserver.addOnScrollChangedListener(mScrollChangedListener);
+        }
+
+        addAccessibilityApisToJavaScript();
+
+        mTouchEventQueue.reset();
+    }
+
+    @Override
+    public void onDetachedFromWindow() {
+        clearHelpers();
+        mZoomManager.dismissZoomPicker();
+        if (mWebView.hasWindowFocus()) setActive(false);
+
+        final ViewTreeObserver treeObserver = mWebView.getViewTreeObserver();
+        if (mGlobalLayoutListener != null) {
+            treeObserver.removeGlobalOnLayoutListener(mGlobalLayoutListener);
+            mGlobalLayoutListener = null;
+        }
+        if (mScrollChangedListener != null) {
+            treeObserver.removeOnScrollChangedListener(mScrollChangedListener);
+            mScrollChangedListener = null;
+        }
+
+        removeAccessibilityApisFromJavaScript();
+    }
+
+    @Override
+    public void onVisibilityChanged(View changedView, int visibility) {
+        // The zoomManager may be null if the webview is created from XML that
+        // specifies the view's visibility param as not visible (see http://b/2794841)
+        if (visibility != View.VISIBLE && mZoomManager != null) {
+            mZoomManager.dismissZoomPicker();
+        }
+        updateDrawingState();
+    }
+
+    void setActive(boolean active) {
+        if (active) {
+            if (mWebView.hasFocus()) {
+                // If our window regained focus, and we have focus, then begin
+                // drawing the cursor ring
+                mDrawCursorRing = true;
+                setFocusControllerActive(true);
+            } else {
+                mDrawCursorRing = false;
+                setFocusControllerActive(false);
+            }
+        } else {
+            if (!mZoomManager.isZoomPickerVisible()) {
+                /*
+                 * The external zoom controls come in their own window, so our
+                 * window loses focus. Our policy is to not draw the cursor ring
+                 * if our window is not focused, but this is an exception since
+                 * the user can still navigate the web page with the zoom
+                 * controls showing.
+                 */
+                mDrawCursorRing = false;
+            }
+            mKeysPressed.clear();
+            mPrivateHandler.removeMessages(SWITCH_TO_LONGPRESS);
+            mTouchMode = TOUCH_DONE_MODE;
+            setFocusControllerActive(false);
+        }
+        invalidate();
+    }
+
+    // To avoid drawing the cursor ring, and remove the TextView when our window
+    // loses focus.
+    @Override
+    public void onWindowFocusChanged(boolean hasWindowFocus) {
+        setActive(hasWindowFocus);
+        if (hasWindowFocus) {
+            JWebCoreJavaBridge.setActiveWebView(this);
+            if (mPictureUpdatePausedForFocusChange) {
+                WebViewCore.resumeUpdatePicture(mWebViewCore);
+                mPictureUpdatePausedForFocusChange = false;
+            }
+        } else {
+            JWebCoreJavaBridge.removeActiveWebView(this);
+            final WebSettings settings = getSettings();
+            if (settings != null && settings.enableSmoothTransition() &&
+                    mWebViewCore != null && !WebViewCore.isUpdatePicturePaused(mWebViewCore)) {
+                WebViewCore.pauseUpdatePicture(mWebViewCore);
+                mPictureUpdatePausedForFocusChange = true;
+            }
+        }
+    }
+
+    /*
+     * Pass a message to WebCore Thread, telling the WebCore::Page's
+     * FocusController to be  "inactive" so that it will
+     * not draw the blinking cursor.  It gets set to "active" to draw the cursor
+     * in WebViewCore.cpp, when the WebCore thread receives key events/clicks.
+     */
+    /* package */ void setFocusControllerActive(boolean active) {
+        if (mWebViewCore == null) return;
+        mWebViewCore.sendMessage(EventHub.SET_ACTIVE, active ? 1 : 0, 0);
+        // Need to send this message after the document regains focus.
+        if (active && mListBoxMessage != null) {
+            mWebViewCore.sendMessage(mListBoxMessage);
+            mListBoxMessage = null;
+        }
+    }
+
+    @Override
+    public void onFocusChanged(boolean focused, int direction,
+            Rect previouslyFocusedRect) {
+        if (DebugFlags.WEB_VIEW) {
+            Log.v(LOGTAG, "MT focusChanged " + focused + ", " + direction);
+        }
+        if (focused) {
+            mDrawCursorRing = true;
+            setFocusControllerActive(true);
+        } else {
+            mDrawCursorRing = false;
+            setFocusControllerActive(false);
+            mKeysPressed.clear();
+        }
+        if (!mTouchHighlightRegion.isEmpty()) {
+            mWebView.invalidate(mTouchHighlightRegion.getBounds());
+        }
+    }
+
+    void setGLRectViewport() {
+        // Use the getGlobalVisibleRect() to get the intersection among the parents
+        // visible == false means we're clipped - send a null rect down to indicate that
+        // we should not draw
+        boolean visible = mWebView.getGlobalVisibleRect(mGLRectViewport);
+        if (visible) {
+            // Then need to invert the Y axis, just for GL
+            View rootView = mWebView.getRootView();
+            int rootViewHeight = rootView.getHeight();
+            mViewRectViewport.set(mGLRectViewport);
+            int savedWebViewBottom = mGLRectViewport.bottom;
+            mGLRectViewport.bottom = rootViewHeight - mGLRectViewport.top - getVisibleTitleHeightImpl();
+            mGLRectViewport.top = rootViewHeight - savedWebViewBottom;
+            mGLViewportEmpty = false;
+        } else {
+            mGLViewportEmpty = true;
+        }
+        calcOurContentVisibleRectF(mVisibleContentRect);
+        nativeUpdateDrawGLFunction(mGLViewportEmpty ? null : mGLRectViewport,
+                mGLViewportEmpty ? null : mViewRectViewport,
+                mVisibleContentRect, getScale());
+    }
+
+    /**
+     * @hide
+     */
+    @Override
+    public boolean setFrame(int left, int top, int right, int bottom) {
+        boolean changed = mWebViewPrivate.super_setFrame(left, top, right, bottom);
+        if (!changed && mHeightCanMeasure) {
+            // When mHeightCanMeasure is true, we will set mLastHeightSent to 0
+            // in WebViewCore after we get the first layout. We do call
+            // requestLayout() when we get contentSizeChanged(). But the View
+            // system won't call onSizeChanged if the dimension is not changed.
+            // In this case, we need to call sendViewSizeZoom() explicitly to
+            // notify the WebKit about the new dimensions.
+            sendViewSizeZoom(false);
+        }
+        setGLRectViewport();
+        return changed;
+    }
+
+    @Override
+    public void onSizeChanged(int w, int h, int ow, int oh) {
+        // adjust the max viewport width depending on the view dimensions. This
+        // is to ensure the scaling is not going insane. So do not shrink it if
+        // the view size is temporarily smaller, e.g. when soft keyboard is up.
+        int newMaxViewportWidth = (int) (Math.max(w, h) / mZoomManager.getDefaultMinZoomScale());
+        if (newMaxViewportWidth > sMaxViewportWidth) {
+            sMaxViewportWidth = newMaxViewportWidth;
+        }
+
+        mZoomManager.onSizeChanged(w, h, ow, oh);
+
+        if (mLoadedPicture != null && mDelaySetPicture == null) {
+            // Size changes normally result in a new picture
+            // Re-set the loaded picture to simulate that
+            // However, do not update the base layer as that hasn't changed
+            setNewPicture(mLoadedPicture, false);
+        }
+    }
+
+    @Override
+    public void onScrollChanged(int l, int t, int oldl, int oldt) {
+        if (!mInOverScrollMode) {
+            sendOurVisibleRect();
+            // update WebKit if visible title bar height changed. The logic is same
+            // as getVisibleTitleHeightImpl.
+            int titleHeight = getTitleHeight();
+            if (Math.max(titleHeight - t, 0) != Math.max(titleHeight - oldt, 0)) {
+                sendViewSizeZoom(false);
+            }
+        }
+    }
+
+    @Override
+    public boolean dispatchKeyEvent(KeyEvent event) {
+        switch (event.getAction()) {
+            case KeyEvent.ACTION_DOWN:
+                mKeysPressed.add(Integer.valueOf(event.getKeyCode()));
+                break;
+            case KeyEvent.ACTION_MULTIPLE:
+                // Always accept the action.
+                break;
+            case KeyEvent.ACTION_UP:
+                int location = mKeysPressed.indexOf(Integer.valueOf(event.getKeyCode()));
+                if (location == -1) {
+                    // We did not receive the key down for this key, so do not
+                    // handle the key up.
+                    return false;
+                } else {
+                    // We did receive the key down.  Handle the key up, and
+                    // remove it from our pressed keys.
+                    mKeysPressed.remove(location);
+                }
+                break;
+            default:
+                // Accept the action.  This should not happen, unless a new
+                // action is added to KeyEvent.
+                break;
+        }
+        return mWebViewPrivate.super_dispatchKeyEvent(event);
+    }
+
+    /*
+     * Here is the snap align logic:
+     * 1. If it starts nearly horizontally or vertically, snap align;
+     * 2. If there is a dramitic direction change, let it go;
+     *
+     * Adjustable parameters. Angle is the radians on a unit circle, limited
+     * to quadrant 1. Values range from 0f (horizontal) to PI/2 (vertical)
+     */
+    private static final float HSLOPE_TO_START_SNAP = .25f;
+    private static final float HSLOPE_TO_BREAK_SNAP = .4f;
+    private static final float VSLOPE_TO_START_SNAP = 1.25f;
+    private static final float VSLOPE_TO_BREAK_SNAP = .95f;
+    /*
+     *  These values are used to influence the average angle when entering
+     *  snap mode. If is is the first movement entering snap, we set the average
+     *  to the appropriate ideal. If the user is entering into snap after the
+     *  first movement, then we average the average angle with these values.
+     */
+    private static final float ANGLE_VERT = 2f;
+    private static final float ANGLE_HORIZ = 0f;
+    /*
+     *  The modified moving average weight.
+     *  Formula: MAV[t]=MAV[t-1] + (P[t]-MAV[t-1])/n
+     */
+    private static final float MMA_WEIGHT_N = 5;
+
+    private boolean hitFocusedPlugin(int contentX, int contentY) {
+        // TODO: Figure out what to do with this (b/6111517)
+        return false;
+    }
+
+    private boolean shouldForwardTouchEvent() {
+        if (mFullScreenHolder != null) return true;
+        if (mBlockWebkitViewMessages) return false;
+        return mForwardTouchEvents
+                && !mSelectingText
+                && mPreventDefault != PREVENT_DEFAULT_IGNORE
+                && mPreventDefault != PREVENT_DEFAULT_NO;
+    }
+
+    private boolean inFullScreenMode() {
+        return mFullScreenHolder != null;
+    }
+
+    private void dismissFullScreenMode() {
+        if (inFullScreenMode()) {
+            mFullScreenHolder.hide();
+            mFullScreenHolder = null;
+            invalidate();
+        }
+    }
+
+    void onPinchToZoomAnimationStart() {
+        // cancel the single touch handling
+        cancelTouch();
+        onZoomAnimationStart();
+    }
+
+    void onPinchToZoomAnimationEnd(ScaleGestureDetector detector) {
+        onZoomAnimationEnd();
+        // start a drag, TOUCH_PINCH_DRAG, can't use TOUCH_INIT_MODE as
+        // it may trigger the unwanted click, can't use TOUCH_DRAG_MODE
+        // as it may trigger the unwanted fling.
+        mTouchMode = TOUCH_PINCH_DRAG;
+        mConfirmMove = true;
+        startTouch(detector.getFocusX(), detector.getFocusY(), mLastTouchTime);
+    }
+
+    // See if there is a layer at x, y and switch to TOUCH_DRAG_LAYER_MODE if a
+    // layer is found.
+    private void startScrollingLayer(float x, float y) {
+        int contentX = viewToContentX((int) x + getScrollX());
+        int contentY = viewToContentY((int) y + getScrollY());
+        mCurrentScrollingLayerId = nativeScrollableLayer(contentX, contentY,
+                mScrollingLayerRect, mScrollingLayerBounds);
+        if (mCurrentScrollingLayerId != 0) {
+            mTouchMode = TOUCH_DRAG_LAYER_MODE;
+        }
+    }
+
+    // 1/(density * density) used to compute the distance between points.
+    // Computed in init().
+    private float DRAG_LAYER_INVERSE_DENSITY_SQUARED;
+
+    // The distance between two points reported in onTouchEvent scaled by the
+    // density of the screen.
+    private static final int DRAG_LAYER_FINGER_DISTANCE = 20000;
+
+    @Override
+    public boolean onHoverEvent(MotionEvent event) {
+        if (mNativeClass == 0) {
+            return false;
+        }
+        int x = viewToContentX((int) event.getX() + getScrollX());
+        int y = viewToContentY((int) event.getY() + getScrollY());
+        mWebViewCore.sendMessage(EventHub.SET_MOVE_MOUSE, x, y);
+        return true;
+    }
+
+    @Override
+    public boolean onTouchEvent(MotionEvent ev) {
+        if (mNativeClass == 0 || (!mWebView.isClickable() && !mWebView.isLongClickable())) {
+            return false;
+        }
+
+        if (!mWebView.isFocused()) {
+            mWebView.requestFocus();
+        }
+
+        if (DebugFlags.WEB_VIEW) {
+            Log.v(LOGTAG, ev + " at " + ev.getEventTime()
+                + " mTouchMode=" + mTouchMode
+                + " numPointers=" + ev.getPointerCount());
+        }
+
+        // If WebKit wasn't interested in this multitouch gesture, enqueue
+        // the event for handling directly rather than making the round trip
+        // to WebKit and back.
+        if (ev.getPointerCount() > 1 && mPreventDefault != PREVENT_DEFAULT_NO) {
+            passMultiTouchToWebKit(ev, mTouchEventQueue.nextTouchSequence());
+        } else {
+            mTouchEventQueue.enqueueTouchEvent(ev);
+        }
+
+        // Since all events are handled asynchronously, we always want the gesture stream.
+        return true;
+    }
+
+    private float calculateDragAngle(int dx, int dy) {
+        dx = Math.abs(dx);
+        dy = Math.abs(dy);
+        return (float) Math.atan2(dy, dx);
+    }
+
+    /*
+     * Common code for single touch and multi-touch.
+     * (x, y) denotes current focus point, which is the touch point for single touch
+     * and the middle point for multi-touch.
+     */
+    private boolean handleTouchEventCommon(MotionEvent ev, int action, int x, int y) {
+        long eventTime = ev.getEventTime();
+
+        // Due to the touch screen edge effect, a touch closer to the edge
+        // always snapped to the edge. As getViewWidth() can be different from
+        // getWidth() due to the scrollbar, adjusting the point to match
+        // getViewWidth(). Same applied to the height.
+        x = Math.min(x, getViewWidth() - 1);
+        y = Math.min(y, getViewHeightWithTitle() - 1);
+
+        int deltaX = mLastTouchX - x;
+        int deltaY = mLastTouchY - y;
+        int contentX = viewToContentX(x + getScrollX());
+        int contentY = viewToContentY(y + getScrollY());
+
+        switch (action) {
+            case MotionEvent.ACTION_DOWN: {
+                mPreventDefault = PREVENT_DEFAULT_NO;
+                mConfirmMove = false;
+                mInitialHitTestResult = null;
+                if (!mScroller.isFinished()) {
+                    // stop the current scroll animation, but if this is
+                    // the start of a fling, allow it to add to the current
+                    // fling's velocity
+                    mScroller.abortAnimation();
+                    mTouchMode = TOUCH_DRAG_START_MODE;
+                    mConfirmMove = true;
+                    nativeSetIsScrolling(false);
+                } else if (mPrivateHandler.hasMessages(RELEASE_SINGLE_TAP)) {
+                    mPrivateHandler.removeMessages(RELEASE_SINGLE_TAP);
+                    removeTouchHighlight();
+                    if (deltaX * deltaX + deltaY * deltaY < mDoubleTapSlopSquare) {
+                        mTouchMode = TOUCH_DOUBLE_TAP_MODE;
+                    } else {
+                        // commit the short press action for the previous tap
+                        doShortPress();
+                        mTouchMode = TOUCH_INIT_MODE;
+                        mDeferTouchProcess = !mBlockWebkitViewMessages
+                                && (!inFullScreenMode() && mForwardTouchEvents)
+                                ? hitFocusedPlugin(contentX, contentY)
+                                : false;
+                    }
+                } else { // the normal case
+                    mTouchMode = TOUCH_INIT_MODE;
+                    mDeferTouchProcess = !mBlockWebkitViewMessages
+                            && (!inFullScreenMode() && mForwardTouchEvents)
+                            ? hitFocusedPlugin(contentX, contentY)
+                            : false;
+                    TouchHighlightData data = new TouchHighlightData();
+                    data.mX = contentX;
+                    data.mY = contentY;
+                    data.mNativeLayerRect = new Rect();
+                    data.mNativeLayer = nativeScrollableLayer(
+                            contentX, contentY, data.mNativeLayerRect, null);
+                    data.mSlop = viewToContentDimension(mNavSlop);
+                    mTouchHighlightRegion.setEmpty();
+                    if (!mBlockWebkitViewMessages) {
+                        mTouchHighlightRequested = System.currentTimeMillis();
+                        mWebViewCore.sendMessageAtFrontOfQueue(
+                                EventHub.HIT_TEST, data);
+                    }
+                    if (DEBUG_TOUCH_HIGHLIGHT) {
+                        if (getSettings().getNavDump()) {
+                            mTouchHighlightX = x + getScrollX();
+                            mTouchHighlightY = y + getScrollY();
+                            mPrivateHandler.postDelayed(new Runnable() {
+                                @Override
+                                public void run() {
+                                    mTouchHighlightX = mTouchHighlightY = 0;
+                                    invalidate();
+                                }
+                            }, TOUCH_HIGHLIGHT_ELAPSE_TIME);
+                        }
+                    }
+                    if (mLogEvent && eventTime - mLastTouchUpTime < 1000) {
+                        EventLog.writeEvent(EventLogTags.BROWSER_DOUBLE_TAP_DURATION,
+                                (eventTime - mLastTouchUpTime), eventTime);
+                    }
+                    mSelectionStarted = false;
+                    if (mSelectingText) {
+                        int shiftedY = y - getTitleHeight() + getScrollY();
+                        int shiftedX = x + getScrollX();
+                        if (mSelectHandleCenter != null && mSelectHandleCenter.getBounds()
+                                .contains(shiftedX, shiftedY)) {
+                            mSelectionStarted = true;
+                            mSelectDraggingCursor = mSelectCursorBase;
+                            mPrivateHandler.removeMessages(CLEAR_CARET_HANDLE);
+                            hidePasteButton();
+                        } else if (mSelectHandleLeft != null
+                                && mSelectHandleLeft.getBounds()
+                                    .contains(shiftedX, shiftedY)) {
+                                mSelectionStarted = true;
+                                mSelectDraggingCursor = mSelectCursorBase;
+                        } else if (mSelectHandleRight != null
+                                && mSelectHandleRight.getBounds()
+                                .contains(shiftedX, shiftedY)) {
+                            mSelectionStarted = true;
+                            mSelectDraggingCursor = mSelectCursorExtent;
+                        } else if (mIsCaretSelection) {
+                            selectionDone();
+                        }
+                        if (mSelectDraggingCursor != null) {
+                            mSelectDraggingOffset.set(
+                                    mSelectDraggingCursor.left - contentX,
+                                    mSelectDraggingCursor.top - contentY);
+                        }
+                        if (DebugFlags.WEB_VIEW) {
+                            Log.v(LOGTAG, "select=" + contentX + "," + contentY);
+                        }
+                    }
+                }
+                // Trigger the link
+                if (!mSelectingText && (mTouchMode == TOUCH_INIT_MODE
+                        || mTouchMode == TOUCH_DOUBLE_TAP_MODE)) {
+                    mPrivateHandler.sendEmptyMessageDelayed(
+                            SWITCH_TO_SHORTPRESS, TAP_TIMEOUT);
+                    mPrivateHandler.sendEmptyMessageDelayed(
+                            SWITCH_TO_LONGPRESS, LONG_PRESS_TIMEOUT);
+                    if (inFullScreenMode() || mDeferTouchProcess) {
+                        mPreventDefault = PREVENT_DEFAULT_YES;
+                    } else if (!mBlockWebkitViewMessages && mForwardTouchEvents) {
+                        mPreventDefault = PREVENT_DEFAULT_MAYBE_YES;
+                    } else {
+                        mPreventDefault = PREVENT_DEFAULT_NO;
+                    }
+                    // pass the touch events from UI thread to WebCore thread
+                    if (shouldForwardTouchEvent()) {
+                        TouchEventData ted = new TouchEventData();
+                        ted.mAction = action;
+                        ted.mIds = new int[1];
+                        ted.mIds[0] = ev.getPointerId(0);
+                        ted.mPoints = new Point[1];
+                        ted.mPoints[0] = new Point(contentX, contentY);
+                        ted.mPointsInView = new Point[1];
+                        ted.mPointsInView[0] = new Point(x, y);
+                        ted.mMetaState = ev.getMetaState();
+                        ted.mReprocess = mDeferTouchProcess;
+                        ted.mNativeLayer = nativeScrollableLayer(
+                                contentX, contentY, ted.mNativeLayerRect, null);
+                        ted.mSequence = mTouchEventQueue.nextTouchSequence();
+                        mTouchEventQueue.preQueueTouchEventData(ted);
+                        mWebViewCore.sendMessage(EventHub.TOUCH_EVENT, ted);
+                        if (mDeferTouchProcess) {
+                            // still needs to set them for compute deltaX/Y
+                            mLastTouchX = x;
+                            mLastTouchY = y;
+                            break;
+                        }
+                        if (!inFullScreenMode()) {
+                            mPrivateHandler.removeMessages(PREVENT_DEFAULT_TIMEOUT);
+                            mPrivateHandler.sendMessageDelayed(mPrivateHandler
+                                    .obtainMessage(PREVENT_DEFAULT_TIMEOUT,
+                                            action, 0), TAP_TIMEOUT);
+                        }
+                    }
+                }
+                startTouch(x, y, eventTime);
+                break;
+            }
+            case MotionEvent.ACTION_MOVE: {
+                boolean firstMove = false;
+                if (!mConfirmMove && (deltaX * deltaX + deltaY * deltaY)
+                        >= mTouchSlopSquare) {
+                    mPrivateHandler.removeMessages(SWITCH_TO_SHORTPRESS);
+                    mPrivateHandler.removeMessages(SWITCH_TO_LONGPRESS);
+                    mConfirmMove = true;
+                    firstMove = true;
+                    if (mTouchMode == TOUCH_DOUBLE_TAP_MODE) {
+                        mTouchMode = TOUCH_INIT_MODE;
+                    }
+                    removeTouchHighlight();
+                }
+                if (mSelectingText && mSelectionStarted) {
+                    if (DebugFlags.WEB_VIEW) {
+                        Log.v(LOGTAG, "extend=" + contentX + "," + contentY);
+                    }
+                    ViewParent parent = mWebView.getParent();
+                    if (parent != null) {
+                        parent.requestDisallowInterceptTouchEvent(true);
+                    }
+                    if (deltaX != 0 || deltaY != 0) {
+                        mSelectDraggingCursor.offsetTo(
+                                contentX + mSelectDraggingOffset.x,
+                                contentY + mSelectDraggingOffset.y);
+                        updateWebkitSelection();
+                        mLastTouchX = x;
+                        mLastTouchY = y;
+                        invalidate();
+                    }
+                    break;
+                }
+
+                // pass the touch events from UI thread to WebCore thread
+                if (shouldForwardTouchEvent() && mConfirmMove && (firstMove
+                        || eventTime - mLastSentTouchTime > mCurrentTouchInterval)) {
+                    TouchEventData ted = new TouchEventData();
+                    ted.mAction = action;
+                    ted.mIds = new int[1];
+                    ted.mIds[0] = ev.getPointerId(0);
+                    ted.mPoints = new Point[1];
+                    ted.mPoints[0] = new Point(contentX, contentY);
+                    ted.mPointsInView = new Point[1];
+                    ted.mPointsInView[0] = new Point(x, y);
+                    ted.mMetaState = ev.getMetaState();
+                    ted.mReprocess = mDeferTouchProcess;
+                    ted.mNativeLayer = mCurrentScrollingLayerId;
+                    ted.mNativeLayerRect.set(mScrollingLayerRect);
+                    ted.mSequence = mTouchEventQueue.nextTouchSequence();
+                    mTouchEventQueue.preQueueTouchEventData(ted);
+                    mWebViewCore.sendMessage(EventHub.TOUCH_EVENT, ted);
+                    mLastSentTouchTime = eventTime;
+                    if (mDeferTouchProcess) {
+                        break;
+                    }
+                    if (firstMove && !inFullScreenMode()) {
+                        mPrivateHandler.sendMessageDelayed(mPrivateHandler
+                                .obtainMessage(PREVENT_DEFAULT_TIMEOUT,
+                                        action, 0), TAP_TIMEOUT);
+                    }
+                }
+                if (mTouchMode == TOUCH_DONE_MODE
+                        || mPreventDefault == PREVENT_DEFAULT_YES) {
+                    // no dragging during scroll zoom animation, or when prevent
+                    // default is yes
+                    break;
+                }
+                if (mVelocityTracker == null) {
+                    Log.e(LOGTAG, "Got null mVelocityTracker when "
+                            + "mPreventDefault = " + mPreventDefault
+                            + " mDeferTouchProcess = " + mDeferTouchProcess
+                            + " mTouchMode = " + mTouchMode);
+                } else {
+                    mVelocityTracker.addMovement(ev);
+                }
+
+                if (mTouchMode != TOUCH_DRAG_MODE &&
+                        mTouchMode != TOUCH_DRAG_LAYER_MODE) {
+
+                    if (!mConfirmMove) {
+                        break;
+                    }
+
+                    if (mPreventDefault == PREVENT_DEFAULT_MAYBE_YES
+                            || mPreventDefault == PREVENT_DEFAULT_NO_FROM_TOUCH_DOWN) {
+                        // track mLastTouchTime as we may need to do fling at
+                        // ACTION_UP
+                        mLastTouchTime = eventTime;
+                        break;
+                    }
+
+                    // Only lock dragging to one axis if we don't have a scale in progress.
+                    // Scaling implies free-roaming movement. Note this is only ever a question
+                    // if mZoomManager.supportsPanDuringZoom() is true.
+                    final ScaleGestureDetector detector =
+                      mZoomManager.getMultiTouchGestureDetector();
+                    mAverageAngle = calculateDragAngle(deltaX, deltaY);
+                    if (detector == null || !detector.isInProgress()) {
+                        // if it starts nearly horizontal or vertical, enforce it
+                        if (mAverageAngle < HSLOPE_TO_START_SNAP) {
+                            mSnapScrollMode = SNAP_X;
+                            mSnapPositive = deltaX > 0;
+                            mAverageAngle = ANGLE_HORIZ;
+                        } else if (mAverageAngle > VSLOPE_TO_START_SNAP) {
+                            mSnapScrollMode = SNAP_Y;
+                            mSnapPositive = deltaY > 0;
+                            mAverageAngle = ANGLE_VERT;
+                        }
+                    }
+
+                    mTouchMode = TOUCH_DRAG_MODE;
+                    mLastTouchX = x;
+                    mLastTouchY = y;
+                    deltaX = 0;
+                    deltaY = 0;
+
+                    startScrollingLayer(x, y);
+                    startDrag();
+                }
+
+                // do pan
+                boolean done = false;
+                boolean keepScrollBarsVisible = false;
+                if (deltaX == 0 && deltaY == 0) {
+                    keepScrollBarsVisible = done = true;
+                } else {
+                    mAverageAngle +=
+                        (calculateDragAngle(deltaX, deltaY) - mAverageAngle)
+                        / MMA_WEIGHT_N;
+                    if (mSnapScrollMode != SNAP_NONE) {
+                        if (mSnapScrollMode == SNAP_Y) {
+                            // radical change means getting out of snap mode
+                            if (mAverageAngle < VSLOPE_TO_BREAK_SNAP) {
+                                mSnapScrollMode = SNAP_NONE;
+                            }
+                        }
+                        if (mSnapScrollMode == SNAP_X) {
+                            // radical change means getting out of snap mode
+                            if (mAverageAngle > HSLOPE_TO_BREAK_SNAP) {
+                                mSnapScrollMode = SNAP_NONE;
+                            }
+                        }
+                    } else {
+                        if (mAverageAngle < HSLOPE_TO_START_SNAP) {
+                            mSnapScrollMode = SNAP_X;
+                            mSnapPositive = deltaX > 0;
+                            mAverageAngle = (mAverageAngle + ANGLE_HORIZ) / 2;
+                        } else if (mAverageAngle > VSLOPE_TO_START_SNAP) {
+                            mSnapScrollMode = SNAP_Y;
+                            mSnapPositive = deltaY > 0;
+                            mAverageAngle = (mAverageAngle + ANGLE_VERT) / 2;
+                        }
+                    }
+                    if (mSnapScrollMode != SNAP_NONE) {
+                        if ((mSnapScrollMode & SNAP_X) == SNAP_X) {
+                            deltaY = 0;
+                        } else {
+                            deltaX = 0;
+                        }
+                    }
+                    mLastTouchX = x;
+                    mLastTouchY = y;
+
+                    if (deltaX * deltaX + deltaY * deltaY > mTouchSlopSquare) {
+                        mHeldMotionless = MOTIONLESS_FALSE;
+                        nativeSetIsScrolling(true);
+                    } else {
+                        mHeldMotionless = MOTIONLESS_TRUE;
+                        nativeSetIsScrolling(false);
+                        keepScrollBarsVisible = true;
+                    }
+
+                    mLastTouchTime = eventTime;
+                }
+
+                doDrag(deltaX, deltaY);
+
+                // Turn off scrollbars when dragging a layer.
+                if (keepScrollBarsVisible &&
+                        mTouchMode != TOUCH_DRAG_LAYER_MODE) {
+                    if (mHeldMotionless != MOTIONLESS_TRUE) {
+                        mHeldMotionless = MOTIONLESS_TRUE;
+                        invalidate();
+                    }
+                    // keep the scrollbar on the screen even there is no scroll
+                    mWebViewPrivate.awakenScrollBars(ViewConfiguration.getScrollDefaultDelay(),
+                            false);
+                    // Post a message so that we'll keep them alive while we're not scrolling.
+                    mPrivateHandler.sendMessageDelayed(mPrivateHandler
+                            .obtainMessage(AWAKEN_SCROLL_BARS),
+                            ViewConfiguration.getScrollDefaultDelay());
+                    // return false to indicate that we can't pan out of the
+                    // view space
+                    return !done;
+                } else {
+                    mPrivateHandler.removeMessages(AWAKEN_SCROLL_BARS);
+                }
+                break;
+            }
+            case MotionEvent.ACTION_UP: {
+                // pass the touch events from UI thread to WebCore thread
+                if (shouldForwardTouchEvent()) {
+                    TouchEventData ted = new TouchEventData();
+                    ted.mIds = new int[1];
+                    ted.mIds[0] = ev.getPointerId(0);
+                    ted.mAction = action;
+                    ted.mPoints = new Point[1];
+                    ted.mPoints[0] = new Point(contentX, contentY);
+                    ted.mPointsInView = new Point[1];
+                    ted.mPointsInView[0] = new Point(x, y);
+                    ted.mMetaState = ev.getMetaState();
+                    ted.mReprocess = mDeferTouchProcess;
+                    ted.mNativeLayer = mCurrentScrollingLayerId;
+                    ted.mNativeLayerRect.set(mScrollingLayerRect);
+                    ted.mSequence = mTouchEventQueue.nextTouchSequence();
+                    mTouchEventQueue.preQueueTouchEventData(ted);
+                    mWebViewCore.sendMessage(EventHub.TOUCH_EVENT, ted);
+                }
+                mLastTouchUpTime = eventTime;
+                if (mSentAutoScrollMessage) {
+                    mAutoScrollX = mAutoScrollY = 0;
+                }
+                switch (mTouchMode) {
+                    case TOUCH_DOUBLE_TAP_MODE: // double tap
+                        mPrivateHandler.removeMessages(SWITCH_TO_SHORTPRESS);
+                        mPrivateHandler.removeMessages(SWITCH_TO_LONGPRESS);
+                        if (inFullScreenMode() || mDeferTouchProcess) {
+                            TouchEventData ted = new TouchEventData();
+                            ted.mIds = new int[1];
+                            ted.mIds[0] = ev.getPointerId(0);
+                            ted.mAction = WebViewCore.ACTION_DOUBLETAP;
+                            ted.mPoints = new Point[1];
+                            ted.mPoints[0] = new Point(contentX, contentY);
+                            ted.mPointsInView = new Point[1];
+                            ted.mPointsInView[0] = new Point(x, y);
+                            ted.mMetaState = ev.getMetaState();
+                            ted.mReprocess = mDeferTouchProcess;
+                            ted.mNativeLayer = nativeScrollableLayer(
+                                    contentX, contentY,
+                                    ted.mNativeLayerRect, null);
+                            ted.mSequence = mTouchEventQueue.nextTouchSequence();
+                            mTouchEventQueue.preQueueTouchEventData(ted);
+                            mWebViewCore.sendMessage(EventHub.TOUCH_EVENT, ted);
+                        } else if (mPreventDefault != PREVENT_DEFAULT_YES){
+                            mZoomManager.handleDoubleTap(mLastTouchX, mLastTouchY);
+                            mTouchMode = TOUCH_DONE_MODE;
+                        }
+                        break;
+                    case TOUCH_INIT_MODE: // tap
+                    case TOUCH_SHORTPRESS_START_MODE:
+                    case TOUCH_SHORTPRESS_MODE:
+                        mPrivateHandler.removeMessages(SWITCH_TO_SHORTPRESS);
+                        mPrivateHandler.removeMessages(SWITCH_TO_LONGPRESS);
+                        if (mConfirmMove) {
+                            Log.w(LOGTAG, "Miss a drag as we are waiting for" +
+                                    " WebCore's response for touch down.");
+                            if (mPreventDefault != PREVENT_DEFAULT_YES
+                                    && (computeMaxScrollX() > 0
+                                            || computeMaxScrollY() > 0)) {
+                                // If the user has performed a very quick touch
+                                // sequence it is possible that we may get here
+                                // before WebCore has had a chance to process the events.
+                                // In this case, any call to preventDefault in the
+                                // JS touch handler will not have been executed yet.
+                                // Hence we will see both the UI (now) and WebCore
+                                // (when context switches) handling the event,
+                                // regardless of whether the web developer actually
+                                // doeses preventDefault in their touch handler. This
+                                // is the nature of our asynchronous touch model.
+
+                                // we will not rewrite drag code here, but we
+                                // will try fling if it applies.
+                                WebViewCore.reducePriority();
+                                // to get better performance, pause updating the
+                                // picture
+                                WebViewCore.pauseUpdatePicture(mWebViewCore);
+                                // fall through to TOUCH_DRAG_MODE
+                            } else {
+                                // WebKit may consume the touch event and modify
+                                // DOM. drawContentPicture() will be called with
+                                // animateSroll as true for better performance.
+                                // Force redraw in high-quality.
+                                invalidate();
+                                break;
+                            }
+                        } else {
+                            if (mSelectingText) {
+                                // tapping on selection or controls does nothing
+                                if (!mSelectionStarted) {
+                                    selectionDone();
+                                }
+                                break;
+                            }
+                            // only trigger double tap if the WebView is
+                            // scalable
+                            if (mTouchMode == TOUCH_INIT_MODE
+                                    && (canZoomIn() || canZoomOut())) {
+                                mPrivateHandler.sendEmptyMessageDelayed(
+                                        RELEASE_SINGLE_TAP, ViewConfiguration
+                                                .getDoubleTapTimeout());
+                            } else {
+                                doShortPress();
+                            }
+                            break;
+                        }
+                    case TOUCH_DRAG_MODE:
+                    case TOUCH_DRAG_LAYER_MODE:
+                        mPrivateHandler.removeMessages(DRAG_HELD_MOTIONLESS);
+                        mPrivateHandler.removeMessages(AWAKEN_SCROLL_BARS);
+                        // if the user waits a while w/o moving before the
+                        // up, we don't want to do a fling
+                        if (eventTime - mLastTouchTime <= MIN_FLING_TIME) {
+                            if (mVelocityTracker == null) {
+                                Log.e(LOGTAG, "Got null mVelocityTracker when "
+                                        + "mPreventDefault = "
+                                        + mPreventDefault
+                                        + " mDeferTouchProcess = "
+                                        + mDeferTouchProcess);
+                            } else {
+                                mVelocityTracker.addMovement(ev);
+                            }
+                            // set to MOTIONLESS_IGNORE so that it won't keep
+                            // removing and sending message in
+                            // drawCoreAndCursorRing()
+                            mHeldMotionless = MOTIONLESS_IGNORE;
+                            doFling();
+                            break;
+                        } else {
+                            if (mScroller.springBack(getScrollX(), getScrollY(), 0,
+                                    computeMaxScrollX(), 0,
+                                    computeMaxScrollY())) {
+                                invalidate();
+                            }
+                        }
+                        // redraw in high-quality, as we're done dragging
+                        mHeldMotionless = MOTIONLESS_TRUE;
+                        invalidate();
+                        // fall through
+                    case TOUCH_DRAG_START_MODE:
+                        // TOUCH_DRAG_START_MODE should not happen for the real
+                        // device as we almost certain will get a MOVE. But this
+                        // is possible on emulator.
+                        mLastVelocity = 0;
+                        WebViewCore.resumePriority();
+                        if (!mSelectingText) {
+                            WebViewCore.resumeUpdatePicture(mWebViewCore);
+                        }
+                        break;
+                }
+                stopTouch();
+                break;
+            }
+            case MotionEvent.ACTION_CANCEL: {
+                if (mTouchMode == TOUCH_DRAG_MODE) {
+                    mScroller.springBack(getScrollX(), getScrollY(), 0,
+                            computeMaxScrollX(), 0, computeMaxScrollY());
+                    invalidate();
+                }
+                cancelWebCoreTouchEvent(contentX, contentY, false);
+                cancelTouch();
+                break;
+            }
+        }
+        return true;
+    }
+
+    private void passMultiTouchToWebKit(MotionEvent ev, long sequence) {
+        TouchEventData ted = new TouchEventData();
+        ted.mAction = ev.getActionMasked();
+        final int count = ev.getPointerCount();
+        ted.mIds = new int[count];
+        ted.mPoints = new Point[count];
+        ted.mPointsInView = new Point[count];
+        for (int c = 0; c < count; c++) {
+            ted.mIds[c] = ev.getPointerId(c);
+            int x = viewToContentX((int) ev.getX(c) + getScrollX());
+            int y = viewToContentY((int) ev.getY(c) + getScrollY());
+            ted.mPoints[c] = new Point(x, y);
+            ted.mPointsInView[c] = new Point((int) ev.getX(c), (int) ev.getY(c));
+        }
+        if (ted.mAction == MotionEvent.ACTION_POINTER_DOWN
+            || ted.mAction == MotionEvent.ACTION_POINTER_UP) {
+            ted.mActionIndex = ev.getActionIndex();
+        }
+        ted.mMetaState = ev.getMetaState();
+        ted.mReprocess = true;
+        ted.mMotionEvent = MotionEvent.obtain(ev);
+        ted.mSequence = sequence;
+        mTouchEventQueue.preQueueTouchEventData(ted);
+        mWebViewCore.sendMessage(EventHub.TOUCH_EVENT, ted);
+        mWebView.cancelLongPress();
+        mPrivateHandler.removeMessages(SWITCH_TO_LONGPRESS);
+    }
+
+    void handleMultiTouchInWebView(MotionEvent ev) {
+        if (DebugFlags.WEB_VIEW) {
+            Log.v(LOGTAG, "multi-touch: " + ev + " at " + ev.getEventTime()
+                + " mTouchMode=" + mTouchMode
+                + " numPointers=" + ev.getPointerCount()
+                + " scrolloffset=(" + getScrollX() + "," + getScrollY() + ")");
+        }
+
+        final ScaleGestureDetector detector =
+            mZoomManager.getMultiTouchGestureDetector();
+
+        // A few apps use WebView but don't instantiate gesture detector.
+        // We don't need to support multi touch for them.
+        if (detector == null) return;
+
+        float x = ev.getX();
+        float y = ev.getY();
+
+        if (mPreventDefault != PREVENT_DEFAULT_YES) {
+            detector.onTouchEvent(ev);
+
+            if (detector.isInProgress()) {
+                if (DebugFlags.WEB_VIEW) {
+                    Log.v(LOGTAG, "detector is in progress");
+                }
+                mLastTouchTime = ev.getEventTime();
+                x = detector.getFocusX();
+                y = detector.getFocusY();
+
+                mWebView.cancelLongPress();
+                mPrivateHandler.removeMessages(SWITCH_TO_LONGPRESS);
+                if (!mZoomManager.supportsPanDuringZoom()) {
+                    return;
+                }
+                mTouchMode = TOUCH_DRAG_MODE;
+                if (mVelocityTracker == null) {
+                    mVelocityTracker = VelocityTracker.obtain();
+                }
+            }
+        }
+
+        int action = ev.getActionMasked();
+        if (action == MotionEvent.ACTION_POINTER_DOWN) {
+            cancelTouch();
+            action = MotionEvent.ACTION_DOWN;
+        } else if (action == MotionEvent.ACTION_POINTER_UP && ev.getPointerCount() >= 2) {
+            // set mLastTouchX/Y to the remaining points for multi-touch.
+            mLastTouchX = Math.round(x);
+            mLastTouchY = Math.round(y);
+        } else if (action == MotionEvent.ACTION_MOVE) {
+            // negative x or y indicate it is on the edge, skip it.
+            if (x < 0 || y < 0) {
+                return;
+            }
+        }
+
+        handleTouchEventCommon(ev, action, Math.round(x), Math.round(y));
+    }
+
+    private void cancelWebCoreTouchEvent(int x, int y, boolean removeEvents) {
+        if (shouldForwardTouchEvent()) {
+            if (removeEvents) {
+                mWebViewCore.removeMessages(EventHub.TOUCH_EVENT);
+            }
+            TouchEventData ted = new TouchEventData();
+            ted.mIds = new int[1];
+            ted.mIds[0] = 0;
+            ted.mPoints = new Point[1];
+            ted.mPoints[0] = new Point(x, y);
+            ted.mPointsInView = new Point[1];
+            int viewX = contentToViewX(x) - getScrollX();
+            int viewY = contentToViewY(y) - getScrollY();
+            ted.mPointsInView[0] = new Point(viewX, viewY);
+            ted.mAction = MotionEvent.ACTION_CANCEL;
+            ted.mNativeLayer = nativeScrollableLayer(
+                    x, y, ted.mNativeLayerRect, null);
+            ted.mSequence = mTouchEventQueue.nextTouchSequence();
+            mWebViewCore.sendMessage(EventHub.TOUCH_EVENT, ted);
+            mPreventDefault = PREVENT_DEFAULT_IGNORE;
+
+            if (removeEvents) {
+                // Mark this after sending the message above; we should
+                // be willing to ignore the cancel event that we just sent.
+                mTouchEventQueue.ignoreCurrentlyMissingEvents();
+            }
+        }
+    }
+
+    private void startTouch(float x, float y, long eventTime) {
+        // Remember where the motion event started
+        mStartTouchX = mLastTouchX = Math.round(x);
+        mStartTouchY = mLastTouchY = Math.round(y);
+        mLastTouchTime = eventTime;
+        mVelocityTracker = VelocityTracker.obtain();
+        mSnapScrollMode = SNAP_NONE;
+    }
+
+    private void startDrag() {
+        WebViewCore.reducePriority();
+        // to get better performance, pause updating the picture
+        WebViewCore.pauseUpdatePicture(mWebViewCore);
+        nativeSetIsScrolling(true);
+
+        if (mHorizontalScrollBarMode != SCROLLBAR_ALWAYSOFF
+                || mVerticalScrollBarMode != SCROLLBAR_ALWAYSOFF) {
+            mZoomManager.invokeZoomPicker();
+        }
+    }
+
+    private void doDrag(int deltaX, int deltaY) {
+        if ((deltaX | deltaY) != 0) {
+            int oldX = getScrollX();
+            int oldY = getScrollY();
+            int rangeX = computeMaxScrollX();
+            int rangeY = computeMaxScrollY();
+            // Check for the original scrolling layer in case we change
+            // directions.  mTouchMode might be TOUCH_DRAG_MODE if we have
+            // reached the edge of a layer but mScrollingLayer will be non-zero
+            // if we initiated the drag on a layer.
+            if (mCurrentScrollingLayerId != 0) {
+                final int contentX = viewToContentDimension(deltaX);
+                final int contentY = viewToContentDimension(deltaY);
+
+                // Check the scrolling bounds to see if we will actually do any
+                // scrolling.  The rectangle is in document coordinates.
+                final int maxX = mScrollingLayerRect.right;
+                final int maxY = mScrollingLayerRect.bottom;
+                final int resultX = Math.max(0,
+                        Math.min(mScrollingLayerRect.left + contentX, maxX));
+                final int resultY = Math.max(0,
+                        Math.min(mScrollingLayerRect.top + contentY, maxY));
+
+                if (resultX != mScrollingLayerRect.left ||
+                        resultY != mScrollingLayerRect.top) {
+                    // In case we switched to dragging the page.
+                    mTouchMode = TOUCH_DRAG_LAYER_MODE;
+                    deltaX = contentX;
+                    deltaY = contentY;
+                    oldX = mScrollingLayerRect.left;
+                    oldY = mScrollingLayerRect.top;
+                    rangeX = maxX;
+                    rangeY = maxY;
+                } else {
+                    // Scroll the main page if we are not going to scroll the
+                    // layer.  This does not reset mScrollingLayer in case the
+                    // user changes directions and the layer can scroll the
+                    // other way.
+                    mTouchMode = TOUCH_DRAG_MODE;
+                }
+            }
+
+            if (mOverScrollGlow != null) {
+                mOverScrollGlow.setOverScrollDeltas(deltaX, deltaY);
+            }
+
+            mWebViewPrivate.overScrollBy(deltaX, deltaY, oldX, oldY,
+                    rangeX, rangeY,
+                    mOverscrollDistance, mOverscrollDistance, true);
+            if (mOverScrollGlow != null && mOverScrollGlow.isAnimating()) {
+                invalidate();
+            }
+        }
+        mZoomManager.keepZoomPickerVisible();
+    }
+
+    private void stopTouch() {
+        if (mScroller.isFinished() && !mSelectingText
+                && (mTouchMode == TOUCH_DRAG_MODE || mTouchMode == TOUCH_DRAG_LAYER_MODE)) {
+            WebViewCore.resumePriority();
+            WebViewCore.resumeUpdatePicture(mWebViewCore);
+            nativeSetIsScrolling(false);
+        }
+
+        // we also use mVelocityTracker == null to tell us that we are
+        // not "moving around", so we can take the slower/prettier
+        // mode in the drawing code
+        if (mVelocityTracker != null) {
+            mVelocityTracker.recycle();
+            mVelocityTracker = null;
+        }
+
+        // Release any pulled glows
+        if (mOverScrollGlow != null) {
+            mOverScrollGlow.releaseAll();
+        }
+
+        if (mSelectingText) {
+            mSelectionStarted = false;
+            syncSelectionCursors();
+            if (mIsCaretSelection) {
+                resetCaretTimer();
+                showPasteWindow();
+            }
+            invalidate();
+        }
+    }
+
+    private void cancelTouch() {
+        // we also use mVelocityTracker == null to tell us that we are
+        // not "moving around", so we can take the slower/prettier
+        // mode in the drawing code
+        if (mVelocityTracker != null) {
+            mVelocityTracker.recycle();
+            mVelocityTracker = null;
+        }
+
+        if ((mTouchMode == TOUCH_DRAG_MODE
+                || mTouchMode == TOUCH_DRAG_LAYER_MODE) && !mSelectingText) {
+            WebViewCore.resumePriority();
+            WebViewCore.resumeUpdatePicture(mWebViewCore);
+            nativeSetIsScrolling(false);
+        }
+        mPrivateHandler.removeMessages(SWITCH_TO_SHORTPRESS);
+        mPrivateHandler.removeMessages(SWITCH_TO_LONGPRESS);
+        mPrivateHandler.removeMessages(DRAG_HELD_MOTIONLESS);
+        mPrivateHandler.removeMessages(AWAKEN_SCROLL_BARS);
+        removeTouchHighlight();
+        mHeldMotionless = MOTIONLESS_TRUE;
+        mTouchMode = TOUCH_DONE_MODE;
+    }
+
+    @Override
+    public boolean onGenericMotionEvent(MotionEvent event) {
+        if ((event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0) {
+            switch (event.getAction()) {
+                case MotionEvent.ACTION_SCROLL: {
+                    final float vscroll;
+                    final float hscroll;
+                    if ((event.getMetaState() & KeyEvent.META_SHIFT_ON) != 0) {
+                        vscroll = 0;
+                        hscroll = event.getAxisValue(MotionEvent.AXIS_VSCROLL);
+                    } else {
+                        vscroll = -event.getAxisValue(MotionEvent.AXIS_VSCROLL);
+                        hscroll = event.getAxisValue(MotionEvent.AXIS_HSCROLL);
+                    }
+                    if (hscroll != 0 || vscroll != 0) {
+                        final int vdelta = (int) (vscroll *
+                                mWebViewPrivate.getVerticalScrollFactor());
+                        final int hdelta = (int) (hscroll *
+                                mWebViewPrivate.getHorizontalScrollFactor());
+                        if (pinScrollBy(hdelta, vdelta, false, 0)) {
+                            return true;
+                        }
+                    }
+                }
+            }
+        }
+        return mWebViewPrivate.super_onGenericMotionEvent(event);
+    }
+
+    private long mTrackballFirstTime = 0;
+    private long mTrackballLastTime = 0;
+    private float mTrackballRemainsX = 0.0f;
+    private float mTrackballRemainsY = 0.0f;
+    private int mTrackballXMove = 0;
+    private int mTrackballYMove = 0;
+    private boolean mSelectingText = false;
+    private boolean mSelectionStarted = false;
+    private static final int TRACKBALL_KEY_TIMEOUT = 1000;
+    private static final int TRACKBALL_TIMEOUT = 200;
+    private static final int TRACKBALL_WAIT = 100;
+    private static final int TRACKBALL_SCALE = 400;
+    private static final int TRACKBALL_SCROLL_COUNT = 5;
+    private static final int TRACKBALL_MOVE_COUNT = 10;
+    private static final int TRACKBALL_MULTIPLIER = 3;
+    private static final int SELECT_CURSOR_OFFSET = 16;
+    private static final int SELECT_SCROLL = 5;
+    private int mSelectX = 0;
+    private int mSelectY = 0;
+    private boolean mTrackballDown = false;
+    private long mTrackballUpTime = 0;
+    private long mLastCursorTime = 0;
+    private Rect mLastCursorBounds;
+
+    // Set by default; BrowserActivity clears to interpret trackball data
+    // directly for movement. Currently, the framework only passes
+    // arrow key events, not trackball events, from one child to the next
+    private boolean mMapTrackballToArrowKeys = true;
+
+    private DrawData mDelaySetPicture;
+    private DrawData mLoadedPicture;
+
+    public void setMapTrackballToArrowKeys(boolean setMap) {
+        checkThread();
+        mMapTrackballToArrowKeys = setMap;
+    }
+
+    void resetTrackballTime() {
+        mTrackballLastTime = 0;
+    }
+
+    @Override
+    public boolean onTrackballEvent(MotionEvent ev) {
+        long time = ev.getEventTime();
+        if ((ev.getMetaState() & KeyEvent.META_ALT_ON) != 0) {
+            if (ev.getY() > 0) pageDown(true);
+            if (ev.getY() < 0) pageUp(true);
+            return true;
+        }
+        if (ev.getAction() == MotionEvent.ACTION_DOWN) {
+            if (mSelectingText) {
+                return true; // discard press if copy in progress
+            }
+            mTrackballDown = true;
+            if (mNativeClass == 0) {
+                return false;
+            }
+            if (DebugFlags.WEB_VIEW) {
+                Log.v(LOGTAG, "onTrackballEvent down ev=" + ev
+                        + " time=" + time
+                        + " mLastCursorTime=" + mLastCursorTime);
+            }
+            if (mWebView.isInTouchMode()) mWebView.requestFocusFromTouch();
+            return false; // let common code in onKeyDown at it
+        }
+        if (ev.getAction() == MotionEvent.ACTION_UP) {
+            // LONG_PRESS_CENTER is set in common onKeyDown
+            mPrivateHandler.removeMessages(LONG_PRESS_CENTER);
+            mTrackballDown = false;
+            mTrackballUpTime = time;
+            if (mSelectingText) {
+                copySelection();
+                selectionDone();
+                return true; // discard press if copy in progress
+            }
+            if (DebugFlags.WEB_VIEW) {
+                Log.v(LOGTAG, "onTrackballEvent up ev=" + ev
+                        + " time=" + time
+                );
+            }
+            return false; // let common code in onKeyUp at it
+        }
+        if ((mMapTrackballToArrowKeys && (ev.getMetaState() & KeyEvent.META_SHIFT_ON) == 0) ||
+                AccessibilityManager.getInstance(mContext).isEnabled()) {
+            if (DebugFlags.WEB_VIEW) Log.v(LOGTAG, "onTrackballEvent gmail quit");
+            return false;
+        }
+        if (mTrackballDown) {
+            if (DebugFlags.WEB_VIEW) Log.v(LOGTAG, "onTrackballEvent down quit");
+            return true; // discard move if trackball is down
+        }
+        if (time - mTrackballUpTime < TRACKBALL_TIMEOUT) {
+            if (DebugFlags.WEB_VIEW) Log.v(LOGTAG, "onTrackballEvent up timeout quit");
+            return true;
+        }
+        // TODO: alternatively we can do panning as touch does
+        switchOutDrawHistory();
+        if (time - mTrackballLastTime > TRACKBALL_TIMEOUT) {
+            if (DebugFlags.WEB_VIEW) {
+                Log.v(LOGTAG, "onTrackballEvent time="
+                        + time + " last=" + mTrackballLastTime);
+            }
+            mTrackballFirstTime = time;
+            mTrackballXMove = mTrackballYMove = 0;
+        }
+        mTrackballLastTime = time;
+        if (DebugFlags.WEB_VIEW) {
+            Log.v(LOGTAG, "onTrackballEvent ev=" + ev + " time=" + time);
+        }
+        mTrackballRemainsX += ev.getX();
+        mTrackballRemainsY += ev.getY();
+        doTrackball(time, ev.getMetaState());
+        return true;
+    }
+
+    private int scaleTrackballX(float xRate, int width) {
+        int xMove = (int) (xRate / TRACKBALL_SCALE * width);
+        int nextXMove = xMove;
+        if (xMove > 0) {
+            if (xMove > mTrackballXMove) {
+                xMove -= mTrackballXMove;
+            }
+        } else if (xMove < mTrackballXMove) {
+            xMove -= mTrackballXMove;
+        }
+        mTrackballXMove = nextXMove;
+        return xMove;
+    }
+
+    private int scaleTrackballY(float yRate, int height) {
+        int yMove = (int) (yRate / TRACKBALL_SCALE * height);
+        int nextYMove = yMove;
+        if (yMove > 0) {
+            if (yMove > mTrackballYMove) {
+                yMove -= mTrackballYMove;
+            }
+        } else if (yMove < mTrackballYMove) {
+            yMove -= mTrackballYMove;
+        }
+        mTrackballYMove = nextYMove;
+        return yMove;
+    }
+
+    private int keyCodeToSoundsEffect(int keyCode) {
+        switch(keyCode) {
+            case KeyEvent.KEYCODE_DPAD_UP:
+                return SoundEffectConstants.NAVIGATION_UP;
+            case KeyEvent.KEYCODE_DPAD_RIGHT:
+                return SoundEffectConstants.NAVIGATION_RIGHT;
+            case KeyEvent.KEYCODE_DPAD_DOWN:
+                return SoundEffectConstants.NAVIGATION_DOWN;
+            case KeyEvent.KEYCODE_DPAD_LEFT:
+                return SoundEffectConstants.NAVIGATION_LEFT;
+        }
+        return 0;
+    }
+
+    private void doTrackball(long time, int metaState) {
+        int elapsed = (int) (mTrackballLastTime - mTrackballFirstTime);
+        if (elapsed == 0) {
+            elapsed = TRACKBALL_TIMEOUT;
+        }
+        float xRate = mTrackballRemainsX * 1000 / elapsed;
+        float yRate = mTrackballRemainsY * 1000 / elapsed;
+        int viewWidth = getViewWidth();
+        int viewHeight = getViewHeight();
+        float ax = Math.abs(xRate);
+        float ay = Math.abs(yRate);
+        float maxA = Math.max(ax, ay);
+        if (DebugFlags.WEB_VIEW) {
+            Log.v(LOGTAG, "doTrackball elapsed=" + elapsed
+                    + " xRate=" + xRate
+                    + " yRate=" + yRate
+                    + " mTrackballRemainsX=" + mTrackballRemainsX
+                    + " mTrackballRemainsY=" + mTrackballRemainsY);
+        }
+        int width = mContentWidth - viewWidth;
+        int height = mContentHeight - viewHeight;
+        if (width < 0) width = 0;
+        if (height < 0) height = 0;
+        ax = Math.abs(mTrackballRemainsX * TRACKBALL_MULTIPLIER);
+        ay = Math.abs(mTrackballRemainsY * TRACKBALL_MULTIPLIER);
+        maxA = Math.max(ax, ay);
+        int count = Math.max(0, (int) maxA);
+        int oldScrollX = getScrollX();
+        int oldScrollY = getScrollY();
+        if (count > 0) {
+            int selectKeyCode = ax < ay ? mTrackballRemainsY < 0 ?
+                    KeyEvent.KEYCODE_DPAD_UP : KeyEvent.KEYCODE_DPAD_DOWN :
+                    mTrackballRemainsX < 0 ? KeyEvent.KEYCODE_DPAD_LEFT :
+                    KeyEvent.KEYCODE_DPAD_RIGHT;
+            count = Math.min(count, TRACKBALL_MOVE_COUNT);
+            if (DebugFlags.WEB_VIEW) {
+                Log.v(LOGTAG, "doTrackball keyCode=" + selectKeyCode
+                        + " count=" + count
+                        + " mTrackballRemainsX=" + mTrackballRemainsX
+                        + " mTrackballRemainsY=" + mTrackballRemainsY);
+            }
+            if (mNativeClass != 0) {
+                for (int i = 0; i < count; i++) {
+                    letPageHandleNavKey(selectKeyCode, time, true, metaState);
+                }
+                letPageHandleNavKey(selectKeyCode, time, false, metaState);
+            }
+            mTrackballRemainsX = mTrackballRemainsY = 0;
+        }
+        if (count >= TRACKBALL_SCROLL_COUNT) {
+            int xMove = scaleTrackballX(xRate, width);
+            int yMove = scaleTrackballY(yRate, height);
+            if (DebugFlags.WEB_VIEW) {
+                Log.v(LOGTAG, "doTrackball pinScrollBy"
+                        + " count=" + count
+                        + " xMove=" + xMove + " yMove=" + yMove
+                        + " mScrollX-oldScrollX=" + (getScrollX()-oldScrollX)
+                        + " mScrollY-oldScrollY=" + (getScrollY()-oldScrollY)
+                        );
+            }
+            if (Math.abs(getScrollX() - oldScrollX) > Math.abs(xMove)) {
+                xMove = 0;
+            }
+            if (Math.abs(getScrollY() - oldScrollY) > Math.abs(yMove)) {
+                yMove = 0;
+            }
+            if (xMove != 0 || yMove != 0) {
+                pinScrollBy(xMove, yMove, true, 0);
+            }
+        }
+    }
+
+    /**
+     * Compute the maximum horizontal scroll position. Used by {@link OverScrollGlow}.
+     * @return Maximum horizontal scroll position within real content
+     */
+    int computeMaxScrollX() {
+        return Math.max(computeRealHorizontalScrollRange() - getViewWidth(), 0);
+    }
+
+    /**
+     * Compute the maximum vertical scroll position. Used by {@link OverScrollGlow}.
+     * @return Maximum vertical scroll position within real content
+     */
+    int computeMaxScrollY() {
+        return Math.max(computeRealVerticalScrollRange() + getTitleHeight()
+                - getViewHeightWithTitle(), 0);
+    }
+
+    boolean updateScrollCoordinates(int x, int y) {
+        int oldX = getScrollX();
+        int oldY = getScrollY();
+        setScrollXRaw(x);
+        setScrollYRaw(y);
+        if (oldX != getScrollX() || oldY != getScrollY()) {
+            mWebViewPrivate.onScrollChanged(getScrollX(), getScrollY(), oldX, oldY);
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    public void flingScroll(int vx, int vy) {
+        checkThread();
+        mScroller.fling(getScrollX(), getScrollY(), vx, vy, 0, computeMaxScrollX(), 0,
+                computeMaxScrollY(), mOverflingDistance, mOverflingDistance);
+        invalidate();
+    }
+
+    private void doFling() {
+        if (mVelocityTracker == null) {
+            return;
+        }
+        int maxX = computeMaxScrollX();
+        int maxY = computeMaxScrollY();
+
+        mVelocityTracker.computeCurrentVelocity(1000, mMaximumFling);
+        int vx = (int) mVelocityTracker.getXVelocity();
+        int vy = (int) mVelocityTracker.getYVelocity();
+
+        int scrollX = getScrollX();
+        int scrollY = getScrollY();
+        int overscrollDistance = mOverscrollDistance;
+        int overflingDistance = mOverflingDistance;
+
+        // Use the layer's scroll data if applicable.
+        if (mTouchMode == TOUCH_DRAG_LAYER_MODE) {
+            scrollX = mScrollingLayerRect.left;
+            scrollY = mScrollingLayerRect.top;
+            maxX = mScrollingLayerRect.right;
+            maxY = mScrollingLayerRect.bottom;
+            // No overscrolling for layers.
+            overscrollDistance = overflingDistance = 0;
+        }
+
+        if (mSnapScrollMode != SNAP_NONE) {
+            if ((mSnapScrollMode & SNAP_X) == SNAP_X) {
+                vy = 0;
+            } else {
+                vx = 0;
+            }
+        }
+        if ((maxX == 0 && vy == 0) || (maxY == 0 && vx == 0)) {
+            WebViewCore.resumePriority();
+            if (!mSelectingText) {
+                WebViewCore.resumeUpdatePicture(mWebViewCore);
+            }
+            if (mScroller.springBack(scrollX, scrollY, 0, maxX, 0, maxY)) {
+                invalidate();
+            }
+            return;
+        }
+        float currentVelocity = mScroller.getCurrVelocity();
+        float velocity = (float) Math.hypot(vx, vy);
+        if (mLastVelocity > 0 && currentVelocity > 0 && velocity
+                > mLastVelocity * MINIMUM_VELOCITY_RATIO_FOR_ACCELERATION) {
+            float deltaR = (float) (Math.abs(Math.atan2(mLastVelY, mLastVelX)
+                    - Math.atan2(vy, vx)));
+            final float circle = (float) (Math.PI) * 2.0f;
+            if (deltaR > circle * 0.9f || deltaR < circle * 0.1f) {
+                vx += currentVelocity * mLastVelX / mLastVelocity;
+                vy += currentVelocity * mLastVelY / mLastVelocity;
+                velocity = (float) Math.hypot(vx, vy);
+                if (DebugFlags.WEB_VIEW) {
+                    Log.v(LOGTAG, "doFling vx= " + vx + " vy=" + vy);
+                }
+            } else if (DebugFlags.WEB_VIEW) {
+                Log.v(LOGTAG, "doFling missed " + deltaR / circle);
+            }
+        } else if (DebugFlags.WEB_VIEW) {
+            Log.v(LOGTAG, "doFling start last=" + mLastVelocity
+                    + " current=" + currentVelocity
+                    + " vx=" + vx + " vy=" + vy
+                    + " maxX=" + maxX + " maxY=" + maxY
+                    + " scrollX=" + scrollX + " scrollY=" + scrollY
+                    + " layer=" + mCurrentScrollingLayerId);
+        }
+
+        // Allow sloppy flings without overscrolling at the edges.
+        if ((scrollX == 0 || scrollX == maxX) && Math.abs(vx) < Math.abs(vy)) {
+            vx = 0;
+        }
+        if ((scrollY == 0 || scrollY == maxY) && Math.abs(vy) < Math.abs(vx)) {
+            vy = 0;
+        }
+
+        if (overscrollDistance < overflingDistance) {
+            if ((vx > 0 && scrollX == -overscrollDistance) ||
+                    (vx < 0 && scrollX == maxX + overscrollDistance)) {
+                vx = 0;
+            }
+            if ((vy > 0 && scrollY == -overscrollDistance) ||
+                    (vy < 0 && scrollY == maxY + overscrollDistance)) {
+                vy = 0;
+            }
+        }
+
+        mLastVelX = vx;
+        mLastVelY = vy;
+        mLastVelocity = velocity;
+
+        // no horizontal overscroll if the content just fits
+        mScroller.fling(scrollX, scrollY, -vx, -vy, 0, maxX, 0, maxY,
+                maxX == 0 ? 0 : overflingDistance, overflingDistance);
+        // Duration is calculated based on velocity. With range boundaries and overscroll
+        // we may not know how long the final animation will take. (Hence the deprecation
+        // warning on the call below.) It's not a big deal for scroll bars but if webcore
+        // resumes during this effect we will take a performance hit. See computeScroll;
+        // we resume webcore there when the animation is finished.
+        final int time = mScroller.getDuration();
+
+        // Suppress scrollbars for layer scrolling.
+        if (mTouchMode != TOUCH_DRAG_LAYER_MODE) {
+            mWebViewPrivate.awakenScrollBars(time);
+        }
+
+        invalidate();
+    }
+
+    /**
+     * See {@link WebView#getZoomControls()}
+     */
+    @Override
+    @Deprecated
+    public View getZoomControls() {
+        checkThread();
+        if (!getSettings().supportZoom()) {
+            Log.w(LOGTAG, "This WebView doesn't support zoom.");
+            return null;
+        }
+        return mZoomManager.getExternalZoomPicker();
+    }
+
+    void dismissZoomControl() {
+        mZoomManager.dismissZoomPicker();
+    }
+
+    float getDefaultZoomScale() {
+        return mZoomManager.getDefaultScale();
+    }
+
+    /**
+     * Return the overview scale of the WebView
+     * @return The overview scale.
+     */
+    float getZoomOverviewScale() {
+        return mZoomManager.getZoomOverviewScale();
+    }
+
+    /**
+     * See {@link WebView#canZoomIn()}
+     */
+    @Override
+    public boolean canZoomIn() {
+        checkThread();
+        return mZoomManager.canZoomIn();
+    }
+
+    /**
+     * See {@link WebView#canZoomOut()}
+     */
+    @Override
+    public boolean canZoomOut() {
+        checkThread();
+        return mZoomManager.canZoomOut();
+    }
+
+    /**
+     * See {@link WebView#zoomIn()}
+     */
+    @Override
+    public boolean zoomIn() {
+        checkThread();
+        return mZoomManager.zoomIn();
+    }
+
+    /**
+     * See {@link WebView#zoomOut()}
+     */
+    @Override
+    public boolean zoomOut() {
+        checkThread();
+        return mZoomManager.zoomOut();
+    }
+
+    private void doShortPress() {
+        if (mNativeClass == 0) {
+            return;
+        }
+        if (mPreventDefault == PREVENT_DEFAULT_YES) {
+            return;
+        }
+        mTouchMode = TOUCH_DONE_MODE;
+        switchOutDrawHistory();
+        if (!mTouchHighlightRegion.isEmpty()) {
+            // set mTouchHighlightRequested to 0 to cause an immediate
+            // drawing of the touch rings
+            mTouchHighlightRequested = 0;
+            mWebView.invalidate(mTouchHighlightRegion.getBounds());
+            mPrivateHandler.postDelayed(new Runnable() {
+                @Override
+                public void run() {
+                    removeTouchHighlight();
+                }
+            }, ViewConfiguration.getPressedStateDuration());
+        }
+        if (mFocusedNode != null && mFocusedNode.mIntentUrl != null) {
+            mWebView.playSoundEffect(SoundEffectConstants.CLICK);
+            overrideLoading(mFocusedNode.mIntentUrl);
+        } else {
+            WebViewCore.TouchUpData touchUpData = new WebViewCore.TouchUpData();
+            // use "0" as generation id to inform WebKit to use the same x/y as
+            // it used when processing GET_TOUCH_HIGHLIGHT_RECTS
+            touchUpData.mMoveGeneration = 0;
+            mWebViewCore.sendMessage(EventHub.TOUCH_UP, touchUpData);
+        }
+    }
+
+    void sendPluginDrawMsg() {
+        mWebViewCore.sendMessage(EventHub.PLUGIN_SURFACE_READY);
+    }
+
+    /*
+     * Return true if the rect (e.g. plugin) is fully visible and maximized
+     * inside the WebView.
+     */
+    boolean isRectFitOnScreen(Rect rect) {
+        final int rectWidth = rect.width();
+        final int rectHeight = rect.height();
+        final int viewWidth = getViewWidth();
+        final int viewHeight = getViewHeightWithTitle();
+        float scale = Math.min((float) viewWidth / rectWidth, (float) viewHeight / rectHeight);
+        scale = mZoomManager.computeScaleWithLimits(scale);
+        return !mZoomManager.willScaleTriggerZoom(scale)
+                && contentToViewX(rect.left) >= getScrollX()
+                && contentToViewX(rect.right) <= getScrollX() + viewWidth
+                && contentToViewY(rect.top) >= getScrollY()
+                && contentToViewY(rect.bottom) <= getScrollY() + viewHeight;
+    }
+
+    /*
+     * Maximize and center the rectangle, specified in the document coordinate
+     * space, inside the WebView. If the zoom doesn't need to be changed, do an
+     * animated scroll to center it. If the zoom needs to be changed, find the
+     * zoom center and do a smooth zoom transition. The rect is in document
+     * coordinates
+     */
+    void centerFitRect(Rect rect) {
+        final int rectWidth = rect.width();
+        final int rectHeight = rect.height();
+        final int viewWidth = getViewWidth();
+        final int viewHeight = getViewHeightWithTitle();
+        float scale = Math.min((float) viewWidth / rectWidth, (float) viewHeight
+                / rectHeight);
+        scale = mZoomManager.computeScaleWithLimits(scale);
+        if (!mZoomManager.willScaleTriggerZoom(scale)) {
+            pinScrollTo(contentToViewX(rect.left + rectWidth / 2) - viewWidth / 2,
+                    contentToViewY(rect.top + rectHeight / 2) - viewHeight / 2,
+                    true, 0);
+        } else {
+            float actualScale = mZoomManager.getScale();
+            float oldScreenX = rect.left * actualScale - getScrollX();
+            float rectViewX = rect.left * scale;
+            float rectViewWidth = rectWidth * scale;
+            float newMaxWidth = mContentWidth * scale;
+            float newScreenX = (viewWidth - rectViewWidth) / 2;
+            // pin the newX to the WebView
+            if (newScreenX > rectViewX) {
+                newScreenX = rectViewX;
+            } else if (newScreenX > (newMaxWidth - rectViewX - rectViewWidth)) {
+                newScreenX = viewWidth - (newMaxWidth - rectViewX);
+            }
+            float zoomCenterX = (oldScreenX * scale - newScreenX * actualScale)
+                    / (scale - actualScale);
+            float oldScreenY = rect.top * actualScale + getTitleHeight()
+                    - getScrollY();
+            float rectViewY = rect.top * scale + getTitleHeight();
+            float rectViewHeight = rectHeight * scale;
+            float newMaxHeight = mContentHeight * scale + getTitleHeight();
+            float newScreenY = (viewHeight - rectViewHeight) / 2;
+            // pin the newY to the WebView
+            if (newScreenY > rectViewY) {
+                newScreenY = rectViewY;
+            } else if (newScreenY > (newMaxHeight - rectViewY - rectViewHeight)) {
+                newScreenY = viewHeight - (newMaxHeight - rectViewY);
+            }
+            float zoomCenterY = (oldScreenY * scale - newScreenY * actualScale)
+                    / (scale - actualScale);
+            mZoomManager.setZoomCenter(zoomCenterX, zoomCenterY);
+            mZoomManager.startZoomAnimation(scale, false);
+        }
+    }
+
+    // Called by JNI to handle a touch on a node representing an email address,
+    // address, or phone number
+    private void overrideLoading(String url) {
+        mCallbackProxy.uiOverrideUrlLoading(url);
+    }
+
+    @Override
+    public boolean requestFocus(int direction, Rect previouslyFocusedRect) {
+        // FIXME: If a subwindow is showing find, and the user touches the
+        // background window, it can steal focus.
+        if (mFindIsUp) return false;
+        boolean result = false;
+        result = mWebViewPrivate.super_requestFocus(direction, previouslyFocusedRect);
+        if (mWebViewCore.getSettings().getNeedInitialFocus() && !mWebView.isInTouchMode()) {
+            // For cases such as GMail, where we gain focus from a direction,
+            // we want to move to the first available link.
+            // FIXME: If there are no visible links, we may not want to
+            int fakeKeyDirection = 0;
+            switch(direction) {
+                case View.FOCUS_UP:
+                    fakeKeyDirection = KeyEvent.KEYCODE_DPAD_UP;
+                    break;
+                case View.FOCUS_DOWN:
+                    fakeKeyDirection = KeyEvent.KEYCODE_DPAD_DOWN;
+                    break;
+                case View.FOCUS_LEFT:
+                    fakeKeyDirection = KeyEvent.KEYCODE_DPAD_LEFT;
+                    break;
+                case View.FOCUS_RIGHT:
+                    fakeKeyDirection = KeyEvent.KEYCODE_DPAD_RIGHT;
+                    break;
+                default:
+                    return result;
+            }
+            // TODO: Send initial focus request to webkit (b/6108927)
+        }
+        return result;
+    }
+
+    @Override
+    public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
+        int heightSize = MeasureSpec.getSize(heightMeasureSpec);
+        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
+        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
+
+        int measuredHeight = heightSize;
+        int measuredWidth = widthSize;
+
+        // Grab the content size from WebViewCore.
+        int contentHeight = contentToViewDimension(mContentHeight);
+        int contentWidth = contentToViewDimension(mContentWidth);
+
+//        Log.d(LOGTAG, "------- measure " + heightMode);
+
+        if (heightMode != MeasureSpec.EXACTLY) {
+            mHeightCanMeasure = true;
+            measuredHeight = contentHeight;
+            if (heightMode == MeasureSpec.AT_MOST) {
+                // If we are larger than the AT_MOST height, then our height can
+                // no longer be measured and we should scroll internally.
+                if (measuredHeight > heightSize) {
+                    measuredHeight = heightSize;
+                    mHeightCanMeasure = false;
+                    measuredHeight |= View.MEASURED_STATE_TOO_SMALL;
+                }
+            }
+        } else {
+            mHeightCanMeasure = false;
+        }
+        if (mNativeClass != 0) {
+            nativeSetHeightCanMeasure(mHeightCanMeasure);
+        }
+        // For the width, always use the given size unless unspecified.
+        if (widthMode == MeasureSpec.UNSPECIFIED) {
+            mWidthCanMeasure = true;
+            measuredWidth = contentWidth;
+        } else {
+            if (measuredWidth < contentWidth) {
+                measuredWidth |= View.MEASURED_STATE_TOO_SMALL;
+            }
+            mWidthCanMeasure = false;
+        }
+
+        synchronized (this) {
+            mWebViewPrivate.setMeasuredDimension(measuredWidth, measuredHeight);
+        }
+    }
+
+    @Override
+    public boolean requestChildRectangleOnScreen(View child,
+                                                 Rect rect,
+                                                 boolean immediate) {
+        if (mNativeClass == 0) {
+            return false;
+        }
+        // don't scroll while in zoom animation. When it is done, we will adjust
+        // the necessary components
+        if (mZoomManager.isFixedLengthAnimationInProgress()) {
+            return false;
+        }
+
+        rect.offset(child.getLeft() - child.getScrollX(),
+                child.getTop() - child.getScrollY());
+
+        Rect content = new Rect(viewToContentX(getScrollX()),
+                viewToContentY(getScrollY()),
+                viewToContentX(getScrollX() + getWidth()
+                - mWebView.getVerticalScrollbarWidth()),
+                viewToContentY(getScrollY() + getViewHeightWithTitle()));
+        content = nativeSubtractLayers(content);
+        int screenTop = contentToViewY(content.top);
+        int screenBottom = contentToViewY(content.bottom);
+        int height = screenBottom - screenTop;
+        int scrollYDelta = 0;
+
+        if (rect.bottom > screenBottom) {
+            int oneThirdOfScreenHeight = height / 3;
+            if (rect.height() > 2 * oneThirdOfScreenHeight) {
+                // If the rectangle is too tall to fit in the bottom two thirds
+                // of the screen, place it at the top.
+                scrollYDelta = rect.top - screenTop;
+            } else {
+                // If the rectangle will still fit on screen, we want its
+                // top to be in the top third of the screen.
+                scrollYDelta = rect.top - (screenTop + oneThirdOfScreenHeight);
+            }
+        } else if (rect.top < screenTop) {
+            scrollYDelta = rect.top - screenTop;
+        }
+
+        int screenLeft = contentToViewX(content.left);
+        int screenRight = contentToViewX(content.right);
+        int width = screenRight - screenLeft;
+        int scrollXDelta = 0;
+
+        if (rect.right > screenRight && rect.left > screenLeft) {
+            if (rect.width() > width) {
+                scrollXDelta += (rect.left - screenLeft);
+            } else {
+                scrollXDelta += (rect.right - screenRight);
+            }
+        } else if (rect.left < screenLeft) {
+            scrollXDelta -= (screenLeft - rect.left);
+        }
+
+        if ((scrollYDelta | scrollXDelta) != 0) {
+            return pinScrollBy(scrollXDelta, scrollYDelta, !immediate, 0);
+        }
+
+        return false;
+    }
+
+    /* package */ void replaceTextfieldText(int oldStart, int oldEnd,
+            String replace, int newStart, int newEnd) {
+        WebViewCore.ReplaceTextData arg = new WebViewCore.ReplaceTextData();
+        arg.mReplace = replace;
+        arg.mNewStart = newStart;
+        arg.mNewEnd = newEnd;
+        mTextGeneration++;
+        arg.mTextGeneration = mTextGeneration;
+        mWebViewCore.sendMessage(EventHub.REPLACE_TEXT, oldStart, oldEnd, arg);
+    }
+
+    /* package */ void passToJavaScript(String currentText, KeyEvent event) {
+        // check if mWebViewCore has been destroyed
+        if (mWebViewCore == null) {
+            return;
+        }
+        WebViewCore.JSKeyData arg = new WebViewCore.JSKeyData();
+        arg.mEvent = event;
+        arg.mCurrentText = currentText;
+        // Increase our text generation number, and pass it to webcore thread
+        mTextGeneration++;
+        mWebViewCore.sendMessage(EventHub.PASS_TO_JS, mTextGeneration, 0, arg);
+        // WebKit's document state is not saved until about to leave the page.
+        // To make sure the host application, like Browser, has the up to date
+        // document state when it goes to background, we force to save the
+        // document state.
+        mWebViewCore.removeMessages(EventHub.SAVE_DOCUMENT_STATE);
+        mWebViewCore.sendMessageDelayed(EventHub.SAVE_DOCUMENT_STATE, null, 1000);
+    }
+
+    /**
+     * @hide
+     */
+    public synchronized WebViewCore getWebViewCore() {
+        return mWebViewCore;
+    }
+
+    /**
+     * Used only by TouchEventQueue to store pending touch events.
+     */
+    private static class QueuedTouch {
+        long mSequence;
+        MotionEvent mEvent; // Optional
+        TouchEventData mTed; // Optional
+
+        QueuedTouch mNext;
+
+        public QueuedTouch set(TouchEventData ted) {
+            mSequence = ted.mSequence;
+            mTed = ted;
+            mEvent = null;
+            mNext = null;
+            return this;
+        }
+
+        public QueuedTouch set(MotionEvent ev, long sequence) {
+            mEvent = MotionEvent.obtain(ev);
+            mSequence = sequence;
+            mTed = null;
+            mNext = null;
+            return this;
+        }
+
+        public QueuedTouch add(QueuedTouch other) {
+            if (other.mSequence < mSequence) {
+                other.mNext = this;
+                return other;
+            }
+
+            QueuedTouch insertAt = this;
+            while (insertAt.mNext != null && insertAt.mNext.mSequence < other.mSequence) {
+                insertAt = insertAt.mNext;
+            }
+            other.mNext = insertAt.mNext;
+            insertAt.mNext = other;
+            return this;
+        }
+    }
+
+    /**
+     * WebView handles touch events asynchronously since some events must be passed to WebKit
+     * for potentially slower processing. TouchEventQueue serializes touch events regardless
+     * of which path they take to ensure that no events are ever processed out of order
+     * by WebView.
+     */
+    private class TouchEventQueue {
+        private long mNextTouchSequence = Long.MIN_VALUE + 1;
+        private long mLastHandledTouchSequence = Long.MIN_VALUE;
+        private long mIgnoreUntilSequence = Long.MIN_VALUE + 1;
+
+        // Events waiting to be processed.
+        private QueuedTouch mTouchEventQueue;
+
+        // Known events that are waiting on a response before being enqueued.
+        private QueuedTouch mPreQueue;
+
+        // Pool of QueuedTouch objects saved for later use.
+        private QueuedTouch mQueuedTouchRecycleBin;
+        private int mQueuedTouchRecycleCount;
+
+        private long mLastEventTime = Long.MAX_VALUE;
+        private static final int MAX_RECYCLED_QUEUED_TOUCH = 15;
+
+        // milliseconds until we abandon hope of getting all of a previous gesture
+        private static final int QUEUED_GESTURE_TIMEOUT = 1000;
+
+        private QueuedTouch obtainQueuedTouch() {
+            if (mQueuedTouchRecycleBin != null) {
+                QueuedTouch result = mQueuedTouchRecycleBin;
+                mQueuedTouchRecycleBin = result.mNext;
+                mQueuedTouchRecycleCount--;
+                return result;
+            }
+            return new QueuedTouch();
+        }
+
+        /**
+         * Allow events with any currently missing sequence numbers to be skipped in processing.
+         */
+        public void ignoreCurrentlyMissingEvents() {
+            mIgnoreUntilSequence = mNextTouchSequence;
+
+            // Run any events we have available and complete, pre-queued or otherwise.
+            runQueuedAndPreQueuedEvents();
+        }
+
+        private void runQueuedAndPreQueuedEvents() {
+            QueuedTouch qd = mPreQueue;
+            boolean fromPreQueue = true;
+            while (qd != null && qd.mSequence == mLastHandledTouchSequence + 1) {
+                handleQueuedTouch(qd);
+                QueuedTouch recycleMe = qd;
+                if (fromPreQueue) {
+                    mPreQueue = qd.mNext;
+                } else {
+                    mTouchEventQueue = qd.mNext;
+                }
+                recycleQueuedTouch(recycleMe);
+                mLastHandledTouchSequence++;
+
+                long nextPre = mPreQueue != null ? mPreQueue.mSequence : Long.MAX_VALUE;
+                long nextQueued = mTouchEventQueue != null ?
+                        mTouchEventQueue.mSequence : Long.MAX_VALUE;
+                fromPreQueue = nextPre < nextQueued;
+                qd = fromPreQueue ? mPreQueue : mTouchEventQueue;
+            }
+        }
+
+        /**
+         * Add a TouchEventData to the pre-queue.
+         *
+         * An event in the pre-queue is an event that we know about that
+         * has been sent to webkit, but that we haven't received back and
+         * enqueued into the normal touch queue yet. If webkit ever times
+         * out and we need to ignore currently missing events, we'll run
+         * events from the pre-queue to patch the holes.
+         *
+         * @param ted TouchEventData to pre-queue
+         */
+        public void preQueueTouchEventData(TouchEventData ted) {
+            QueuedTouch newTouch = obtainQueuedTouch().set(ted);
+            if (mPreQueue == null) {
+                mPreQueue = newTouch;
+            } else {
+                QueuedTouch insertionPoint = mPreQueue;
+                while (insertionPoint.mNext != null &&
+                        insertionPoint.mNext.mSequence < newTouch.mSequence) {
+                    insertionPoint = insertionPoint.mNext;
+                }
+                newTouch.mNext = insertionPoint.mNext;
+                insertionPoint.mNext = newTouch;
+            }
+        }
+
+        private void recycleQueuedTouch(QueuedTouch qd) {
+            if (mQueuedTouchRecycleCount < MAX_RECYCLED_QUEUED_TOUCH) {
+                qd.mNext = mQueuedTouchRecycleBin;
+                mQueuedTouchRecycleBin = qd;
+                mQueuedTouchRecycleCount++;
+            }
+        }
+
+        /**
+         * Reset the touch event queue. This will dump any pending events
+         * and reset the sequence numbering.
+         */
+        public void reset() {
+            mNextTouchSequence = Long.MIN_VALUE + 1;
+            mLastHandledTouchSequence = Long.MIN_VALUE;
+            mIgnoreUntilSequence = Long.MIN_VALUE + 1;
+            while (mTouchEventQueue != null) {
+                QueuedTouch recycleMe = mTouchEventQueue;
+                mTouchEventQueue = mTouchEventQueue.mNext;
+                recycleQueuedTouch(recycleMe);
+            }
+            while (mPreQueue != null) {
+                QueuedTouch recycleMe = mPreQueue;
+                mPreQueue = mPreQueue.mNext;
+                recycleQueuedTouch(recycleMe);
+            }
+        }
+
+        /**
+         * Return the next valid sequence number for tagging incoming touch events.
+         * @return The next touch event sequence number
+         */
+        public long nextTouchSequence() {
+            return mNextTouchSequence++;
+        }
+
+        /**
+         * Enqueue a touch event in the form of TouchEventData.
+         * The sequence number will be read from the mSequence field of the argument.
+         *
+         * If the touch event's sequence number is the next in line to be processed, it will
+         * be handled before this method returns. Any subsequent events that have already
+         * been queued will also be processed in their proper order.
+         *
+         * @param ted Touch data to be processed in order.
+         * @return true if the event was processed before returning, false if it was just enqueued.
+         */
+        public boolean enqueueTouchEvent(TouchEventData ted) {
+            // Remove from the pre-queue if present
+            QueuedTouch preQueue = mPreQueue;
+            if (preQueue != null) {
+                // On exiting this block, preQueue is set to the pre-queued QueuedTouch object
+                // if it was present in the pre-queue, and removed from the pre-queue itself.
+                if (preQueue.mSequence == ted.mSequence) {
+                    mPreQueue = preQueue.mNext;
+                } else {
+                    QueuedTouch prev = preQueue;
+                    preQueue = null;
+                    while (prev.mNext != null) {
+                        if (prev.mNext.mSequence == ted.mSequence) {
+                            preQueue = prev.mNext;
+                            prev.mNext = preQueue.mNext;
+                            break;
+                        } else {
+                            prev = prev.mNext;
+                        }
+                    }
+                }
+            }
+
+            if (ted.mSequence < mLastHandledTouchSequence) {
+                // Stale event and we already moved on; drop it. (Should not be common.)
+                Log.w(LOGTAG, "Stale touch event " + MotionEvent.actionToString(ted.mAction) +
+                        " received from webcore; ignoring");
+                return false;
+            }
+
+            if (dropStaleGestures(ted.mMotionEvent, ted.mSequence)) {
+                return false;
+            }
+
+            // dropStaleGestures above might have fast-forwarded us to
+            // an event we have already.
+            runNextQueuedEvents();
+
+            if (mLastHandledTouchSequence + 1 == ted.mSequence) {
+                if (preQueue != null) {
+                    recycleQueuedTouch(preQueue);
+                    preQueue = null;
+                }
+                handleQueuedTouchEventData(ted);
+
+                mLastHandledTouchSequence++;
+
+                // Do we have any more? Run them if so.
+                runNextQueuedEvents();
+            } else {
+                // Reuse the pre-queued object if we had it.
+                QueuedTouch qd = preQueue != null ? preQueue : obtainQueuedTouch().set(ted);
+                mTouchEventQueue = mTouchEventQueue == null ? qd : mTouchEventQueue.add(qd);
+            }
+            return true;
+        }
+
+        /**
+         * Enqueue a touch event in the form of a MotionEvent from the framework.
+         *
+         * If the touch event's sequence number is the next in line to be processed, it will
+         * be handled before this method returns. Any subsequent events that have already
+         * been queued will also be processed in their proper order.
+         *
+         * @param ev MotionEvent to be processed in order
+         */
+        public void enqueueTouchEvent(MotionEvent ev) {
+            final long sequence = nextTouchSequence();
+
+            if (dropStaleGestures(ev, sequence)) {
+                return;
+            }
+
+            // dropStaleGestures above might have fast-forwarded us to
+            // an event we have already.
+            runNextQueuedEvents();
+
+            if (mLastHandledTouchSequence + 1 == sequence) {
+                handleQueuedMotionEvent(ev);
+
+                mLastHandledTouchSequence++;
+
+                // Do we have any more? Run them if so.
+                runNextQueuedEvents();
+            } else {
+                QueuedTouch qd = obtainQueuedTouch().set(ev, sequence);
+                mTouchEventQueue = mTouchEventQueue == null ? qd : mTouchEventQueue.add(qd);
+            }
+        }
+
+        private void runNextQueuedEvents() {
+            QueuedTouch qd = mTouchEventQueue;
+            while (qd != null && qd.mSequence == mLastHandledTouchSequence + 1) {
+                handleQueuedTouch(qd);
+                QueuedTouch recycleMe = qd;
+                qd = qd.mNext;
+                recycleQueuedTouch(recycleMe);
+                mLastHandledTouchSequence++;
+            }
+            mTouchEventQueue = qd;
+        }
+
+        private boolean dropStaleGestures(MotionEvent ev, long sequence) {
+            if (ev != null && ev.getAction() == MotionEvent.ACTION_MOVE && !mConfirmMove) {
+                // This is to make sure that we don't attempt to process a tap
+                // or long press when webkit takes too long to get back to us.
+                // The movement will be properly confirmed when we process the
+                // enqueued event later.
+                final int dx = Math.round(ev.getX()) - mLastTouchX;
+                final int dy = Math.round(ev.getY()) - mLastTouchY;
+                if (dx * dx + dy * dy > mTouchSlopSquare) {
+                    mPrivateHandler.removeMessages(SWITCH_TO_SHORTPRESS);
+                    mPrivateHandler.removeMessages(SWITCH_TO_LONGPRESS);
+                }
+            }
+
+            if (mTouchEventQueue == null) {
+                return sequence <= mLastHandledTouchSequence;
+            }
+
+            // If we have a new down event and it's been a while since the last event
+            // we saw, catch up as best we can and keep going.
+            if (ev != null && ev.getAction() == MotionEvent.ACTION_DOWN) {
+                long eventTime = ev.getEventTime();
+                long lastHandledEventTime = mLastEventTime;
+                if (eventTime > lastHandledEventTime + QUEUED_GESTURE_TIMEOUT) {
+                    Log.w(LOGTAG, "Got ACTION_DOWN but still waiting on stale event. " +
+                            "Catching up.");
+                    runQueuedAndPreQueuedEvents();
+
+                    // Drop leftovers that we truly don't have.
+                    QueuedTouch qd = mTouchEventQueue;
+                    while (qd != null && qd.mSequence < sequence) {
+                        QueuedTouch recycleMe = qd;
+                        qd = qd.mNext;
+                        recycleQueuedTouch(recycleMe);
+                    }
+                    mTouchEventQueue = qd;
+                    mLastHandledTouchSequence = sequence - 1;
+                }
+            }
+
+            if (mIgnoreUntilSequence - 1 > mLastHandledTouchSequence) {
+                QueuedTouch qd = mTouchEventQueue;
+                while (qd != null && qd.mSequence < mIgnoreUntilSequence) {
+                    QueuedTouch recycleMe = qd;
+                    qd = qd.mNext;
+                    recycleQueuedTouch(recycleMe);
+                }
+                mTouchEventQueue = qd;
+                mLastHandledTouchSequence = mIgnoreUntilSequence - 1;
+            }
+
+            if (mPreQueue != null) {
+                // Drop stale prequeued events
+                QueuedTouch qd = mPreQueue;
+                while (qd != null && qd.mSequence < mIgnoreUntilSequence) {
+                    QueuedTouch recycleMe = qd;
+                    qd = qd.mNext;
+                    recycleQueuedTouch(recycleMe);
+                }
+                mPreQueue = qd;
+            }
+
+            return sequence <= mLastHandledTouchSequence;
+        }
+
+        private void handleQueuedTouch(QueuedTouch qt) {
+            if (qt.mTed != null) {
+                handleQueuedTouchEventData(qt.mTed);
+            } else {
+                handleQueuedMotionEvent(qt.mEvent);
+                qt.mEvent.recycle();
+            }
+        }
+
+        private void handleQueuedMotionEvent(MotionEvent ev) {
+            mLastEventTime = ev.getEventTime();
+            int action = ev.getActionMasked();
+            if (ev.getPointerCount() > 1) {  // Multi-touch
+                handleMultiTouchInWebView(ev);
+            } else {
+                final ScaleGestureDetector detector = mZoomManager.getMultiTouchGestureDetector();
+                if (detector != null && mPreventDefault != PREVENT_DEFAULT_YES) {
+                    // ScaleGestureDetector needs a consistent event stream to operate properly.
+                    // It won't take any action with fewer than two pointers, but it needs to
+                    // update internal bookkeeping state.
+                    detector.onTouchEvent(ev);
+                }
+
+                handleTouchEventCommon(ev, action, Math.round(ev.getX()), Math.round(ev.getY()));
+            }
+        }
+
+        private void handleQueuedTouchEventData(TouchEventData ted) {
+            if (ted.mMotionEvent != null) {
+                mLastEventTime = ted.mMotionEvent.getEventTime();
+            }
+            if (!ted.mReprocess) {
+                if (ted.mAction == MotionEvent.ACTION_DOWN
+                        && mPreventDefault == PREVENT_DEFAULT_MAYBE_YES) {
+                    // if prevent default is called from WebCore, UI
+                    // will not handle the rest of the touch events any
+                    // more.
+                    mPreventDefault = ted.mNativeResult ? PREVENT_DEFAULT_YES
+                            : PREVENT_DEFAULT_NO_FROM_TOUCH_DOWN;
+                } else if (ted.mAction == MotionEvent.ACTION_MOVE
+                        && mPreventDefault == PREVENT_DEFAULT_NO_FROM_TOUCH_DOWN) {
+                    // the return for the first ACTION_MOVE will decide
+                    // whether UI will handle touch or not. Currently no
+                    // support for alternating prevent default
+                    mPreventDefault = ted.mNativeResult ? PREVENT_DEFAULT_YES
+                            : PREVENT_DEFAULT_NO;
+                }
+                if (mPreventDefault == PREVENT_DEFAULT_YES) {
+                    mTouchHighlightRegion.setEmpty();
+                }
+            } else {
+                if (ted.mPoints.length > 1) {  // multi-touch
+                    if (!ted.mNativeResult && mPreventDefault != PREVENT_DEFAULT_YES) {
+                        mPreventDefault = PREVENT_DEFAULT_NO;
+                        handleMultiTouchInWebView(ted.mMotionEvent);
+                    } else {
+                        mPreventDefault = PREVENT_DEFAULT_YES;
+                    }
+                    return;
+                }
+
+                // prevent default is not called in WebCore, so the
+                // message needs to be reprocessed in UI
+                if (!ted.mNativeResult) {
+                    // Following is for single touch.
+                    switch (ted.mAction) {
+                        case MotionEvent.ACTION_DOWN:
+                            mLastDeferTouchX = ted.mPointsInView[0].x;
+                            mLastDeferTouchY = ted.mPointsInView[0].y;
+                            mDeferTouchMode = TOUCH_INIT_MODE;
+                            break;
+                        case MotionEvent.ACTION_MOVE: {
+                            // no snapping in defer process
+                            int x = ted.mPointsInView[0].x;
+                            int y = ted.mPointsInView[0].y;
+
+                            if (mDeferTouchMode != TOUCH_DRAG_MODE) {
+                                mDeferTouchMode = TOUCH_DRAG_MODE;
+                                mLastDeferTouchX = x;
+                                mLastDeferTouchY = y;
+                                startScrollingLayer(x, y);
+                                startDrag();
+                            }
+                            int deltaX = pinLocX((int) (getScrollX()
+                                    + mLastDeferTouchX - x))
+                                    - getScrollX();
+                            int deltaY = pinLocY((int) (getScrollY()
+                                    + mLastDeferTouchY - y))
+                                    - getScrollY();
+                            doDrag(deltaX, deltaY);
+                            if (deltaX != 0) mLastDeferTouchX = x;
+                            if (deltaY != 0) mLastDeferTouchY = y;
+                            break;
+                        }
+                        case MotionEvent.ACTION_UP:
+                        case MotionEvent.ACTION_CANCEL:
+                            if (mDeferTouchMode == TOUCH_DRAG_MODE) {
+                                // no fling in defer process
+                                mScroller.springBack(getScrollX(), getScrollY(), 0,
+                                        computeMaxScrollX(), 0,
+                                        computeMaxScrollY());
+                                invalidate();
+                                WebViewCore.resumePriority();
+                                WebViewCore.resumeUpdatePicture(mWebViewCore);
+                            }
+                            mDeferTouchMode = TOUCH_DONE_MODE;
+                            break;
+                        case WebViewCore.ACTION_DOUBLETAP:
+                            // doDoubleTap() needs mLastTouchX/Y as anchor
+                            mLastDeferTouchX = ted.mPointsInView[0].x;
+                            mLastDeferTouchY = ted.mPointsInView[0].y;
+                            mZoomManager.handleDoubleTap(mLastTouchX, mLastTouchY);
+                            mDeferTouchMode = TOUCH_DONE_MODE;
+                            break;
+                        case WebViewCore.ACTION_LONGPRESS:
+                            HitTestResult hitTest = getHitTestResult();
+                            if (hitTest != null && hitTest.getType()
+                                    != HitTestResult.UNKNOWN_TYPE) {
+                                performLongClick();
+                            }
+                            mDeferTouchMode = TOUCH_DONE_MODE;
+                            break;
+                    }
+                }
+            }
+        }
+    }
+
+    //-------------------------------------------------------------------------
+    // Methods can be called from a separate thread, like WebViewCore
+    // If it needs to call the View system, it has to send message.
+    //-------------------------------------------------------------------------
+
+    /**
+     * General handler to receive message coming from webkit thread
+     */
+    class PrivateHandler extends Handler {
+        @Override
+        public void handleMessage(Message msg) {
+            // exclude INVAL_RECT_MSG_ID since it is frequently output
+            if (DebugFlags.WEB_VIEW && msg.what != INVAL_RECT_MSG_ID) {
+                if (msg.what >= FIRST_PRIVATE_MSG_ID
+                        && msg.what <= LAST_PRIVATE_MSG_ID) {
+                    Log.v(LOGTAG, HandlerPrivateDebugString[msg.what
+                            - FIRST_PRIVATE_MSG_ID]);
+                } else if (msg.what >= FIRST_PACKAGE_MSG_ID
+                        && msg.what <= LAST_PACKAGE_MSG_ID) {
+                    Log.v(LOGTAG, HandlerPackageDebugString[msg.what
+                            - FIRST_PACKAGE_MSG_ID]);
+                } else {
+                    Log.v(LOGTAG, Integer.toString(msg.what));
+                }
+            }
+            if (mWebViewCore == null) {
+                // after WebView's destroy() is called, skip handling messages.
+                return;
+            }
+            if (mBlockWebkitViewMessages
+                    && msg.what != WEBCORE_INITIALIZED_MSG_ID) {
+                // Blocking messages from webkit
+                return;
+            }
+            switch (msg.what) {
+                case REMEMBER_PASSWORD: {
+                    mDatabase.setUsernamePassword(
+                            msg.getData().getString("host"),
+                            msg.getData().getString("username"),
+                            msg.getData().getString("password"));
+                    ((Message) msg.obj).sendToTarget();
+                    break;
+                }
+                case NEVER_REMEMBER_PASSWORD: {
+                    mDatabase.setUsernamePassword(
+                            msg.getData().getString("host"), null, null);
+                    ((Message) msg.obj).sendToTarget();
+                    break;
+                }
+                case PREVENT_DEFAULT_TIMEOUT: {
+                    // if timeout happens, cancel it so that it won't block UI
+                    // to continue handling touch events
+                    if ((msg.arg1 == MotionEvent.ACTION_DOWN
+                            && mPreventDefault == PREVENT_DEFAULT_MAYBE_YES)
+                            || (msg.arg1 == MotionEvent.ACTION_MOVE
+                            && mPreventDefault == PREVENT_DEFAULT_NO_FROM_TOUCH_DOWN)) {
+                        cancelWebCoreTouchEvent(
+                                viewToContentX(mLastTouchX + getScrollX()),
+                                viewToContentY(mLastTouchY + getScrollY()),
+                                true);
+                    }
+                    break;
+                }
+                case SCROLL_SELECT_TEXT: {
+                    if (mAutoScrollX == 0 && mAutoScrollY == 0) {
+                        mSentAutoScrollMessage = false;
+                        break;
+                    }
+                    if (mCurrentScrollingLayerId == 0) {
+                        pinScrollBy(mAutoScrollX, mAutoScrollY, true, 0);
+                    } else {
+                        scrollLayerTo(mScrollingLayerRect.left + mAutoScrollX,
+                                mScrollingLayerRect.top + mAutoScrollY);
+                    }
+                    sendEmptyMessageDelayed(
+                            SCROLL_SELECT_TEXT, SELECT_SCROLL_INTERVAL);
+                    break;
+                }
+                case SWITCH_TO_SHORTPRESS: {
+                    if (mTouchMode == TOUCH_INIT_MODE) {
+                        mTouchMode = TOUCH_SHORTPRESS_MODE;
+                    } else if (mTouchMode == TOUCH_DOUBLE_TAP_MODE) {
+                        mTouchMode = TOUCH_DONE_MODE;
+                    }
+                    break;
+                }
+                case SWITCH_TO_LONGPRESS: {
+                    removeTouchHighlight();
+                    if (inFullScreenMode() || mDeferTouchProcess) {
+                        TouchEventData ted = new TouchEventData();
+                        ted.mAction = WebViewCore.ACTION_LONGPRESS;
+                        ted.mIds = new int[1];
+                        ted.mIds[0] = 0;
+                        ted.mPoints = new Point[1];
+                        ted.mPoints[0] = new Point(viewToContentX(mLastTouchX + getScrollX()),
+                                                   viewToContentY(mLastTouchY + getScrollY()));
+                        ted.mPointsInView = new Point[1];
+                        ted.mPointsInView[0] = new Point(mLastTouchX, mLastTouchY);
+                        // metaState for long press is tricky. Should it be the
+                        // state when the press started or when the press was
+                        // released? Or some intermediary key state? For
+                        // simplicity for now, we don't set it.
+                        ted.mMetaState = 0;
+                        ted.mReprocess = mDeferTouchProcess;
+                        ted.mNativeLayer = nativeScrollableLayer(
+                                ted.mPoints[0].x, ted.mPoints[0].y,
+                                ted.mNativeLayerRect, null);
+                        ted.mSequence = mTouchEventQueue.nextTouchSequence();
+                        mTouchEventQueue.preQueueTouchEventData(ted);
+                        mWebViewCore.sendMessage(EventHub.TOUCH_EVENT, ted);
+                    } else if (mPreventDefault != PREVENT_DEFAULT_YES) {
+                        mTouchMode = TOUCH_DONE_MODE;
+                        performLongClick();
+                    }
+                    break;
+                }
+                case RELEASE_SINGLE_TAP: {
+                    doShortPress();
+                    break;
+                }
+                case SCROLL_TO_MSG_ID: {
+                    // arg1 = animate, arg2 = onlyIfImeIsShowing
+                    // obj = Point(x, y)
+                    if (msg.arg2 == 1) {
+                        // This scroll is intended to bring the textfield into
+                        // view, but is only necessary if the IME is showing
+                        InputMethodManager imm = InputMethodManager.peekInstance();
+                        if (imm == null || !imm.isAcceptingText()
+                                || !imm.isActive(mWebView)) {
+                            break;
+                        }
+                    }
+                    final Point p = (Point) msg.obj;
+                    if (msg.arg1 == 1) {
+                        spawnContentScrollTo(p.x, p.y);
+                    } else {
+                        setContentScrollTo(p.x, p.y);
+                    }
+                    break;
+                }
+                case UPDATE_ZOOM_RANGE: {
+                    WebViewCore.ViewState viewState = (WebViewCore.ViewState) msg.obj;
+                    // mScrollX contains the new minPrefWidth
+                    mZoomManager.updateZoomRange(viewState, getViewWidth(), viewState.mScrollX);
+                    break;
+                }
+                case UPDATE_ZOOM_DENSITY: {
+                    final float density = (Float) msg.obj;
+                    mZoomManager.updateDefaultZoomDensity(density);
+                    break;
+                }
+                case REPLACE_BASE_CONTENT: {
+                    nativeReplaceBaseContent(msg.arg1);
+                    break;
+                }
+                case NEW_PICTURE_MSG_ID: {
+                    // called for new content
+                    final WebViewCore.DrawData draw = (WebViewCore.DrawData) msg.obj;
+                    setNewPicture(draw, true);
+                    break;
+                }
+                case WEBCORE_INITIALIZED_MSG_ID:
+                    // nativeCreate sets mNativeClass to a non-zero value
+                    String drawableDir = BrowserFrame.getRawResFilename(
+                            BrowserFrame.DRAWABLEDIR, mContext);
+                    WindowManager windowManager =
+                            (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
+                    Display display = windowManager.getDefaultDisplay();
+                    nativeCreate(msg.arg1, drawableDir,
+                            ActivityManager.isHighEndGfx(display));
+                    if (mDelaySetPicture != null) {
+                        setNewPicture(mDelaySetPicture, true);
+                        mDelaySetPicture = null;
+                    }
+                    if (mIsPaused) {
+                        nativeSetPauseDrawing(mNativeClass, true);
+                    }
+                    break;
+                case UPDATE_TEXTFIELD_TEXT_MSG_ID:
+                    // Make sure that the textfield is currently focused
+                    // and representing the same node as the pointer.
+                    if (msg.arg2 == mTextGeneration) {
+                        String text = (String) msg.obj;
+                        if (null == text) {
+                            text = "";
+                        }
+                        if (mInputConnection != null &&
+                                mFieldPointer == msg.arg1) {
+                            mInputConnection.setTextAndKeepSelection(text);
+                        }
+                    }
+                    break;
+                case REQUEST_KEYBOARD_WITH_SELECTION_MSG_ID:
+                    displaySoftKeyboard(true);
+                    // fall through to UPDATE_TEXT_SELECTION_MSG_ID
+                case UPDATE_TEXT_SELECTION_MSG_ID:
+                    updateTextSelectionFromMessage(msg.arg1, msg.arg2,
+                            (WebViewCore.TextSelectionData) msg.obj);
+                    break;
+                case FORM_DID_BLUR:
+                    // TODO: Figure out if this is needed for something (b/6111763)
+                    break;
+                case TAKE_FOCUS:
+                    int direction = msg.arg1;
+                    View focusSearch = mWebView.focusSearch(direction);
+                    if (focusSearch != null && focusSearch != mWebView) {
+                        focusSearch.requestFocus();
+                    }
+                    break;
+                case CLEAR_TEXT_ENTRY:
+                    hideSoftKeyboard();
+                    break;
+                case INVAL_RECT_MSG_ID: {
+                    Rect r = (Rect)msg.obj;
+                    if (r == null) {
+                        invalidate();
+                    } else {
+                        // we need to scale r from content into view coords,
+                        // which viewInvalidate() does for us
+                        viewInvalidate(r.left, r.top, r.right, r.bottom);
+                    }
+                    break;
+                }
+
+                case LONG_PRESS_CENTER:
+                    // as this is shared by keydown and trackballdown, reset all
+                    // the states
+                    mGotCenterDown = false;
+                    mTrackballDown = false;
+                    performLongClick();
+                    break;
+
+                case WEBCORE_NEED_TOUCH_EVENTS:
+                    mForwardTouchEvents = (msg.arg1 != 0);
+                    break;
+
+                case PREVENT_TOUCH_ID:
+                    if (inFullScreenMode()) {
+                        break;
+                    }
+                    TouchEventData ted = (TouchEventData) msg.obj;
+
+                    if (mTouchEventQueue.enqueueTouchEvent(ted)) {
+                        // WebCore is responding to us; remove pending timeout.
+                        // It will be re-posted when needed.
+                        removeMessages(PREVENT_DEFAULT_TIMEOUT);
+                    }
+                    break;
+
+                case REQUEST_KEYBOARD:
+                    if (msg.arg1 == 0) {
+                        hideSoftKeyboard();
+                    } else {
+                        displaySoftKeyboard(false);
+                    }
+                    break;
+
+                case DRAG_HELD_MOTIONLESS:
+                    mHeldMotionless = MOTIONLESS_TRUE;
+                    invalidate();
+                    // fall through to keep scrollbars awake
+
+                case AWAKEN_SCROLL_BARS:
+                    if (mTouchMode == TOUCH_DRAG_MODE
+                            && mHeldMotionless == MOTIONLESS_TRUE) {
+                        mWebViewPrivate.awakenScrollBars(ViewConfiguration
+                                .getScrollDefaultDelay(), false);
+                        mPrivateHandler.sendMessageDelayed(mPrivateHandler
+                                .obtainMessage(AWAKEN_SCROLL_BARS),
+                                ViewConfiguration.getScrollDefaultDelay());
+                    }
+                    break;
+
+                case SCREEN_ON:
+                    mWebView.setKeepScreenOn(msg.arg1 == 1);
+                    break;
+
+                case ENTER_FULLSCREEN_VIDEO:
+                    int layerId = msg.arg1;
+
+                    String url = (String) msg.obj;
+                    if (mHTML5VideoViewProxy != null) {
+                        mHTML5VideoViewProxy.enterFullScreenVideo(layerId, url);
+                    }
+                    break;
+
+                case EXIT_FULLSCREEN_VIDEO:
+                    if (mHTML5VideoViewProxy != null) {
+                        mHTML5VideoViewProxy.exitFullScreenVideo();
+                    }
+                    break;
+
+                case SHOW_FULLSCREEN: {
+                    View view = (View) msg.obj;
+                    int orientation = msg.arg1;
+                    int npp = msg.arg2;
+
+                    if (inFullScreenMode()) {
+                        Log.w(LOGTAG, "Should not have another full screen.");
+                        dismissFullScreenMode();
+                    }
+                    mFullScreenHolder = new PluginFullScreenHolder(WebViewClassic.this, orientation, npp);
+                    mFullScreenHolder.setContentView(view);
+                    mFullScreenHolder.show();
+                    invalidate();
+
+                    break;
+                }
+                case HIDE_FULLSCREEN:
+                    dismissFullScreenMode();
+                    break;
+
+                case SHOW_RECT_MSG_ID: {
+                    WebViewCore.ShowRectData data = (WebViewCore.ShowRectData) msg.obj;
+                    int x = getScrollX();
+                    int left = contentToViewX(data.mLeft);
+                    int width = contentToViewDimension(data.mWidth);
+                    int maxWidth = contentToViewDimension(data.mContentWidth);
+                    int viewWidth = getViewWidth();
+                    if (width < viewWidth) {
+                        // center align
+                        x += left + width / 2 - getScrollX() - viewWidth / 2;
+                    } else {
+                        x += (int) (left + data.mXPercentInDoc * width
+                                - getScrollX() - data.mXPercentInView * viewWidth);
+                    }
+                    if (DebugFlags.WEB_VIEW) {
+                        Log.v(LOGTAG, "showRectMsg=(left=" + left + ",width=" +
+                              width + ",maxWidth=" + maxWidth +
+                              ",viewWidth=" + viewWidth + ",x="
+                              + x + ",xPercentInDoc=" + data.mXPercentInDoc +
+                              ",xPercentInView=" + data.mXPercentInView+ ")");
+                    }
+                    // use the passing content width to cap x as the current
+                    // mContentWidth may not be updated yet
+                    x = Math.max(0,
+                            (Math.min(maxWidth, x + viewWidth)) - viewWidth);
+                    int top = contentToViewY(data.mTop);
+                    int height = contentToViewDimension(data.mHeight);
+                    int maxHeight = contentToViewDimension(data.mContentHeight);
+                    int viewHeight = getViewHeight();
+                    int y = (int) (top + data.mYPercentInDoc * height -
+                                   data.mYPercentInView * viewHeight);
+                    if (DebugFlags.WEB_VIEW) {
+                        Log.v(LOGTAG, "showRectMsg=(top=" + top + ",height=" +
+                              height + ",maxHeight=" + maxHeight +
+                              ",viewHeight=" + viewHeight + ",y="
+                              + y + ",yPercentInDoc=" + data.mYPercentInDoc +
+                              ",yPercentInView=" + data.mYPercentInView+ ")");
+                    }
+                    // use the passing content height to cap y as the current
+                    // mContentHeight may not be updated yet
+                    y = Math.max(0,
+                            (Math.min(maxHeight, y + viewHeight) - viewHeight));
+                    // We need to take into account the visible title height
+                    // when scrolling since y is an absolute view position.
+                    y = Math.max(0, y - getVisibleTitleHeightImpl());
+                    mWebView.scrollTo(x, y);
+                    }
+                    break;
+
+                case CENTER_FIT_RECT:
+                    centerFitRect((Rect)msg.obj);
+                    break;
+
+                case SET_SCROLLBAR_MODES:
+                    mHorizontalScrollBarMode = msg.arg1;
+                    mVerticalScrollBarMode = msg.arg2;
+                    break;
+
+                case SELECTION_STRING_CHANGED:
+                    if (mAccessibilityInjector != null) {
+                        String selectionString = (String) msg.obj;
+                        mAccessibilityInjector.onSelectionStringChange(selectionString);
+                    }
+                    break;
+
+                case HIT_TEST_RESULT:
+                    WebKitHitTest hit = (WebKitHitTest) msg.obj;
+                    mFocusedNode = hit;
+                    setTouchHighlightRects(hit);
+                    setHitTestResult(hit);
+                    break;
+
+                case SAVE_WEBARCHIVE_FINISHED:
+                    SaveWebArchiveMessage saveMessage = (SaveWebArchiveMessage)msg.obj;
+                    if (saveMessage.mCallback != null) {
+                        saveMessage.mCallback.onReceiveValue(saveMessage.mResultFile);
+                    }
+                    break;
+
+                case SET_AUTOFILLABLE:
+                    mAutoFillData = (WebViewCore.AutoFillData) msg.obj;
+                    // TODO: Support (b/6083041)
+                    break;
+
+                case AUTOFILL_COMPLETE:
+                    // TODO: Support (b/6083041)
+                    break;
+
+                case COPY_TO_CLIPBOARD:
+                    copyToClipboard((String) msg.obj);
+                    break;
+
+                case INIT_EDIT_FIELD:
+                    if (mInputConnection != null) {
+                        TextFieldInitData initData = (TextFieldInitData) msg.obj;
+                        mTextGeneration = 0;
+                        mFieldPointer = initData.mFieldPointer;
+                        mInputConnection.initEditorInfo(initData);
+                        mInputConnection.setTextAndKeepSelection(initData.mText);
+                    }
+                    break;
+
+                case REPLACE_TEXT:{
+                    String text = (String)msg.obj;
+                    int start = msg.arg1;
+                    int end = msg.arg2;
+                    int cursorPosition = start + text.length();
+                    replaceTextfieldText(start, end, text,
+                            cursorPosition, cursorPosition);
+                    break;
+                }
+
+                case UPDATE_MATCH_COUNT: {
+                    if (mFindCallback != null) {
+                        mFindCallback.updateMatchCount(msg.arg1, msg.arg2,
+                            (String) msg.obj);
+                    }
+                    break;
+                }
+                case CLEAR_CARET_HANDLE:
+                    selectionDone();
+                    break;
+
+                case KEY_PRESS:
+                    mWebViewCore.sendMessage(EventHub.KEY_PRESS, msg.arg1);
+                    break;
+
+                default:
+                    super.handleMessage(msg);
+                    break;
+            }
+        }
+    }
+
+    private void setHitTestTypeFromUrl(String url) {
+        String substr = null;
+        if (url.startsWith(SCHEME_GEO)) {
+            mInitialHitTestResult.setType(HitTestResult.GEO_TYPE);
+            substr = url.substring(SCHEME_GEO.length());
+        } else if (url.startsWith(SCHEME_TEL)) {
+            mInitialHitTestResult.setType(HitTestResult.PHONE_TYPE);
+            substr = url.substring(SCHEME_TEL.length());
+        } else if (url.startsWith(SCHEME_MAILTO)) {
+            mInitialHitTestResult.setType(HitTestResult.EMAIL_TYPE);
+            substr = url.substring(SCHEME_MAILTO.length());
+        } else {
+            mInitialHitTestResult.setType(HitTestResult.SRC_ANCHOR_TYPE);
+            mInitialHitTestResult.setExtra(url);
+            return;
+        }
+        try {
+            mInitialHitTestResult.setExtra(URLDecoder.decode(substr, "UTF-8"));
+        } catch (Throwable e) {
+            Log.w(LOGTAG, "Failed to decode URL! " + substr, e);
+            mInitialHitTestResult.setType(HitTestResult.UNKNOWN_TYPE);
+        }
+    }
+
+    private void setHitTestResult(WebKitHitTest hit) {
+        if (hit == null) {
+            mInitialHitTestResult = null;
+            return;
+        }
+        mInitialHitTestResult = new HitTestResult();
+        if (hit.mLinkUrl != null) {
+            setHitTestTypeFromUrl(hit.mLinkUrl);
+            if (hit.mImageUrl != null
+                    && mInitialHitTestResult.getType() == HitTestResult.SRC_ANCHOR_TYPE) {
+                mInitialHitTestResult.setType(HitTestResult.SRC_IMAGE_ANCHOR_TYPE);
+                mInitialHitTestResult.setExtra(hit.mImageUrl);
+            }
+        } else if (hit.mImageUrl != null) {
+            mInitialHitTestResult.setType(HitTestResult.IMAGE_TYPE);
+            mInitialHitTestResult.setExtra(hit.mImageUrl);
+        } else if (hit.mEditable) {
+            mInitialHitTestResult.setType(HitTestResult.EDIT_TEXT_TYPE);
+        } else if (hit.mIntentUrl != null) {
+            setHitTestTypeFromUrl(hit.mIntentUrl);
+        }
+    }
+
+    private boolean shouldDrawHighlightRect() {
+        if (mFocusedNode == null || mInitialHitTestResult == null) {
+            return false;
+        }
+        if (mTouchHighlightRegion.isEmpty()) {
+            return false;
+        }
+        if (mFocusedNode.mHasFocus && !mWebView.isInTouchMode()) {
+            return mDrawCursorRing && !mFocusedNode.mEditable;
+        }
+        if (mFocusedNode.mHasFocus && mFocusedNode.mEditable) {
+            return false;
+        }
+        long delay = System.currentTimeMillis() - mTouchHighlightRequested;
+        if (delay < ViewConfiguration.getTapTimeout()) {
+            Rect r = mTouchHighlightRegion.getBounds();
+            mWebView.postInvalidateDelayed(delay, r.left, r.top, r.right, r.bottom);
+            return false;
+        }
+        return true;
+    }
+
+
+    private FocusTransitionDrawable mFocusTransition = null;
+    static class FocusTransitionDrawable extends Drawable {
+        Region mPreviousRegion;
+        Region mNewRegion;
+        float mProgress = 0;
+        WebViewClassic mWebView;
+        Paint mPaint;
+        int mMaxAlpha;
+        Point mTranslate;
+
+        public FocusTransitionDrawable(WebViewClassic view) {
+            mWebView = view;
+            mPaint = new Paint(mWebView.mTouchHightlightPaint);
+            mMaxAlpha = mPaint.getAlpha();
+        }
+
+        @Override
+        public void setColorFilter(ColorFilter cf) {
+        }
+
+        @Override
+        public void setAlpha(int alpha) {
+        }
+
+        @Override
+        public int getOpacity() {
+            return 0;
+        }
+
+        public void setProgress(float p) {
+            mProgress = p;
+            if (mWebView.mFocusTransition == this) {
+                if (mProgress == 1f)
+                    mWebView.mFocusTransition = null;
+                mWebView.invalidate();
+            }
+        }
+
+        public float getProgress() {
+            return mProgress;
+        }
+
+        @Override
+        public void draw(Canvas canvas) {
+            if (mTranslate == null) {
+                Rect bounds = mPreviousRegion.getBounds();
+                Point from = new Point(bounds.centerX(), bounds.centerY());
+                mNewRegion.getBounds(bounds);
+                Point to = new Point(bounds.centerX(), bounds.centerY());
+                mTranslate = new Point(from.x - to.x, from.y - to.y);
+            }
+            int alpha = (int) (mProgress * mMaxAlpha);
+            RegionIterator iter = new RegionIterator(mPreviousRegion);
+            Rect r = new Rect();
+            mPaint.setAlpha(mMaxAlpha - alpha);
+            float tx = mTranslate.x * mProgress;
+            float ty = mTranslate.y * mProgress;
+            int save = canvas.save(Canvas.MATRIX_SAVE_FLAG);
+            canvas.translate(-tx, -ty);
+            while (iter.next(r)) {
+                canvas.drawRect(r, mPaint);
+            }
+            canvas.restoreToCount(save);
+            iter = new RegionIterator(mNewRegion);
+            r = new Rect();
+            mPaint.setAlpha(alpha);
+            save = canvas.save(Canvas.MATRIX_SAVE_FLAG);
+            tx = mTranslate.x - tx;
+            ty = mTranslate.y - ty;
+            canvas.translate(tx, ty);
+            while (iter.next(r)) {
+                canvas.drawRect(r, mPaint);
+            }
+            canvas.restoreToCount(save);
+        }
+    };
+
+    private boolean shouldAnimateTo(WebKitHitTest hit) {
+        // TODO: Don't be annoying or throw out the animation entirely
+        return false;
+    }
+
+    private void setTouchHighlightRects(WebKitHitTest hit) {
+        FocusTransitionDrawable transition = null;
+        if (shouldAnimateTo(hit)) {
+            transition = new FocusTransitionDrawable(this);
+        }
+        Rect[] rects = hit != null ? hit.mTouchRects : null;
+        if (!mTouchHighlightRegion.isEmpty()) {
+            mWebView.invalidate(mTouchHighlightRegion.getBounds());
+            if (transition != null) {
+                transition.mPreviousRegion = new Region(mTouchHighlightRegion);
+            }
+            mTouchHighlightRegion.setEmpty();
+        }
+        if (rects != null) {
+            mTouchHightlightPaint.setColor(hit.mTapHighlightColor);
+            for (Rect rect : rects) {
+                Rect viewRect = contentToViewRect(rect);
+                // some sites, like stories in nytimes.com, set
+                // mouse event handler in the top div. It is not
+                // user friendly to highlight the div if it covers
+                // more than half of the screen.
+                if (viewRect.width() < getWidth() >> 1
+                        || viewRect.height() < getHeight() >> 1) {
+                    mTouchHighlightRegion.union(viewRect);
+                } else {
+                    Log.w(LOGTAG, "Skip the huge selection rect:"
+                            + viewRect);
+                }
+            }
+            mWebView.invalidate(mTouchHighlightRegion.getBounds());
+            if (transition != null && transition.mPreviousRegion != null) {
+                transition.mNewRegion = new Region(mTouchHighlightRegion);
+                mFocusTransition = transition;
+                ObjectAnimator animator = ObjectAnimator.ofFloat(
+                        mFocusTransition, "progress", 1f);
+                animator.start();
+            }
+        }
+    }
+
+    // Interface to allow the profiled WebView to hook the page swap notifications.
+    public interface PageSwapDelegate {
+        void onPageSwapOccurred(boolean notifyAnimationStarted);
+    }
+
+    /** @hide Called by JNI when pages are swapped (only occurs with hardware
+     * acceleration) */
+    protected void pageSwapCallback(boolean notifyAnimationStarted) {
+        mWebViewCore.resumeWebKitDraw();
+        if (notifyAnimationStarted) {
+            mWebViewCore.sendMessage(EventHub.NOTIFY_ANIMATION_STARTED);
+        }
+        if (mWebView instanceof PageSwapDelegate) {
+            // This provides a hook for ProfiledWebView to observe the tile page swaps.
+            ((PageSwapDelegate) mWebView).onPageSwapOccurred(notifyAnimationStarted);
+        }
+    }
+
+    void setNewPicture(final WebViewCore.DrawData draw, boolean updateBaseLayer) {
+        if (mNativeClass == 0) {
+            if (mDelaySetPicture != null) {
+                throw new IllegalStateException("Tried to setNewPicture with"
+                        + " a delay picture already set! (memory leak)");
+            }
+            // Not initialized yet, delay set
+            mDelaySetPicture = draw;
+            return;
+        }
+        WebViewCore.ViewState viewState = draw.mViewState;
+        boolean isPictureAfterFirstLayout = viewState != null;
+
+        if (updateBaseLayer) {
+            setBaseLayer(draw.mBaseLayer, draw.mInvalRegion,
+                    getSettings().getShowVisualIndicator(),
+                    isPictureAfterFirstLayout);
+        }
+        final Point viewSize = draw.mViewSize;
+        // We update the layout (i.e. request a layout from the
+        // view system) if the last view size that we sent to
+        // WebCore matches the view size of the picture we just
+        // received in the fixed dimension.
+        final boolean updateLayout = viewSize.x == mLastWidthSent
+                && viewSize.y == mLastHeightSent;
+        // Don't send scroll event for picture coming from webkit,
+        // since the new picture may cause a scroll event to override
+        // the saved history scroll position.
+        mSendScrollEvent = false;
+        recordNewContentSize(draw.mContentSize.x,
+                draw.mContentSize.y, updateLayout);
+        if (isPictureAfterFirstLayout) {
+            // Reset the last sent data here since dealing with new page.
+            mLastWidthSent = 0;
+            mZoomManager.onFirstLayout(draw);
+            int scrollX = viewState.mShouldStartScrolledRight
+                    ? getContentWidth() : viewState.mScrollX;
+            int scrollY = viewState.mScrollY;
+            setContentScrollTo(scrollX, scrollY);
+            if (!mDrawHistory) {
+                // As we are on a new page, hide the keyboard
+                hideSoftKeyboard();
+            }
+        }
+        mSendScrollEvent = true;
+
+        if (DebugFlags.WEB_VIEW) {
+            Rect b = draw.mInvalRegion.getBounds();
+            Log.v(LOGTAG, "NEW_PICTURE_MSG_ID {" +
+                    b.left+","+b.top+","+b.right+","+b.bottom+"}");
+        }
+        invalidateContentRect(draw.mInvalRegion.getBounds());
+
+        if (mPictureListener != null) {
+            mPictureListener.onNewPicture(getWebView(), capturePicture());
+        }
+
+        // update the zoom information based on the new picture
+        mZoomManager.onNewPicture(draw);
+
+        if (isPictureAfterFirstLayout) {
+            mViewManager.postReadyToDrawAll();
+        }
+    }
+
+    /**
+     * Used when receiving messages for REQUEST_KEYBOARD_WITH_SELECTION_MSG_ID
+     * and UPDATE_TEXT_SELECTION_MSG_ID.
+     */
+    private void updateTextSelectionFromMessage(int nodePointer,
+            int textGeneration, WebViewCore.TextSelectionData data) {
+        if (textGeneration == mTextGeneration) {
+            if (mInputConnection != null && mFieldPointer == nodePointer) {
+                mInputConnection.setSelection(data.mStart, data.mEnd);
+            }
+        }
+        nativeSetTextSelection(mNativeClass, data.mSelectTextPtr);
+
+        if (data.mSelectTextPtr != 0 &&
+                (data.mStart != data.mEnd ||
+                (mFieldPointer == nodePointer && mFieldPointer != 0))) {
+            mIsCaretSelection = (data.mStart == data.mEnd);
+            if (!mSelectingText) {
+                setupWebkitSelect();
+            } else if (!mSelectionStarted) {
+                syncSelectionCursors();
+            }
+            if (mIsCaretSelection) {
+                resetCaretTimer();
+            }
+        } else {
+            selectionDone();
+        }
+        invalidate();
+    }
+
+    // Class used to use a dropdown for a <select> element
+    private class InvokeListBox implements Runnable {
+        // Whether the listbox allows multiple selection.
+        private boolean     mMultiple;
+        // Passed in to a list with multiple selection to tell
+        // which items are selected.
+        private int[]       mSelectedArray;
+        // Passed in to a list with single selection to tell
+        // where the initial selection is.
+        private int         mSelection;
+
+        private Container[] mContainers;
+
+        // Need these to provide stable ids to my ArrayAdapter,
+        // which normally does not have stable ids. (Bug 1250098)
+        private class Container extends Object {
+            /**
+             * Possible values for mEnabled.  Keep in sync with OptionStatus in
+             * WebViewCore.cpp
+             */
+            final static int OPTGROUP = -1;
+            final static int OPTION_DISABLED = 0;
+            final static int OPTION_ENABLED = 1;
+
+            String  mString;
+            int     mEnabled;
+            int     mId;
+
+            @Override
+            public String toString() {
+                return mString;
+            }
+        }
+
+        /**
+         *  Subclass ArrayAdapter so we can disable OptionGroupLabels,
+         *  and allow filtering.
+         */
+        private class MyArrayListAdapter extends ArrayAdapter<Container> {
+            public MyArrayListAdapter() {
+                super(WebViewClassic.this.mContext,
+                        mMultiple ? com.android.internal.R.layout.select_dialog_multichoice :
+                        com.android.internal.R.layout.webview_select_singlechoice,
+                        mContainers);
+            }
+
+            @Override
+            public View getView(int position, View convertView,
+                    ViewGroup parent) {
+                // Always pass in null so that we will get a new CheckedTextView
+                // Otherwise, an item which was previously used as an <optgroup>
+                // element (i.e. has no check), could get used as an <option>
+                // element, which needs a checkbox/radio, but it would not have
+                // one.
+                convertView = super.getView(position, null, parent);
+                Container c = item(position);
+                if (c != null && Container.OPTION_ENABLED != c.mEnabled) {
+                    // ListView does not draw dividers between disabled and
+                    // enabled elements.  Use a LinearLayout to provide dividers
+                    LinearLayout layout = new LinearLayout(mContext);
+                    layout.setOrientation(LinearLayout.VERTICAL);
+                    if (position > 0) {
+                        View dividerTop = new View(mContext);
+                        dividerTop.setBackgroundResource(
+                                android.R.drawable.divider_horizontal_bright);
+                        layout.addView(dividerTop);
+                    }
+
+                    if (Container.OPTGROUP == c.mEnabled) {
+                        // Currently select_dialog_multichoice uses CheckedTextViews.
+                        // If that changes, the class cast will no longer be valid.
+                        if (mMultiple) {
+                            Assert.assertTrue(convertView instanceof CheckedTextView);
+                            ((CheckedTextView) convertView).setCheckMarkDrawable(null);
+                        }
+                    } else {
+                        // c.mEnabled == Container.OPTION_DISABLED
+                        // Draw the disabled element in a disabled state.
+                        convertView.setEnabled(false);
+                    }
+
+                    layout.addView(convertView);
+                    if (position < getCount() - 1) {
+                        View dividerBottom = new View(mContext);
+                        dividerBottom.setBackgroundResource(
+                                android.R.drawable.divider_horizontal_bright);
+                        layout.addView(dividerBottom);
+                    }
+                    return layout;
+                }
+                return convertView;
+            }
+
+            @Override
+            public boolean hasStableIds() {
+                // AdapterView's onChanged method uses this to determine whether
+                // to restore the old state.  Return false so that the old (out
+                // of date) state does not replace the new, valid state.
+                return false;
+            }
+
+            private Container item(int position) {
+                if (position < 0 || position >= getCount()) {
+                    return null;
+                }
+                return getItem(position);
+            }
+
+            @Override
+            public long getItemId(int position) {
+                Container item = item(position);
+                if (item == null) {
+                    return -1;
+                }
+                return item.mId;
+            }
+
+            @Override
+            public boolean areAllItemsEnabled() {
+                return false;
+            }
+
+            @Override
+            public boolean isEnabled(int position) {
+                Container item = item(position);
+                if (item == null) {
+                    return false;
+                }
+                return Container.OPTION_ENABLED == item.mEnabled;
+            }
+        }
+
+        private InvokeListBox(String[] array, int[] enabled, int[] selected) {
+            mMultiple = true;
+            mSelectedArray = selected;
+
+            int length = array.length;
+            mContainers = new Container[length];
+            for (int i = 0; i < length; i++) {
+                mContainers[i] = new Container();
+                mContainers[i].mString = array[i];
+                mContainers[i].mEnabled = enabled[i];
+                mContainers[i].mId = i;
+            }
+        }
+
+        private InvokeListBox(String[] array, int[] enabled, int selection) {
+            mSelection = selection;
+            mMultiple = false;
+
+            int length = array.length;
+            mContainers = new Container[length];
+            for (int i = 0; i < length; i++) {
+                mContainers[i] = new Container();
+                mContainers[i].mString = array[i];
+                mContainers[i].mEnabled = enabled[i];
+                mContainers[i].mId = i;
+            }
+        }
+
+        /*
+         * Whenever the data set changes due to filtering, this class ensures
+         * that the checked item remains checked.
+         */
+        private class SingleDataSetObserver extends DataSetObserver {
+            private long        mCheckedId;
+            private ListView    mListView;
+            private Adapter     mAdapter;
+
+            /*
+             * Create a new observer.
+             * @param id The ID of the item to keep checked.
+             * @param l ListView for getting and clearing the checked states
+             * @param a Adapter for getting the IDs
+             */
+            public SingleDataSetObserver(long id, ListView l, Adapter a) {
+                mCheckedId = id;
+                mListView = l;
+                mAdapter = a;
+            }
+
+            @Override
+            public void onChanged() {
+                // The filter may have changed which item is checked.  Find the
+                // item that the ListView thinks is checked.
+                int position = mListView.getCheckedItemPosition();
+                long id = mAdapter.getItemId(position);
+                if (mCheckedId != id) {
+                    // Clear the ListView's idea of the checked item, since
+                    // it is incorrect
+                    mListView.clearChoices();
+                    // Search for mCheckedId.  If it is in the filtered list,
+                    // mark it as checked
+                    int count = mAdapter.getCount();
+                    for (int i = 0; i < count; i++) {
+                        if (mAdapter.getItemId(i) == mCheckedId) {
+                            mListView.setItemChecked(i, true);
+                            break;
+                        }
+                    }
+                }
+            }
+        }
+
+        @Override
+        public void run() {
+            final ListView listView = (ListView) LayoutInflater.from(mContext)
+                    .inflate(com.android.internal.R.layout.select_dialog, null);
+            final MyArrayListAdapter adapter = new MyArrayListAdapter();
+            AlertDialog.Builder b = new AlertDialog.Builder(mContext)
+                    .setView(listView).setCancelable(true)
+                    .setInverseBackgroundForced(true);
+
+            if (mMultiple) {
+                b.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
+                    @Override
+                    public void onClick(DialogInterface dialog, int which) {
+                        mWebViewCore.sendMessage(
+                                EventHub.LISTBOX_CHOICES,
+                                adapter.getCount(), 0,
+                                listView.getCheckedItemPositions());
+                    }});
+                b.setNegativeButton(android.R.string.cancel,
+                        new DialogInterface.OnClickListener() {
+                    @Override
+                    public void onClick(DialogInterface dialog, int which) {
+                        mWebViewCore.sendMessage(
+                                EventHub.SINGLE_LISTBOX_CHOICE, -2, 0);
+                }});
+            }
+            mListBoxDialog = b.create();
+            listView.setAdapter(adapter);
+            listView.setFocusableInTouchMode(true);
+            // There is a bug (1250103) where the checks in a ListView with
+            // multiple items selected are associated with the positions, not
+            // the ids, so the items do not properly retain their checks when
+            // filtered.  Do not allow filtering on multiple lists until
+            // that bug is fixed.
+
+            listView.setTextFilterEnabled(!mMultiple);
+            if (mMultiple) {
+                listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
+                int length = mSelectedArray.length;
+                for (int i = 0; i < length; i++) {
+                    listView.setItemChecked(mSelectedArray[i], true);
+                }
+            } else {
+                listView.setOnItemClickListener(new OnItemClickListener() {
+                    @Override
+                    public void onItemClick(AdapterView<?> parent, View v,
+                            int position, long id) {
+                        // Rather than sending the message right away, send it
+                        // after the page regains focus.
+                        mListBoxMessage = Message.obtain(null,
+                                EventHub.SINGLE_LISTBOX_CHOICE, (int) id, 0);
+                        mListBoxDialog.dismiss();
+                        mListBoxDialog = null;
+                    }
+                });
+                if (mSelection != -1) {
+                    listView.setSelection(mSelection);
+                    listView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
+                    listView.setItemChecked(mSelection, true);
+                    DataSetObserver observer = new SingleDataSetObserver(
+                            adapter.getItemId(mSelection), listView, adapter);
+                    adapter.registerDataSetObserver(observer);
+                }
+            }
+            mListBoxDialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
+                @Override
+                public void onCancel(DialogInterface dialog) {
+                    mWebViewCore.sendMessage(
+                                EventHub.SINGLE_LISTBOX_CHOICE, -2, 0);
+                    mListBoxDialog = null;
+                }
+            });
+            mListBoxDialog.show();
+        }
+    }
+
+    private Message mListBoxMessage;
+
+    /*
+     * Request a dropdown menu for a listbox with multiple selection.
+     *
+     * @param array Labels for the listbox.
+     * @param enabledArray  State for each element in the list.  See static
+     *      integers in Container class.
+     * @param selectedArray Which positions are initally selected.
+     */
+    void requestListBox(String[] array, int[] enabledArray, int[]
+            selectedArray) {
+        mPrivateHandler.post(
+                new InvokeListBox(array, enabledArray, selectedArray));
+    }
+
+    /*
+     * Request a dropdown menu for a listbox with single selection or a single
+     * <select> element.
+     *
+     * @param array Labels for the listbox.
+     * @param enabledArray  State for each element in the list.  See static
+     *      integers in Container class.
+     * @param selection Which position is initally selected.
+     */
+    void requestListBox(String[] array, int[] enabledArray, int selection) {
+        mPrivateHandler.post(
+                new InvokeListBox(array, enabledArray, selection));
+    }
+
+    private int getScaledMaxXScroll() {
+        int width;
+        if (mHeightCanMeasure == false) {
+            width = getViewWidth() / 4;
+        } else {
+            Rect visRect = new Rect();
+            calcOurVisibleRect(visRect);
+            width = visRect.width() / 2;
+        }
+        // FIXME the divisor should be retrieved from somewhere
+        return viewToContentX(width);
+    }
+
+    private int getScaledMaxYScroll() {
+        int height;
+        if (mHeightCanMeasure == false) {
+            height = getViewHeight() / 4;
+        } else {
+            Rect visRect = new Rect();
+            calcOurVisibleRect(visRect);
+            height = visRect.height() / 2;
+        }
+        // FIXME the divisor should be retrieved from somewhere
+        // the closest thing today is hard-coded into ScrollView.java
+        // (from ScrollView.java, line 363)   int maxJump = height/2;
+        return Math.round(height * mZoomManager.getInvScale());
+    }
+
+    /**
+     * Called by JNI to invalidate view
+     */
+    private void viewInvalidate() {
+        invalidate();
+    }
+
+    /**
+     * Pass the key directly to the page.  This assumes that
+     * nativePageShouldHandleShiftAndArrows() returned true.
+     */
+    private void letPageHandleNavKey(int keyCode, long time, boolean down, int metaState) {
+        int keyEventAction;
+        if (down) {
+            keyEventAction = KeyEvent.ACTION_DOWN;
+        } else {
+            keyEventAction = KeyEvent.ACTION_UP;
+        }
+
+        KeyEvent event = new KeyEvent(time, time, keyEventAction, keyCode,
+                1, (metaState & KeyEvent.META_SHIFT_ON)
+                | (metaState & KeyEvent.META_ALT_ON)
+                | (metaState & KeyEvent.META_SYM_ON)
+                , KeyCharacterMap.VIRTUAL_KEYBOARD, 0, 0);
+        sendKeyEvent(event);
+    }
+
+    private void sendKeyEvent(KeyEvent event) {
+        int direction = 0;
+        switch (event.getKeyCode()) {
+        case KeyEvent.KEYCODE_DPAD_DOWN:
+            direction = View.FOCUS_DOWN;
+            break;
+        case KeyEvent.KEYCODE_DPAD_UP:
+            direction = View.FOCUS_UP;
+            break;
+        case KeyEvent.KEYCODE_DPAD_LEFT:
+            direction = View.FOCUS_LEFT;
+            break;
+        case KeyEvent.KEYCODE_DPAD_RIGHT:
+            direction = View.FOCUS_RIGHT;
+            break;
+        case KeyEvent.KEYCODE_TAB:
+            direction = event.isShiftPressed() ? View.FOCUS_BACKWARD : View.FOCUS_FORWARD;
+            break;
+        }
+        if (direction != 0 && mWebView.focusSearch(direction) == null) {
+            // Can't take focus in that direction
+            direction = 0;
+        }
+        int eventHubAction = EventHub.KEY_UP;
+        if (event.getAction() == KeyEvent.ACTION_DOWN) {
+            eventHubAction = EventHub.KEY_DOWN;
+            int sound = keyCodeToSoundsEffect(event.getKeyCode());
+            if (sound != 0) {
+                mWebView.playSoundEffect(sound);
+            }
+        }
+        mWebViewCore.sendMessage(eventHubAction, direction, event);
+    }
+
+    /**
+     * @return Whether accessibility script has been injected.
+     */
+    private boolean accessibilityScriptInjected() {
+        // TODO: Maybe the injected script should announce its presence in
+        // the page meta-tag so the nativePageShouldHandleShiftAndArrows
+        // will check that as one of the conditions it looks for
+        return mAccessibilityScriptInjected;
+    }
+
+    /**
+     * See {@link WebView#setBackgroundColor(int)}
+     */
+    @Override
+    public void setBackgroundColor(int color) {
+        mBackgroundColor = color;
+        mWebViewCore.sendMessage(EventHub.SET_BACKGROUND_COLOR, color);
+    }
+
+    /**
+     * See {@link WebView#debugDump()}
+     */
+    @Override
+    @Deprecated
+    public void debugDump() {
+    }
+
+    /**
+     * Draw the HTML page into the specified canvas. This call ignores any
+     * view-specific zoom, scroll offset, or other changes. It does not draw
+     * any view-specific chrome, such as progress or URL bars.
+     *
+     * @hide only needs to be accessible to Browser and testing
+     */
+    public void drawPage(Canvas canvas) {
+        calcOurContentVisibleRectF(mVisibleContentRect);
+        nativeDraw(canvas, mVisibleContentRect, 0, 0, false);
+    }
+
+    /**
+     * Enable the communication b/t the webView and VideoViewProxy
+     *
+     * @hide only used by the Browser
+     */
+    public void setHTML5VideoViewProxy(HTML5VideoViewProxy proxy) {
+        mHTML5VideoViewProxy = proxy;
+    }
+
+    /**
+     * Set the time to wait between passing touches to WebCore. See also the
+     * TOUCH_SENT_INTERVAL member for further discussion.
+     *
+     * @hide This is only used by the DRT test application.
+     */
+    public void setTouchInterval(int interval) {
+        mCurrentTouchInterval = interval;
+    }
+
+    /**
+     * Copy text into the clipboard. This is called indirectly from
+     * WebViewCore.
+     * @param text The text to put into the clipboard.
+     */
+    private void copyToClipboard(String text) {
+        ClipboardManager cm = (ClipboardManager)mContext
+                .getSystemService(Context.CLIPBOARD_SERVICE);
+        ClipData clip = ClipData.newPlainText(getTitle(), text);
+        cm.setPrimaryClip(clip);
+    }
+
+    /*package*/ void autoFillForm(int autoFillQueryId) {
+        mWebViewCore.sendMessage(EventHub.AUTOFILL_FORM, autoFillQueryId, /* unused */0);
+    }
+
+    /* package */ ViewManager getViewManager() {
+        return mViewManager;
+    }
+
+    private static void checkThread() {
+        if (Looper.myLooper() != Looper.getMainLooper()) {
+            Throwable throwable = new Throwable(
+                    "Warning: A WebView method was called on thread '" +
+                    Thread.currentThread().getName() + "'. " +
+                    "All WebView methods must be called on the UI thread. " +
+                    "Future versions of WebView may not support use on other threads.");
+            Log.w(LOGTAG, Log.getStackTraceString(throwable));
+            StrictMode.onWebViewMethodCalledOnWrongThread(throwable);
+        }
+    }
+
+    /** @hide send content invalidate */
+    protected void contentInvalidateAll() {
+        if (mWebViewCore != null && !mBlockWebkitViewMessages) {
+            mWebViewCore.sendMessage(EventHub.CONTENT_INVALIDATE_ALL);
+        }
+    }
+
+    /** @hide discard all textures from tiles. Used in Profiled WebView */
+    public void discardAllTextures() {
+        nativeDiscardAllTextures();
+    }
+
+    /**
+     * Begin collecting per-tile profiling data
+     *
+     * @hide only used by profiling tests
+     */
+    public void tileProfilingStart() {
+        nativeTileProfilingStart();
+    }
+    /**
+     * Return per-tile profiling data
+     *
+     * @hide only used by profiling tests
+     */
+    public float tileProfilingStop() {
+        return nativeTileProfilingStop();
+    }
+
+    /** @hide only used by profiling tests */
+    public void tileProfilingClear() {
+        nativeTileProfilingClear();
+    }
+    /** @hide only used by profiling tests */
+    public int tileProfilingNumFrames() {
+        return nativeTileProfilingNumFrames();
+    }
+    /** @hide only used by profiling tests */
+    public int tileProfilingNumTilesInFrame(int frame) {
+        return nativeTileProfilingNumTilesInFrame(frame);
+    }
+    /** @hide only used by profiling tests */
+    public int tileProfilingGetInt(int frame, int tile, String key) {
+        return nativeTileProfilingGetInt(frame, tile, key);
+    }
+    /** @hide only used by profiling tests */
+    public float tileProfilingGetFloat(int frame, int tile, String key) {
+        return nativeTileProfilingGetFloat(frame, tile, key);
+    }
+
+    /**
+     * Checks the focused content for an editable text field. This can be
+     * text input or ContentEditable.
+     * @return true if the focused item is an editable text field.
+     */
+    boolean focusCandidateIsEditableText() {
+        if (mFocusedNode != null) {
+            return mFocusedNode.mEditable;
+        }
+        return false;
+    }
+
+    // Called via JNI
+    private void postInvalidate() {
+        mWebView.postInvalidate();
+    }
+
+    private native void     nativeCreate(int ptr, String drawableDir, boolean isHighEndGfx);
+    private native void     nativeDebugDump();
+    private native void     nativeDestroy();
+
+    /**
+     * Draw the picture set with a background color and extra. If
+     * "splitIfNeeded" is true and the return value is not 0, the return value
+     * MUST be passed to WebViewCore with SPLIT_PICTURE_SET message so that the
+     * native allocation can be freed.
+     */
+    private native int nativeDraw(Canvas canvas, RectF visibleRect,
+            int color, int extra, boolean splitIfNeeded);
+    private native void     nativeDumpDisplayTree(String urlOrNull);
+    private native boolean  nativeEvaluateLayersAnimations(int nativeInstance);
+    private native int      nativeGetDrawGLFunction(int nativeInstance, Rect rect,
+            Rect viewRect, RectF visibleRect, float scale, int extras);
+    private native void     nativeUpdateDrawGLFunction(Rect rect, Rect viewRect,
+            RectF visibleRect, float scale);
+    private native String   nativeGetSelection();
+    private native Rect     nativeLayerBounds(int layer);
+    private native void     nativeSetHeightCanMeasure(boolean measure);
+    private native boolean  nativeSetBaseLayer(int nativeInstance,
+            int layer, Region invalRegion,
+            boolean showVisualIndicator, boolean isPictureAfterFirstLayout);
+    private native int      nativeGetBaseLayer();
+    private native void     nativeReplaceBaseContent(int content);
+    private native void     nativeCopyBaseContentToPicture(Picture pict);
+    private native boolean  nativeHasContent();
+    private native void     nativeStopGL();
+    private native Rect     nativeSubtractLayers(Rect content);
+    private native void     nativeDiscardAllTextures();
+    private native void     nativeTileProfilingStart();
+    private native float    nativeTileProfilingStop();
+    private native void     nativeTileProfilingClear();
+    private native int      nativeTileProfilingNumFrames();
+    private native int      nativeTileProfilingNumTilesInFrame(int frame);
+    private native int      nativeTileProfilingGetInt(int frame, int tile, String key);
+    private native float    nativeTileProfilingGetFloat(int frame, int tile, String key);
+
+    private native void     nativeUseHardwareAccelSkia(boolean enabled);
+
+    // Returns a pointer to the scrollable LayerAndroid at the given point.
+    private native int      nativeScrollableLayer(int x, int y, Rect scrollRect,
+            Rect scrollBounds);
+    /**
+     * Scroll the specified layer.
+     * @param layer Id of the layer to scroll, as determined by nativeScrollableLayer.
+     * @param newX Destination x position to which to scroll.
+     * @param newY Destination y position to which to scroll.
+     * @return True if the layer is successfully scrolled.
+     */
+    private native boolean  nativeScrollLayer(int layer, int newX, int newY);
+    private native void     nativeSetIsScrolling(boolean isScrolling);
+    private native int      nativeGetBackgroundColor();
+    native boolean  nativeSetProperty(String key, String value);
+    native String   nativeGetProperty(String key);
+    /**
+     * See {@link ComponentCallbacks2} for the trim levels and descriptions
+     */
+    private static native void     nativeOnTrimMemory(int level);
+    private static native void nativeSetPauseDrawing(int instance, boolean pause);
+    private static native void nativeSetTextSelection(int instance, int selection);
+    private static native int nativeGetHandleLayerId(int instance, int handle,
+            Rect cursorLocation);
+    private static native boolean nativeIsBaseFirst(int instance);
+}
diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java
index 93fd92b..09aa286c 100644
--- a/core/java/android/webkit/WebViewCore.java
+++ b/core/java/android/webkit/WebViewCore.java
@@ -39,7 +39,7 @@
 import android.view.MotionEvent;
 import android.view.SurfaceView;
 import android.view.View;
-import android.webkit.WebView.FocusNodeHref;
+import android.webkit.WebViewClassic.FocusNodeHref;
 
 import junit.framework.Assert;
 
@@ -72,11 +72,12 @@
      */
 
     // The WebView that corresponds to this WebViewCore.
-    private WebView mWebView;
+    // TODO: rename this field (and its getter) to mWebViewClassic or  mWebViewImpl.
+    private WebViewClassic mWebView;
     // Proxy for handling callbacks from native code
     private final CallbackProxy mCallbackProxy;
     // Settings object for maintaining all settings
-    private final WebSettings mSettings;
+    private final WebSettingsClassic mSettings;
     // Context for initializing the BrowserFrame with the proper assets.
     private final Context mContext;
     // The pointer to a native view object.
@@ -138,11 +139,13 @@
     private int mHighMemoryUsageThresholdMb;
     private int mHighUsageDeltaMb;
 
+    private int mChromeCanFocusDirection;
+
     // The thread name used to identify the WebCore thread and for use in
     // debugging other classes that require operation within the WebCore thread.
     /* package */ static final String THREAD_NAME = "WebViewCoreThread";
 
-    public WebViewCore(Context context, WebView w, CallbackProxy proxy,
+    public WebViewCore(Context context, WebViewClassic w, CallbackProxy proxy,
             Map<String, Object> javascriptInterfaces) {
         // No need to assign this in the WebCore thread.
         mCallbackProxy = proxy;
@@ -179,7 +182,7 @@
         // ready.
         mEventHub = new EventHub();
         // Create a WebSettings object for maintaining all settings
-        mSettings = new WebSettings(mContext, mWebView);
+        mSettings = new WebSettingsClassic(mContext, mWebView);
         // The WebIconDatabase needs to be initialized within the UI thread so
         // just request the instance here.
         WebIconDatabase.getInstance();
@@ -234,7 +237,7 @@
         // WebCore thread.
         if (mWebView != null) {
             Message.obtain(mWebView.mPrivateHandler,
-                    WebView.WEBCORE_INITIALIZED_MSG_ID,
+                    WebViewClassic.WEBCORE_INITIALIZED_MSG_ID,
                     mNativeClass, 0).sendToTarget();
         }
 
@@ -284,7 +287,7 @@
         BrowserFrame.sJavaBridge.resume();
     }
 
-    public WebSettings getSettings() {
+    public WebSettingsClassic getSettings() {
         return mSettings;
     }
 
@@ -329,7 +332,7 @@
      */
     private void formDidBlur(int nodePointer) {
         if (mWebView == null) return;
-        Message.obtain(mWebView.mPrivateHandler, WebView.FORM_DID_BLUR,
+        Message.obtain(mWebView.mPrivateHandler, WebViewClassic.FORM_DID_BLUR,
                 nodePointer, 0).sendToTarget();
     }
 
@@ -338,11 +341,63 @@
      */
     private void focusNodeChanged(WebKitHitTest hitTest) {
         if (mWebView == null) return;
-        mWebView.mPrivateHandler.obtainMessage(WebView.HIT_TEST_RESULT, hitTest)
+        mWebView.mPrivateHandler.obtainMessage(WebViewClassic.HIT_TEST_RESULT, hitTest)
                 .sendToTarget();
     }
 
     /**
+     * Called by JNI to advance focus to the next view.
+     */
+    private void chromeTakeFocus(int webkitDirection) {
+        if (mWebView == null) return;
+        Message m = mWebView.mPrivateHandler.obtainMessage(
+                WebViewClassic.TAKE_FOCUS);
+        m.arg1 = mapDirection(webkitDirection);
+        m.sendToTarget();
+    }
+
+    /**
+     * Called by JNI to see if we can take focus in the given direction.
+     */
+    private boolean chromeCanTakeFocus(int webkitDirection) {
+        int direction = mapDirection(webkitDirection);
+        return direction == mChromeCanFocusDirection && direction != 0;
+    }
+
+    /**
+     * Maps a Webkit focus direction to a framework one
+     */
+    private int mapDirection(int webkitDirection) {
+        /*
+         * This is WebKit's FocusDirection enum (from FocusDirection.h)
+        enum FocusDirection {
+            FocusDirectionNone = 0,
+            FocusDirectionForward,
+            FocusDirectionBackward,
+            FocusDirectionUp,
+            FocusDirectionDown,
+            FocusDirectionLeft,
+            FocusDirectionRight
+        };
+         */
+        switch (webkitDirection) {
+        case 1:
+            return View.FOCUS_FORWARD;
+        case 2:
+            return View.FOCUS_BACKWARD;
+        case 3:
+            return View.FOCUS_UP;
+        case 4:
+            return View.FOCUS_DOWN;
+        case 5:
+            return View.FOCUS_LEFT;
+        case 6:
+            return View.FOCUS_RIGHT;
+        }
+        return 0;
+    }
+
+    /**
      * Called by JNI.  Open a file chooser to upload a file.
      * @param acceptType The value of the 'accept' attribute of the
      *         input tag associated with this file picker.
@@ -508,7 +563,7 @@
     protected void enterFullscreenForVideoLayer(int layerId, String url) {
         if (mWebView == null) return;
         Message message = Message.obtain(mWebView.mPrivateHandler,
-                       WebView.ENTER_FULLSCREEN_VIDEO, layerId, 0);
+                       WebViewClassic.ENTER_FULLSCREEN_VIDEO, layerId, 0);
         message.obj = url;
         message.sendToTarget();
     }
@@ -520,7 +575,7 @@
     protected void exitFullscreenVideo() {
         if (mWebView == null) return;
         Message message = Message.obtain(mWebView.mPrivateHandler,
-                       WebView.EXIT_FULLSCREEN_VIDEO);
+                       WebViewClassic.EXIT_FULLSCREEN_VIDEO);
         message.sendToTarget();
     }
 
@@ -609,15 +664,9 @@
     private native void nativeSetFocusControllerActive(int nativeClass,
             boolean active);
 
-    private native void nativeSaveDocumentState(int nativeClass, int frame);
+    private native void nativeSaveDocumentState(int nativeClass);
 
-    private native void nativeMoveFocus(int nativeClass, int framePtr,
-            int nodePointer);
-    private native void nativeMoveMouse(int nativeClass, int framePtr, int x,
-            int y);
-
-    private native void nativeMoveMouseIfLatest(int nativeClass,
-            int moveGeneration, int framePtr, int x, int y);
+    private native void nativeMoveMouse(int nativeClass, int x, int y);
 
     private native String nativeRetrieveHref(int nativeClass, int x, int y);
     private native String nativeRetrieveAnchorText(int nativeClass,
@@ -631,16 +680,12 @@
             int[] idArray, int[] xArray, int[] yArray, int count,
             int actionIndex, int metaState);
 
-    private native void nativeUpdateFrameCache(int nativeClass);
-
     private native void nativeSetBackgroundColor(int nativeClass, int color);
 
     private native void nativeDumpDomTree(int nativeClass, boolean useFile);
 
     private native void nativeDumpRenderTree(int nativeClass, boolean useFile);
 
-    private native void nativeDumpNavTree(int nativeClass);
-
     private native void nativeSetJsFlags(int nativeClass, String flags);
 
     /**
@@ -798,21 +843,6 @@
         String mHistoryUrl;
     }
 
-    static class CursorData {
-        CursorData() {}
-        CursorData(int frame, int node, int x, int y) {
-            mFrame = frame;
-            mNode = node;
-            mX = x;
-            mY = y;
-        }
-        int mMoveGeneration;
-        int mFrame;
-        int mNode;
-        int mX;
-        int mY;
-    }
-
     static class JSInterfaceData {
         Object mObject;
         String mInterfaceName;
@@ -886,7 +916,7 @@
         String mTitle;
         Rect[] mTouchRects;
         boolean mEditable;
-        int mTapHighlightColor = WebView.HIGHLIGHT_COLOR;
+        int mTapHighlightColor = WebViewClassic.HIGHLIGHT_COLOR;
         Rect[] mEnclosingParentRects;
         boolean mHasFocus;
 
@@ -969,8 +999,8 @@
 
         static final String[] HandlerDebugString = {
             "REVEAL_SELECTION", // 96
-            "REQUEST_LABEL", // 97
-            "UPDATE_FRAME_CACHE_IF_LOADING", // = 98
+            "", // 97
+            "", // = 98
             "SCROLL_TEXT_INPUT", // = 99
             "LOAD_URL", // = 100;
             "STOP_LOADING", // = 101;
@@ -989,7 +1019,7 @@
             "REPLACE_TEXT", // = 114;
             "PASS_TO_JS", // = 115;
             "SET_GLOBAL_BOUNDS", // = 116;
-            "UPDATE_CACHE_AND_TEXT_ENTRY", // = 117;
+            "", // = 117;
             "CLICK", // = 118;
             "SET_NETWORK_STATE", // = 119;
             "DOC_HAS_IMAGES", // = 120;
@@ -1007,8 +1037,8 @@
             "POST_URL", // = 132;
             "SPLIT_PICTURE_SET", // = 133;
             "CLEAR_CONTENT", // = 134;
-            "SET_MOVE_MOUSE", // = 135;
-            "SET_MOVE_MOUSE_IF_LATEST", // = 136;
+            "", // = 135;
+            "", // = 136;
             "REQUEST_CURSOR_HREF", // = 137;
             "ADD_JS_INTERFACE", // = 138;
             "LOAD_DATA", // = 139;
@@ -1039,8 +1069,6 @@
     public class EventHub {
         // Message Ids
         static final int REVEAL_SELECTION = 96;
-        static final int REQUEST_LABEL = 97;
-        static final int UPDATE_FRAME_CACHE_IF_LOADING = 98;
         static final int SCROLL_TEXT_INPUT = 99;
         static final int LOAD_URL = 100;
         static final int STOP_LOADING = 101;
@@ -1059,7 +1087,6 @@
         static final int REPLACE_TEXT = 114;
         static final int PASS_TO_JS = 115;
         static final int SET_GLOBAL_BOUNDS = 116;
-        static final int UPDATE_CACHE_AND_TEXT_ENTRY = 117;
         static final int CLICK = 118;
         static final int SET_NETWORK_STATE = 119;
         static final int DOC_HAS_IMAGES = 120;
@@ -1069,7 +1096,6 @@
         static final int SINGLE_LISTBOX_CHOICE = 124;
         public static final int MESSAGE_RELAY = 125;
         static final int SET_BACKGROUND_COLOR = 126;
-        static final int SET_MOVE_FOCUS = 127;
         static final int SAVE_DOCUMENT_STATE = 128;
         static final int DELETE_SURROUNDING_TEXT = 129;
 
@@ -1081,7 +1107,6 @@
 
         // UI nav messages
         static final int SET_MOVE_MOUSE = 135;
-        static final int SET_MOVE_MOUSE_IF_LATEST = 136;
         static final int REQUEST_CURSOR_HREF = 137;
         static final int ADD_JS_INTERFACE = 138;
         static final int LOAD_DATA = 139;
@@ -1101,7 +1126,6 @@
         static final int ON_PAUSE = 143;
         static final int ON_RESUME = 144;
         static final int FREE_MEMORY = 145;
-        static final int VALID_NODE_BOUNDS = 146;
 
         // Load and save web archives
         static final int SAVE_WEBARCHIVE = 147;
@@ -1121,7 +1145,6 @@
         // debugging
         static final int DUMP_DOMTREE = 170;
         static final int DUMP_RENDERTREE = 171;
-        static final int DUMP_NAVTREE = 172;
 
         static final int SET_JS_FLAGS = 174;
         static final int CONTENT_INVALIDATE_ALL = 175;
@@ -1200,7 +1223,7 @@
         private EventHub() {}
 
         private static final int FIRST_PACKAGE_MSG_ID = REVEAL_SELECTION;
-        private static final int LAST_PACKAGE_MSG_ID = VALID_NODE_BOUNDS;
+        private static final int LAST_PACKAGE_MSG_ID = REMOVE_JS_INTERFACE;
 
         /**
          * Transfer all messages to the newly created webcore thread handler.
@@ -1251,6 +1274,12 @@
                             // Time to take down the world. Cancel all pending
                             // loads and destroy the native view and frame.
                             synchronized (WebViewCore.this) {
+                                mCallbackProxy.shutdown();
+                                // Wake up the WebCore thread just in case it is waiting for a
+                                // JavaScript dialog.
+                                synchronized (mCallbackProxy) {
+                                    mCallbackProxy.notify();
+                                }
                                 mBrowserFrame.destroy();
                                 mBrowserFrame = null;
                                 mSettings.onDestroyed();
@@ -1263,23 +1292,6 @@
                             nativeRevealSelection(mNativeClass);
                             break;
 
-                        case REQUEST_LABEL:
-                            if (mWebView != null) {
-                                int nodePointer = msg.arg2;
-                                String label = nativeRequestLabel(mNativeClass,
-                                        msg.arg1, nodePointer);
-                                if (label != null && label.length() > 0) {
-                                    Message.obtain(mWebView.mPrivateHandler,
-                                            WebView.RETURN_LABEL, nodePointer,
-                                            0, label).sendToTarget();
-                                }
-                            }
-                            break;
-
-                        case UPDATE_FRAME_CACHE_IF_LOADING:
-                            nativeUpdateFrameCacheIfLoading(mNativeClass);
-                            break;
-
                         case SCROLL_TEXT_INPUT:
                             float xPercent;
                             if (msg.obj == null) {
@@ -1353,11 +1365,11 @@
                             break;
 
                         case KEY_DOWN:
-                            key((KeyEvent) msg.obj, true);
+                            key((KeyEvent) msg.obj, msg.arg1, true);
                             break;
 
                         case KEY_UP:
-                            key((KeyEvent) msg.obj, false);
+                            key((KeyEvent) msg.obj, msg.arg1, false);
                             break;
 
                         case KEY_PRESS:
@@ -1373,15 +1385,15 @@
                             break;
 
                         case VIEW_SIZE_CHANGED: {
-                            viewSizeChanged((WebView.ViewSizeData) msg.obj);
+                            viewSizeChanged((WebViewClassic.ViewSizeData) msg.obj);
                             break;
                         }
                         case SET_SCROLL_OFFSET:
                             // note: these are in document coordinates
                             // (inv-zoom)
                             Point pt = (Point) msg.obj;
-                            nativeSetScrollOffset(mNativeClass, msg.arg1,
-                                    msg.arg2 == 1, pt.x, pt.y);
+                            nativeSetScrollOffset(mNativeClass,
+                                    msg.arg1 == 1, pt.x, pt.y);
                             break;
 
                         case SET_GLOBAL_BOUNDS:
@@ -1485,8 +1497,7 @@
                         }
 
                         case SAVE_DOCUMENT_STATE: {
-                            CursorData cDat = (CursorData) msg.obj;
-                            nativeSaveDocumentState(mNativeClass, cDat.mFrame);
+                            nativeSaveDocumentState(mNativeClass);
                             break;
                         }
 
@@ -1529,7 +1540,7 @@
                                     ted.mMetaState);
                             Message.obtain(
                                     mWebView.mPrivateHandler,
-                                    WebView.PREVENT_TOUCH_ID,
+                                    WebViewClassic.PREVENT_TOUCH_ID,
                                     ted.mAction,
                                     ted.mNativeResult ? 1 : 0,
                                     ted).sendToTarget();
@@ -1561,22 +1572,8 @@
                             mBrowserFrame.documentAsText((Message) msg.obj);
                             break;
 
-                        case SET_MOVE_FOCUS:
-                            CursorData focusData = (CursorData) msg.obj;
-                            nativeMoveFocus(mNativeClass, focusData.mFrame, focusData.mNode);
-                            break;
-
                         case SET_MOVE_MOUSE:
-                            CursorData cursorData = (CursorData) msg.obj;
-                            nativeMoveMouse(mNativeClass,
-                                     cursorData.mFrame, cursorData.mX, cursorData.mY);
-                            break;
-
-                        case SET_MOVE_MOUSE_IF_LATEST:
-                            CursorData cData = (CursorData) msg.obj;
-                            nativeMoveMouseIfLatest(mNativeClass,
-                                    cData.mMoveGeneration,
-                                    cData.mFrame, cData.mX, cData.mY);
+                            nativeMoveMouse(mNativeClass, msg.arg1, msg.arg2);
                             break;
 
                         case REQUEST_CURSOR_HREF: {
@@ -1590,15 +1587,6 @@
                             break;
                         }
 
-                        case UPDATE_CACHE_AND_TEXT_ENTRY:
-                            nativeUpdateFrameCache(mNativeClass);
-                            // FIXME: this should provide a minimal rectangle
-                            if (mWebView != null) {
-                                mWebView.postInvalidate();
-                            }
-                            sendUpdateTextEntry();
-                            break;
-
                         case DOC_HAS_IMAGES:
                             Message imageResult = (Message) msg.obj;
                             imageResult.arg1 =
@@ -1621,7 +1609,8 @@
                             String modifiedSelectionString =
                                 nativeModifySelection(mNativeClass, msg.arg1,
                                         msg.arg2);
-                            mWebView.mPrivateHandler.obtainMessage(WebView.SELECTION_STRING_CHANGED,
+                            mWebView.mPrivateHandler.obtainMessage(
+                                    WebViewClassic.SELECTION_STRING_CHANGED,
                                     modifiedSelectionString).sendToTarget();
                             break;
 
@@ -1653,10 +1642,6 @@
                             nativeDumpRenderTree(mNativeClass, msg.arg1 == 1);
                             break;
 
-                        case DUMP_NAVTREE:
-                            nativeDumpNavTree(mNativeClass);
-                            break;
-
                         case SET_JS_FLAGS:
                             nativeSetJsFlags(mNativeClass, (String)msg.obj);
                             break;
@@ -1666,12 +1651,12 @@
                             break;
 
                         case SAVE_WEBARCHIVE:
-                            WebView.SaveWebArchiveMessage saveMessage =
-                                (WebView.SaveWebArchiveMessage)msg.obj;
+                            WebViewClassic.SaveWebArchiveMessage saveMessage =
+                                (WebViewClassic.SaveWebArchiveMessage)msg.obj;
                             saveMessage.mResultFile =
                                 saveWebArchive(saveMessage.mBasename, saveMessage.mAutoname);
                             mWebView.mPrivateHandler.obtainMessage(
-                                WebView.SAVE_WEBARCHIVE_FINISHED, saveMessage).sendToTarget();
+                                WebViewClassic.SAVE_WEBARCHIVE_FINISHED, saveMessage).sendToTarget();
                             break;
 
                         case GEOLOCATION_PERMISSIONS_PROVIDE:
@@ -1684,7 +1669,7 @@
                         case SPLIT_PICTURE_SET:
                             nativeSplitContent(mNativeClass, msg.arg1);
                             mWebView.mPrivateHandler.obtainMessage(
-                                    WebView.REPLACE_BASE_CONTENT, msg.arg1, 0);
+                                    WebViewClassic.REPLACE_BASE_CONTENT, msg.arg1, 0);
                             mSplitPictureIsScheduled = false;
                             break;
 
@@ -1703,21 +1688,6 @@
                             nativeProvideVisitedHistory(mNativeClass, (String[])msg.obj);
                             break;
 
-                        case VALID_NODE_BOUNDS: {
-                            MotionUpData motionUpData = (MotionUpData) msg.obj;
-                            if (!nativeValidNodeAndBounds(
-                                    mNativeClass, motionUpData.mFrame,
-                                    motionUpData.mNode, motionUpData.mBounds)) {
-                                nativeUpdateFrameCache(mNativeClass);
-                            }
-                            Message message = mWebView.mPrivateHandler
-                                    .obtainMessage(WebView.DO_MOTION_UP,
-                                    motionUpData.mX, motionUpData.mY);
-                            mWebView.mPrivateHandler.sendMessageAtFrontOfQueue(
-                                    message);
-                            break;
-                        }
-
                         case HIDE_FULLSCREEN:
                             nativeFullScreenPluginHidden(mNativeClass, msg.arg1);
                             break;
@@ -1747,7 +1717,7 @@
                             }
                             WebKitHitTest hit = performHitTest(d.mX, d.mY, d.mSlop, true);
                             mWebView.mPrivateHandler.obtainMessage(
-                                    WebView.HIT_TEST_RESULT, hit)
+                                    WebViewClassic.HIT_TEST_RESULT, hit)
                                     .sendToTarget();
                             break;
 
@@ -1757,7 +1727,7 @@
 
                         case AUTOFILL_FORM:
                             nativeAutoFillForm(mNativeClass, msg.arg1);
-                            mWebView.mPrivateHandler.obtainMessage(WebView.AUTOFILL_COMPLETE, null)
+                            mWebView.mPrivateHandler.obtainMessage(WebViewClassic.AUTOFILL_COMPLETE, null)
                                     .sendToTarget();
                             break;
 
@@ -1788,7 +1758,7 @@
                                     handles[0], handles[1], handles[2],
                                     handles[3]);
                             if (copiedText != null) {
-                                mWebView.mPrivateHandler.obtainMessage(WebView.COPY_TO_CLIPBOARD, copiedText)
+                                mWebView.mPrivateHandler.obtainMessage(WebViewClassic.COPY_TO_CLIPBOARD, copiedText)
                                         .sendToTarget();
                             }
                             break;
@@ -2034,11 +2004,12 @@
         return mBrowserFrame.saveWebArchive(filename, autoname);
     }
 
-    private void key(KeyEvent evt, boolean isDown) {
+    private void key(KeyEvent evt, int canTakeFocusDirection, boolean isDown) {
         if (DebugFlags.WEB_VIEW_CORE) {
             Log.v(LOGTAG, "CORE key at " + System.currentTimeMillis() + ", "
                     + evt);
         }
+        mChromeCanFocusDirection = canTakeFocusDirection;
         int keyCode = evt.getKeyCode();
         int unicodeChar = evt.getUnicodeChar();
 
@@ -2048,18 +2019,18 @@
             unicodeChar = evt.getCharacters().codePointAt(0);
         }
 
-        if (!nativeKey(mNativeClass, keyCode, unicodeChar, evt.getRepeatCount(),
+        boolean handled = nativeKey(mNativeClass, keyCode, unicodeChar, evt.getRepeatCount(),
                 evt.isShiftPressed(), evt.isAltPressed(),
-                evt.isSymPressed(), isDown) && keyCode != KeyEvent.KEYCODE_ENTER) {
+                evt.isSymPressed(), isDown);
+        mChromeCanFocusDirection = 0;
+        if (!handled && keyCode != KeyEvent.KEYCODE_ENTER) {
             if (keyCode >= KeyEvent.KEYCODE_DPAD_UP
                     && keyCode <= KeyEvent.KEYCODE_DPAD_RIGHT) {
-                if (DebugFlags.WEB_VIEW_CORE) {
-                    Log.v(LOGTAG, "key: arrow unused by page: " + keyCode);
-                }
-                if (mWebView != null && evt.isDown()) {
-                    Message.obtain(mWebView.mPrivateHandler,
-                            WebView.UNHANDLED_NAV_KEY, keyCode,
-                            0).sendToTarget();
+                if (canTakeFocusDirection != 0 && isDown) {
+                    Message m = mWebView.mPrivateHandler.obtainMessage(
+                            WebViewClassic.TAKE_FOCUS);
+                    m.arg1 = canTakeFocusDirection;
+                    m.sendToTarget();
                 }
                 return;
             }
@@ -2081,7 +2052,7 @@
     private float mCurrentViewScale = 1.0f;
 
     // notify webkit that our virtual view size changed size (after inv-zoom)
-    private void viewSizeChanged(WebView.ViewSizeData data) {
+    private void viewSizeChanged(WebViewClassic.ViewSizeData data) {
         int w = data.mWidth;
         int h = data.mHeight;
         int textwrapWidth = data.mTextWrapWidth;
@@ -2115,8 +2086,6 @@
             if (DebugFlags.WEB_VIEW_CORE) Log.v(LOGTAG, "viewSizeChanged");
             contentDraw();
         }
-        mEventHub.sendMessage(Message.obtain(null,
-                EventHub.UPDATE_CACHE_AND_TEXT_ENTRY));
     }
 
     // Calculate width to be used in webkit window.
@@ -2125,7 +2094,7 @@
         if (mSettings.getUseWideViewPort()) {
             if (mViewportWidth == -1) {
                 // Fixed viewport width.
-                width = WebView.DEFAULT_VIEWPORT_WIDTH;
+                width = WebViewClassic.DEFAULT_VIEWPORT_WIDTH;
             } else if (mViewportWidth > 0) {
                 // Use website specified or desired fixed viewport width.
                 width = mViewportWidth;
@@ -2137,13 +2106,6 @@
         return width;
     }
 
-    private void sendUpdateTextEntry() {
-        if (mWebView != null) {
-            Message.obtain(mWebView.mPrivateHandler,
-                    WebView.UPDATE_TEXT_ENTRY_MSG_ID).sendToTarget();
-        }
-    }
-
     // Utility method for exceededDatabaseQuota and reachedMaxAppCacheSize
     // callbacks. Computes the sum of database quota for all origins.
     private long getUsedQuota() {
@@ -2230,9 +2192,9 @@
             // If anything more complex than position has been touched, let's do a full draw
             webkitDraw();
         }
-        mWebView.mPrivateHandler.removeMessages(WebView.INVAL_RECT_MSG_ID);
+        mWebView.mPrivateHandler.removeMessages(WebViewClassic.INVAL_RECT_MSG_ID);
         mWebView.mPrivateHandler.sendMessageAtFrontOfQueue(mWebView.mPrivateHandler
-                .obtainMessage(WebView.INVAL_RECT_MSG_ID));
+                .obtainMessage(WebViewClassic.INVAL_RECT_MSG_ID));
     }
 
     private Boolean m_skipDrawFlag = false;
@@ -2289,7 +2251,7 @@
             draw.mViewSize = new Point(mCurrentViewWidth, mCurrentViewHeight);
             if (mSettings.getUseWideViewPort()) {
                 draw.mMinPrefWidth = Math.max(
-                        mViewportWidth == -1 ? WebView.DEFAULT_VIEWPORT_WIDTH
+                        mViewportWidth == -1 ? WebViewClassic.DEFAULT_VIEWPORT_WIDTH
                                 : (mViewportWidth == 0 ? mCurrentViewWidth
                                         : mViewportWidth),
                         nativeGetContentMinPrefWidth(mNativeClass));
@@ -2304,7 +2266,7 @@
             }
             if (DebugFlags.WEB_VIEW_CORE) Log.v(LOGTAG, "webkitDraw NEW_PICTURE_MSG_ID");
             Message.obtain(mWebView.mPrivateHandler,
-                    WebView.NEW_PICTURE_MSG_ID, draw).sendToTarget();
+                    WebViewClassic.NEW_PICTURE_MSG_ID, draw).sendToTarget();
         }
     }
 
@@ -2433,7 +2395,7 @@
         }
         if (mWebView != null) {
             Message msg = Message.obtain(mWebView.mPrivateHandler,
-                    WebView.SCROLL_TO_MSG_ID, animate ? 1 : 0,
+                    WebViewClassic.SCROLL_TO_MSG_ID, animate ? 1 : 0,
                     onlyIfImeIsShowing ? 1 : 0, new Point(x, y));
             if (mDrawIsScheduled) {
                 mEventHub.sendMessage(Message.obtain(null,
@@ -2446,7 +2408,6 @@
 
     // called by JNI
     private void sendNotifyProgressFinished() {
-        sendUpdateTextEntry();
         contentDraw();
     }
 
@@ -2457,7 +2418,7 @@
     private void sendViewInvalidate(int left, int top, int right, int bottom) {
         if (mWebView != null) {
             Message.obtain(mWebView.mPrivateHandler,
-                           WebView.INVAL_RECT_MSG_ID,
+                           WebViewClassic.INVAL_RECT_MSG_ID,
                            new Rect(left, top, right, bottom)).sendToTarget();
         }
     }
@@ -2473,7 +2434,7 @@
 
     // Gets the WebView corresponding to this WebViewCore. Note that the
     // WebView object must only be used on the UI thread.
-    /* package */ WebView getWebView() {
+    /* package */ WebViewClassic getWebView() {
         return mWebView;
     }
 
@@ -2499,10 +2460,8 @@
         }
 
         // remove the touch highlight when moving to a new page
-        if (WebView.sDisableNavcache) {
-            mWebView.mPrivateHandler.sendEmptyMessage(
-                    WebView.HIT_TEST_RESULT);
-        }
+        mWebView.mPrivateHandler.sendEmptyMessage(
+                WebViewClassic.HIT_TEST_RESULT);
 
         // reset the scroll position, the restored offset and scales
         mRestoredX = mRestoredY = 0;
@@ -2567,7 +2526,7 @@
         }
         if (adjust != mWebView.getDefaultZoomScale()) {
             Message.obtain(mWebView.mPrivateHandler,
-                    WebView.UPDATE_ZOOM_DENSITY, adjust).sendToTarget();
+                    WebViewClassic.UPDATE_ZOOM_DENSITY, adjust).sendToTarget();
         }
         int defaultScale = (int) (adjust * 100);
 
@@ -2618,7 +2577,7 @@
             viewState.mScrollX = 0;
             viewState.mShouldStartScrolledRight = false;
             Message.obtain(mWebView.mPrivateHandler,
-                    WebView.UPDATE_ZOOM_RANGE, viewState).sendToTarget();
+                    WebViewClassic.UPDATE_ZOOM_RANGE, viewState).sendToTarget();
             return;
         }
 
@@ -2689,7 +2648,7 @@
             mWebView.mLastHeightSent = 0;
             // Send a negative scale to indicate that WebCore should reuse
             // the current scale
-            WebView.ViewSizeData data = new WebView.ViewSizeData();
+            WebViewClassic.ViewSizeData data = new WebViewClassic.ViewSizeData();
             data.mWidth = mWebView.mLastWidthSent;
             data.mHeight = 0;
             // if mHeightCanMeasure is true, getUseWideViewPort() can't be
@@ -2713,7 +2672,7 @@
                 // to WebViewCore
                 mWebView.mLastWidthSent = 0;
             } else {
-                WebView.ViewSizeData data = new WebView.ViewSizeData();
+                WebViewClassic.ViewSizeData data = new WebViewClassic.ViewSizeData();
                 // mViewScale as 0 means it is in zoom overview mode. So we don't
                 // know the exact scale. If mRestoredScale is non-zero, use it;
                 // otherwise just use mTextWrapScale as the initial scale.
@@ -2791,7 +2750,7 @@
     private void needTouchEvents(boolean need) {
         if (mWebView != null) {
             Message.obtain(mWebView.mPrivateHandler,
-                    WebView.WEBCORE_NEED_TOUCH_EVENTS, need ? 1 : 0, 0)
+                    WebViewClassic.WEBCORE_NEED_TOUCH_EVENTS, need ? 1 : 0, 0)
                     .sendToTarget();
         }
     }
@@ -2801,7 +2760,7 @@
             String text, int textGeneration) {
         if (mWebView != null) {
             Message msg = Message.obtain(mWebView.mPrivateHandler,
-                    WebView.UPDATE_TEXTFIELD_TEXT_MSG_ID, ptr,
+                    WebViewClassic.UPDATE_TEXTFIELD_TEXT_MSG_ID, ptr,
                     textGeneration, text);
             msg.getData().putBoolean("password", changeToPassword);
             msg.sendToTarget();
@@ -2813,7 +2772,7 @@
             int textGeneration, int selectionPtr) {
         if (mWebView != null) {
             Message.obtain(mWebView.mPrivateHandler,
-                WebView.UPDATE_TEXT_SELECTION_MSG_ID, pointer, textGeneration,
+                WebViewClassic.UPDATE_TEXT_SELECTION_MSG_ID, pointer, textGeneration,
                 new TextSelectionData(start, end, selectionPtr)).sendToTarget();
         }
     }
@@ -2822,7 +2781,7 @@
     private void clearTextEntry() {
         if (mWebView == null) return;
         Message.obtain(mWebView.mPrivateHandler,
-                WebView.CLEAR_TEXT_ENTRY).sendToTarget();
+                WebViewClassic.CLEAR_TEXT_ENTRY).sendToTarget();
     }
 
     // called by JNI
@@ -2836,9 +2795,9 @@
                 text, inputType, isSpellCheckEnabled, nextFieldIsText, label,
                 maxLength);
         Message.obtain(mWebView.mPrivateHandler,
-                WebView.INIT_EDIT_FIELD, initData).sendToTarget();
+                WebViewClassic.INIT_EDIT_FIELD, initData).sendToTarget();
         Message.obtain(mWebView.mPrivateHandler,
-                WebView.REQUEST_KEYBOARD_WITH_SELECTION_MSG_ID, pointer,
+                WebViewClassic.REQUEST_KEYBOARD_WITH_SELECTION_MSG_ID, pointer,
                 0, new TextSelectionData(start, end, selectionPtr))
                 .sendToTarget();
     }
@@ -2850,11 +2809,10 @@
             return;
         }
         Message.obtain(mWebView.mPrivateHandler,
-                WebView.UPDATE_MATCH_COUNT, matchIndex, matchCount,
+                WebViewClassic.UPDATE_MATCH_COUNT, matchIndex, matchCount,
                 findText).sendToTarget();
     }
 
-    private native void nativeUpdateFrameCacheIfLoading(int nativeClass);
     private native void nativeRevealSelection(int nativeClass);
     private native String nativeRequestLabel(int nativeClass, int framePtr,
             int nodePtr);
@@ -2865,7 +2823,7 @@
             float xPercent, int y);
 
     // these must be in document space (i.e. not scaled/zoomed).
-    private native void nativeSetScrollOffset(int nativeClass, int gen,
+    private native void nativeSetScrollOffset(int nativeClass,
             boolean sendScrollEvent, int dx, int dy);
 
     private native void nativeSetGlobalBounds(int nativeClass, int x, int y,
@@ -2892,14 +2850,14 @@
     private void requestKeyboard(boolean showKeyboard) {
         if (mWebView != null) {
             Message.obtain(mWebView.mPrivateHandler,
-                    WebView.REQUEST_KEYBOARD, showKeyboard ? 1 : 0, 0)
+                    WebViewClassic.REQUEST_KEYBOARD, showKeyboard ? 1 : 0, 0)
                     .sendToTarget();
         }
     }
 
     private void setWebTextViewAutoFillable(int queryId, String preview) {
         if (mWebView != null) {
-            Message.obtain(mWebView.mPrivateHandler, WebView.SET_AUTOFILLABLE,
+            Message.obtain(mWebView.mPrivateHandler, WebViewClassic.SET_AUTOFILLABLE,
                     new AutoFillData(queryId, preview))
                     .sendToTarget();
         }
@@ -2912,7 +2870,7 @@
     // called by JNI
     private void keepScreenOn(boolean screenOn) {
         if (mWebView != null) {
-            Message message = mWebView.mPrivateHandler.obtainMessage(WebView.SCREEN_ON);
+            Message message = mWebView.mPrivateHandler.obtainMessage(WebViewClassic.SCREEN_ON);
             message.arg1 = screenOn ? 1 : 0;
             message.sendToTarget();
         }
@@ -2952,7 +2910,7 @@
             return;
         }
 
-        Message message = mWebView.mPrivateHandler.obtainMessage(WebView.SHOW_FULLSCREEN);
+        Message message = mWebView.mPrivateHandler.obtainMessage(WebViewClassic.SHOW_FULLSCREEN);
         message.obj = childView.mView;
         message.arg1 = orientation;
         message.arg2 = npp;
@@ -2964,7 +2922,7 @@
         if (mWebView == null) {
             return;
         }
-        mWebView.mPrivateHandler.obtainMessage(WebView.HIDE_FULLSCREEN)
+        mWebView.mPrivateHandler.obtainMessage(WebViewClassic.HIDE_FULLSCREEN)
                 .sendToTarget();
     }
 
@@ -3036,7 +2994,7 @@
             data.mXPercentInView = xPercentInView;
             data.mYPercentInDoc = yPercentInDoc;
             data.mYPercentInView = yPercentInView;
-            Message.obtain(mWebView.mPrivateHandler, WebView.SHOW_RECT_MSG_ID,
+            Message.obtain(mWebView.mPrivateHandler, WebViewClassic.SHOW_RECT_MSG_ID,
                     data).sendToTarget();
         }
     }
@@ -3046,7 +3004,7 @@
         if (mWebView == null) {
             return;
         }
-        mWebView.mPrivateHandler.obtainMessage(WebView.CENTER_FIT_RECT,
+        mWebView.mPrivateHandler.obtainMessage(WebViewClassic.CENTER_FIT_RECT,
                 new Rect(x, y, x + width, y + height)).sendToTarget();
     }
 
@@ -3055,16 +3013,13 @@
         if (mWebView == null) {
             return;
         }
-        mWebView.mPrivateHandler.obtainMessage(WebView.SET_SCROLLBAR_MODES,
+        mWebView.mPrivateHandler.obtainMessage(WebViewClassic.SET_SCROLLBAR_MODES,
                 hMode, vMode).sendToTarget();
     }
 
     // called by JNI
-    @SuppressWarnings("unused")
     private void selectAt(int x, int y) {
-        if (mWebView != null) {
-            mWebView.mPrivateHandler.obtainMessage(WebView.SELECT_AT, x, y).sendToTarget();
-        }
+        // TODO: Figure out what to do with this (b/6111818)
     }
 
     private void useMockDeviceOrientation() {
@@ -3099,8 +3054,6 @@
     private native void nativeFreeMemory(int nativeClass);
     private native void nativeFullScreenPluginHidden(int nativeClass, int npp);
     private native void nativePluginSurfaceReady(int nativeClass);
-    private native boolean nativeValidNodeAndBounds(int nativeClass, int frame,
-            int node, Rect bounds);
 
     private native WebKitHitTest nativeHitTest(int nativeClass, int x, int y,
             int slop, boolean moveMouse);
diff --git a/core/java/android/webkit/WebViewFactoryProvider.java b/core/java/android/webkit/WebViewFactoryProvider.java
new file mode 100644
index 0000000..22bf0bf
--- /dev/null
+++ b/core/java/android/webkit/WebViewFactoryProvider.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.webkit;
+
+/**
+ * This is the main entry-point into the WebView back end implementations, which the WebView
+ * proxy class uses to instantiate all the other objects as needed. The backend must provide an
+ * implementation of this interface, and make it available to the WebView via mechanism TBD.
+ * @hide
+ */
+public interface WebViewFactoryProvider {
+
+    /**
+     * Construct a new WebView provider.
+     * @param webView the WebView instance bound to this implementation instance. Note it will not
+     * necessarily be fully constructed at the point of this call: defer real initialization to
+     * WebViewProvider.init().
+     * @param privateAccess provides access into WebView internal methods.
+     */
+    WebViewProvider createWebView(WebView webView, WebView.PrivateAccess privateAccess);
+
+    Statics getStatics();
+
+    /**
+     * This Interface provides glue for implementing the backend of WebView static methods which
+     * cannot be implemented in-situ in the proxy class.
+     */
+    interface Statics {
+        /**
+         * Implements the API method:
+         * {@link android.webkit.WebView#findAddress(String)}
+         */
+        String findAddress(String addr);
+
+        /**
+         * Implements the API methods:
+         * {@link android.webkit.WebView#enablePlatformNotifications()}
+         * {@link android.webkit.WebView#disablePlatformNotifications()}
+         */
+        void setPlatformNotificationsEnabled(boolean enable);
+    }
+}
diff --git a/core/java/android/webkit/WebViewProvider.java b/core/java/android/webkit/WebViewProvider.java
new file mode 100644
index 0000000..2e8ad6d
--- /dev/null
+++ b/core/java/android/webkit/WebViewProvider.java
@@ -0,0 +1,372 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.webkit;
+
+import android.content.res.Configuration;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Picture;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.net.http.SslCertificate;
+import android.os.Bundle;
+import android.os.Message;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewGroup.LayoutParams;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityNodeInfo;
+import android.view.inputmethod.EditorInfo;
+import android.view.inputmethod.InputConnection;
+import android.webkit.WebView.HitTestResult;
+import android.webkit.WebView.PictureListener;
+
+import java.io.File;
+import java.util.Map;
+
+/**
+ * WebView backend provider interface: this interface is the abstract backend to a WebView
+ * instance; each WebView object is bound to exactly one WebViewProvider object which implements
+ * the runtime behavior of that WebView.
+ *
+ * All methods must behave as per their namesake in {@link WebView}, unless otherwise noted.
+ *
+ * @hide Not part of the public API; only required by system implementors.
+ */
+public interface WebViewProvider {
+    //-------------------------------------------------------------------------
+    // Main interface for backend provider of the WebView class.
+    //-------------------------------------------------------------------------
+    /**
+     * Initialize this WebViewProvider instance. Called after the WebView has fully constructed.
+     * @param javaScriptInterfaces is a Map of interface names, as keys, and
+     * object implementing those interfaces, as values.
+     * @param privateBrowsing If true the web view will be initialized in private / incognito mode.
+     */
+    public void init(Map<String, Object> javaScriptInterfaces,
+            boolean privateBrowsing);
+
+    public void setHorizontalScrollbarOverlay(boolean overlay);
+
+    public void setVerticalScrollbarOverlay(boolean overlay);
+
+    public boolean overlayHorizontalScrollbar();
+
+    public boolean overlayVerticalScrollbar();
+
+    public int getVisibleTitleHeight();
+
+    public SslCertificate getCertificate();
+
+    public void setCertificate(SslCertificate certificate);
+
+    public void savePassword(String host, String username, String password);
+
+    public void setHttpAuthUsernamePassword(String host, String realm,
+            String username, String password);
+
+    public String[] getHttpAuthUsernamePassword(String host, String realm);
+
+    /**
+     * See {@link WebView#destroy()}.
+     * As well as releasing the internal state and resources held by the implementation,
+     * the provider should null all references it holds on the WebView proxy class, and ensure
+     * no further method calls are made to it.
+     */
+    public void destroy();
+
+    public void setNetworkAvailable(boolean networkUp);
+
+    public WebBackForwardList saveState(Bundle outState);
+
+    public boolean savePicture(Bundle b, final File dest);
+
+    public boolean restorePicture(Bundle b, File src);
+
+    public WebBackForwardList restoreState(Bundle inState);
+
+    public void loadUrl(String url, Map<String, String> additionalHttpHeaders);
+
+    public void loadUrl(String url);
+
+    public void postUrl(String url, byte[] postData);
+
+    public void loadData(String data, String mimeType, String encoding);
+
+    public void loadDataWithBaseURL(String baseUrl, String data,
+            String mimeType, String encoding, String historyUrl);
+
+    public void saveWebArchive(String filename);
+
+    public void saveWebArchive(String basename, boolean autoname, ValueCallback<String> callback);
+
+    public void stopLoading();
+
+    public void reload();
+
+    public boolean canGoBack();
+
+    public void goBack();
+
+    public boolean canGoForward();
+
+    public void goForward();
+
+    public boolean canGoBackOrForward(int steps);
+
+    public void goBackOrForward(int steps);
+
+    public boolean isPrivateBrowsingEnabled();
+
+    public boolean pageUp(boolean top);
+
+    public boolean pageDown(boolean bottom);
+
+    public void clearView();
+
+    public Picture capturePicture();
+
+    public float getScale();
+
+    public void setInitialScale(int scaleInPercent);
+
+    public void invokeZoomPicker();
+
+    public HitTestResult getHitTestResult();
+
+    public void requestFocusNodeHref(Message hrefMsg);
+
+    public void requestImageRef(Message msg);
+
+    public String getUrl();
+
+    public String getOriginalUrl();
+
+    public String getTitle();
+
+    public Bitmap getFavicon();
+
+    public String getTouchIconUrl();
+
+    public int getProgress();
+
+    public int getContentHeight();
+
+    public int getContentWidth();
+
+    public void pauseTimers();
+
+    public void resumeTimers();
+
+    public void onPause();
+
+    public void onResume();
+
+    public boolean isPaused();
+
+    public void freeMemory();
+
+    public void clearCache(boolean includeDiskFiles);
+
+    public void clearFormData();
+
+    public void clearHistory();
+
+    public void clearSslPreferences();
+
+    public WebBackForwardList copyBackForwardList();
+
+    public void findNext(boolean forward);
+
+    public int findAll(String find);
+
+    public boolean showFindDialog(String text, boolean showIme);
+
+    public void clearMatches();
+
+    public void documentHasImages(Message response);
+
+    public void setWebViewClient(WebViewClient client);
+
+    public void setDownloadListener(DownloadListener listener);
+
+    public void setWebChromeClient(WebChromeClient client);
+
+    public void setPictureListener(PictureListener listener);
+
+    public void addJavascriptInterface(Object obj, String interfaceName);
+
+    public void removeJavascriptInterface(String interfaceName);
+
+    public WebSettings getSettings();
+
+    public void emulateShiftHeld();
+
+    public void setMapTrackballToArrowKeys(boolean setMap);
+
+    public void flingScroll(int vx, int vy);
+
+    public View getZoomControls();
+
+    public boolean canZoomIn();
+
+    public boolean canZoomOut();
+
+    public boolean zoomIn();
+
+    public boolean zoomOut();
+
+    public void debugDump();
+
+    //-------------------------------------------------------------------------
+    // Provider glue methods
+    //-------------------------------------------------------------------------
+
+    /**
+     * @return the ViewDelegate implementation. This provides the functionality to back all of
+     * the name-sake functions from the View and ViewGroup base classes of WebView.
+     */
+    /* package */ ViewDelegate getViewDelegate();
+
+    /**
+     * @return a ScrollDelegate implementation. Normally this would be same object as is
+     * returned by getViewDelegate().
+     */
+    /* package */ ScrollDelegate getScrollDelegate();
+
+    //-------------------------------------------------------------------------
+    // View / ViewGroup delegation methods
+    //-------------------------------------------------------------------------
+
+    /**
+     * Provides mechanism for the name-sake methods declared in View and ViewGroup to be delegated
+     * into the WebViewProvider instance.
+     * NOTE For many of these methods, the WebView will provide a super.Foo() call before or after
+     * making the call into the provider instance. This is done for convenience in the common case
+     * of maintaining backward compatibility. For remaining super class calls (e.g. where the
+     * provider may need to only conditionally make the call based on some internal state) see the
+     * {@link WebView.PrivateAccess} callback class.
+     */
+    // TODO: See if the pattern of the super-class calls can be rationalized at all, and document
+    // the remainder on the methods below.
+    interface ViewDelegate {
+        public boolean shouldDelayChildPressedState();
+
+        public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info);
+
+        public void onInitializeAccessibilityEvent(AccessibilityEvent event);
+
+        public void setOverScrollMode(int mode);
+
+        public void setScrollBarStyle(int style);
+
+        public void onDrawVerticalScrollBar(Canvas canvas, Drawable scrollBar, int l, int t,
+                int r, int b);
+
+        public void onOverScrolled(int scrollX, int scrollY, boolean clampedX, boolean clampedY);
+
+        public void onWindowVisibilityChanged(int visibility);
+
+        public boolean drawChild(Canvas canvas, View child, long drawingTime);
+
+        public void onDraw(Canvas canvas);
+
+        public void setLayoutParams(LayoutParams layoutParams);
+
+        public boolean performLongClick();
+
+        public void onConfigurationChanged(Configuration newConfig);
+
+        public InputConnection onCreateInputConnection(EditorInfo outAttrs);
+
+        public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event);
+
+        public boolean onKeyDown(int keyCode, KeyEvent event);
+
+        public boolean onKeyUp(int keyCode, KeyEvent event);
+
+        public void onAttachedToWindow();
+
+        public void onDetachedFromWindow();
+
+        public void onVisibilityChanged(View changedView, int visibility);
+
+        public void onWindowFocusChanged(boolean hasWindowFocus);
+
+        public void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect);
+
+        public boolean setFrame(int left, int top, int right, int bottom);
+
+        public void onSizeChanged(int w, int h, int ow, int oh);
+
+        public void onScrollChanged(int l, int t, int oldl, int oldt);
+
+        public boolean dispatchKeyEvent(KeyEvent event);
+
+        public boolean onTouchEvent(MotionEvent ev);
+
+        public boolean onHoverEvent(MotionEvent event);
+
+        public boolean onGenericMotionEvent(MotionEvent event);
+
+        public boolean onTrackballEvent(MotionEvent ev);
+
+        public boolean requestFocus(int direction, Rect previouslyFocusedRect);
+
+        public void onMeasure(int widthMeasureSpec, int heightMeasureSpec);
+
+        public boolean requestChildRectangleOnScreen(View child, Rect rect, boolean immediate);
+
+        public void setBackgroundColor(int color);
+    }
+
+    interface ScrollDelegate {
+        // These methods are declared protected in the ViewGroup base class. This interface
+        // exists to promote them to public so they may be called by the WebView proxy class.
+        // TODO: Combine into ViewDelegate?
+        /**
+         * See {@link android.webkit.WebView#computeHorizontalScrollRange}
+         */
+        public int computeHorizontalScrollRange();
+
+        /**
+         * See {@link android.webkit.WebView#computeHorizontalScrollOffset}
+         */
+        public int computeHorizontalScrollOffset();
+
+        /**
+         * See {@link android.webkit.WebView#computeVerticalScrollRange}
+         */
+        public int computeVerticalScrollRange();
+
+        /**
+         * See {@link android.webkit.WebView#computeVerticalScrollOffset}
+         */
+        public int computeVerticalScrollOffset();
+
+        /**
+         * See {@link android.webkit.WebView#computeVerticalScrollExtent}
+         */
+        public int computeVerticalScrollExtent();
+
+        /**
+         * See {@link android.webkit.WebView#computeScroll}
+         */
+        public void computeScroll();
+    }
+}
diff --git a/core/java/android/webkit/ZoomControlEmbedded.java b/core/java/android/webkit/ZoomControlEmbedded.java
index e505614..d2a0561 100644
--- a/core/java/android/webkit/ZoomControlEmbedded.java
+++ b/core/java/android/webkit/ZoomControlEmbedded.java
@@ -25,12 +25,12 @@
 class ZoomControlEmbedded implements ZoomControlBase {
 
     private final ZoomManager mZoomManager;
-    private final WebView mWebView;
+    private final WebViewClassic mWebView;
 
     // The controller is lazily initialized in getControls() for performance.
     private ZoomButtonsController mZoomButtonsController;
 
-    public ZoomControlEmbedded(ZoomManager zoomManager, WebView webView) {
+    public ZoomControlEmbedded(ZoomManager zoomManager, WebViewClassic webView) {
         mZoomManager = zoomManager;
         mWebView = webView;
     }
@@ -41,7 +41,7 @@
             mZoomButtonsController.setVisible(true);
 
             if (mZoomManager.isDoubleTapEnabled()) {
-                WebSettings settings = mWebView.getSettings();
+                WebSettingsClassic settings = mWebView.getSettings();
                 int count = settings.getDoubleTapToastCount();
                 if (mZoomManager.isInZoomOverview() && count > 0) {
                     settings.setDoubleTapToastCount(--count);
@@ -82,7 +82,7 @@
 
     private ZoomButtonsController getControls() {
         if (mZoomButtonsController == null) {
-            mZoomButtonsController = new ZoomButtonsController(mWebView);
+            mZoomButtonsController = new ZoomButtonsController(mWebView.getWebView());
             mZoomButtonsController.setOnZoomListener(new ZoomListener());
             // ZoomButtonsController positions the buttons at the bottom, but in
             // the middle. Change their layout parameters so they appear on the
diff --git a/core/java/android/webkit/ZoomControlExternal.java b/core/java/android/webkit/ZoomControlExternal.java
index d75313e..f5bfc05 100644
--- a/core/java/android/webkit/ZoomControlExternal.java
+++ b/core/java/android/webkit/ZoomControlExternal.java
@@ -35,9 +35,9 @@
     private Runnable mZoomControlRunnable;
     private final Handler mPrivateHandler = new Handler();
 
-    private final WebView mWebView;
+    private final WebViewClassic mWebView;
 
-    public ZoomControlExternal(WebView webView) {
+    public ZoomControlExternal(WebViewClassic webView) {
         mWebView = webView;
     }
 
diff --git a/core/java/android/webkit/ZoomManager.java b/core/java/android/webkit/ZoomManager.java
index 369e883..2247678 100644
--- a/core/java/android/webkit/ZoomManager.java
+++ b/core/java/android/webkit/ZoomManager.java
@@ -50,7 +50,7 @@
 
     static final String LOGTAG = "webviewZoom";
 
-    private final WebView mWebView;
+    private final WebViewClassic mWebView;
     private final CallbackProxy mCallbackProxy;
 
     // Widgets responsible for the on-screen zoom functions of the WebView.
@@ -211,7 +211,7 @@
     private boolean mHardwareAccelerated = false;
     private boolean mInHWAcceleratedZoom = false;
 
-    public ZoomManager(WebView webView, CallbackProxy callbackProxy) {
+    public ZoomManager(WebViewClassic webView, CallbackProxy callbackProxy) {
         mWebView = webView;
         mCallbackProxy = callbackProxy;
 
@@ -220,7 +220,7 @@
          * ESPN and Engadget always have wider mContentWidth no matter what the
          * viewport size is.
          */
-        setZoomOverviewWidth(WebView.DEFAULT_VIEWPORT_WIDTH);
+        setZoomOverviewWidth(WebViewClassic.DEFAULT_VIEWPORT_WIDTH);
 
         mFocusMovementQueue = new FocusMovementQueue();
     }
@@ -487,13 +487,13 @@
         // zoomScale, we can't use the WebView's pinLocX/Y functions directly.
         float scale = zoomScale * mInvInitialZoomScale;
         int tx = Math.round(scale * (mInitialScrollX + mZoomCenterX) - mZoomCenterX);
-        tx = -WebView.pinLoc(tx, mWebView.getViewWidth(), Math.round(mWebView.getContentWidth()
+        tx = -WebViewClassic.pinLoc(tx, mWebView.getViewWidth(), Math.round(mWebView.getContentWidth()
                 * zoomScale)) + mWebView.getScrollX();
         int titleHeight = mWebView.getTitleHeight();
         int ty = Math.round(scale
                 * (mInitialScrollY + mZoomCenterY - titleHeight)
                 - (mZoomCenterY - titleHeight));
-        ty = -(ty <= titleHeight ? Math.max(ty, 0) : WebView.pinLoc(ty
+        ty = -(ty <= titleHeight ? Math.max(ty, 0) : WebViewClassic.pinLoc(ty
                 - titleHeight, mWebView.getViewHeight(), Math.round(mWebView.getContentHeight()
                 * zoomScale)) + titleHeight) + mWebView.getScrollY();
 
@@ -630,7 +630,7 @@
     public void handleDoubleTap(float lastTouchX, float lastTouchY) {
         // User takes action, set initial zoom overview to false.
         mInitialZoomOverview = false;
-        WebSettings settings = mWebView.getSettings();
+        WebSettingsClassic settings = mWebView.getSettings();
         if (!isDoubleTapEnabled()) {
             return;
         }
@@ -643,20 +643,6 @@
         // remove the zoom control after double tap
         dismissZoomPicker();
 
-        /*
-         * If the double tap was on a plugin then either zoom to maximize the
-         * plugin on the screen or scale to overview mode.
-         */
-        Rect pluginBounds = mWebView.getPluginBounds(mAnchorX, mAnchorY);
-        if (pluginBounds != null) {
-            if (mWebView.isRectFitOnScreen(pluginBounds)) {
-                zoomToOverview();
-            } else {
-                mWebView.centerFitRect(pluginBounds);
-            }
-            return;
-        }
-
         final float newTextWrapScale;
         if (settings.getUseFixedViewport()) {
             newTextWrapScale = Math.max(mActualScale, getReadingLevelScale());
@@ -690,7 +676,7 @@
 
     private void setZoomOverviewWidth(int width) {
         if (width == 0) {
-            mZoomOverviewWidth = WebView.DEFAULT_VIEWPORT_WIDTH;
+            mZoomOverviewWidth = WebViewClassic.DEFAULT_VIEWPORT_WIDTH;
         } else {
             mZoomOverviewWidth = width;
         }
@@ -719,7 +705,7 @@
         final float readingScale = getReadingLevelScale();
 
         int left = mWebView.getBlockLeftEdge(mAnchorX, mAnchorY, readingScale);
-        if (left != WebView.NO_LEFTEDGE) {
+        if (left != WebViewClassic.NO_LEFTEDGE) {
             // add a 5pt padding to the left edge.
             int viewLeft = mWebView.contentToViewX(left < 5 ? 0 : (left - 5))
                     - mWebView.getScrollX();
@@ -728,7 +714,7 @@
             if (viewLeft > 0) {
                 mZoomCenterX = viewLeft * readingScale / (readingScale - mActualScale);
             } else {
-                mWebView.scrollBy(viewLeft, 0);
+                mWebView.getWebView().scrollBy(viewLeft, 0);
                 mZoomCenterX = 0;
             }
         }
@@ -955,7 +941,7 @@
         // cause its child View to reposition itself through ViewManager's
         // scaleAll(), we need to post a Runnable to ensure requestLayout().
         // Additionally, only update the text wrap scale if the width changed.
-        mWebView.post(new PostScale(w != ow &&
+        mWebView.getWebView().post(new PostScale(w != ow &&
             !mWebView.getSettings().getUseFixedViewport(), mInZoomOverview, w < ow));
     }
 
@@ -1027,7 +1013,7 @@
         final int viewWidth = mWebView.getViewWidth();
         final boolean zoomOverviewWidthChanged = setupZoomOverviewWidth(drawData, viewWidth);
         final float newZoomOverviewScale = getZoomOverviewScale();
-        WebSettings settings = mWebView.getSettings();
+        WebSettingsClassic settings = mWebView.getSettings();
         if (zoomOverviewWidthChanged && settings.isNarrowColumnLayout() &&
             settings.getUseFixedViewport() &&
             (mInitialZoomOverview || mInZoomOverview)) {
@@ -1085,7 +1071,7 @@
             if (drawData.mContentSize.x > 0) {
                 // The webkitDraw for layers will not populate contentSize, and it'll be
                 // ignored for zoom overview width update.
-                newZoomOverviewWidth = Math.min(WebView.sMaxViewportWidth,
+                newZoomOverviewWidth = Math.min(WebViewClassic.sMaxViewportWidth,
                     drawData.mContentSize.x);
             }
         } else {
@@ -1117,7 +1103,7 @@
         updateZoomRange(viewState, viewSize.x, drawData.mMinPrefWidth);
         setupZoomOverviewWidth(drawData, mWebView.getViewWidth());
         final float overviewScale = getZoomOverviewScale();
-        WebSettings settings = mWebView.getSettings();
+        WebSettingsClassic settings = mWebView.getSettings();
         if (!mMinZoomScaleFixed || settings.getUseWideViewPort()) {
             mMinZoomScale = (mInitialScale > 0) ?
                     Math.min(mInitialScale, overviewScale) : overviewScale;
diff --git a/core/java/android/widget/CalendarView.java b/core/java/android/widget/CalendarView.java
index 85252af..2a74f6a 100644
--- a/core/java/android/widget/CalendarView.java
+++ b/core/java/android/widget/CalendarView.java
@@ -154,21 +154,25 @@
 
     private final int mWeekSeperatorLineWidth;
 
-    private final int mDateTextSize;
+    private int mDateTextSize;
 
-    private final Drawable mSelectedDateVerticalBar;
+    private Drawable mSelectedDateVerticalBar;
 
     private final int mSelectedDateVerticalBarWidth;
 
-    private final int mSelectedWeekBackgroundColor;
+    private int mSelectedWeekBackgroundColor;
 
-    private final int mFocusedMonthDateColor;
+    private int mFocusedMonthDateColor;
 
-    private final int mUnfocusedMonthDateColor;
+    private int mUnfocusedMonthDateColor;
 
-    private final int mWeekSeparatorLineColor;
+    private int mWeekSeparatorLineColor;
 
-    private final int mWeekNumberColor;
+    private int mWeekNumberColor;
+
+    private int mWeekDayTextAppearanceResId;
+
+    private int mDateTextAppearanceResId;
 
     /**
      * The top offset of the weeks list.
@@ -366,15 +370,11 @@
         mSelectedDateVerticalBar = attributesArray.getDrawable(
                 R.styleable.CalendarView_selectedDateVerticalBar);
 
-        int dateTextAppearanceResId= attributesArray.getResourceId(
+        mDateTextAppearanceResId = attributesArray.getResourceId(
                 R.styleable.CalendarView_dateTextAppearance, R.style.TextAppearance_Small);
-        TypedArray dateTextAppearance = context.obtainStyledAttributes(dateTextAppearanceResId,
-                com.android.internal.R.styleable.TextAppearance);
-        mDateTextSize = dateTextAppearance.getDimensionPixelSize(
-                R.styleable.TextAppearance_textSize, DEFAULT_DATE_TEXT_SIZE);
-        dateTextAppearance.recycle();
+        updateDateTextSize();
 
-        int weekDayTextAppearanceResId = attributesArray.getResourceId(
+        mWeekDayTextAppearanceResId = attributesArray.getResourceId(
                 R.styleable.CalendarView_weekDayTextAppearance,
                 DEFAULT_WEEK_DAY_TEXT_APPEARANCE_RES_ID);
         attributesArray.recycle();
@@ -400,7 +400,7 @@
         mDayNamesHeader = (ViewGroup) content.findViewById(com.android.internal.R.id.day_names);
         mMonthName = (TextView) content.findViewById(com.android.internal.R.id.month_name);
 
-        setUpHeader(weekDayTextAppearanceResId);
+        setUpHeader();
         setUpListView();
         setUpAdapter();
 
@@ -417,6 +417,235 @@
         invalidate();
     }
 
+    /**
+     * Sets the number of weeks to be shown.
+     *
+     * @param count The shown week count.
+     */
+    public void setShownWeekCount(int count) {
+        if (mShownWeekCount != count) {
+            mShownWeekCount = count;
+            invalidate();
+        }
+    }
+
+    /**
+     * Gets the number of weeks to be shown.
+     *
+     * @return The shown week count.
+     */
+    public int getShownWeekCount() {
+        return mShownWeekCount;
+    }
+
+    /**
+     * Sets the background color for the selected week.
+     *
+     * @param color The week background color.
+     */
+    public void setSelectedWeekBackgroundColor(int color) {
+        if (mSelectedWeekBackgroundColor != color) {
+            mSelectedWeekBackgroundColor = color;
+            final int childCount = mListView.getChildCount();
+            for (int i = 0; i < childCount; i++) {
+                WeekView weekView = (WeekView) mListView.getChildAt(i);
+                if (weekView.mHasSelectedDay) {
+                    weekView.invalidate();
+                }
+            }
+        }
+    }
+
+    /**
+     * Gets the background color for the selected week.
+     *
+     * @return The week background color.
+     */
+    public int getSelectedWeekBackgroundColor() {
+        return mSelectedWeekBackgroundColor;
+    }
+
+    /**
+     * Sets the color for the dates of the focused month.
+     *
+     * @param color The focused month date color.
+     */
+    public void setFocusedMonthDateColor(int color) {
+        if (mFocusedMonthDateColor != color) {
+            mFocusedMonthDateColor = color;
+            final int childCount = mListView.getChildCount();
+            for (int i = 0; i < childCount; i++) {
+                WeekView weekView = (WeekView) mListView.getChildAt(i);
+                if (weekView.mHasFocusedDay) {
+                    weekView.invalidate();
+                }
+            }
+        }
+    }
+
+    /**
+     * Gets the color for the dates in the focused month.
+     *
+     * @return The focused month date color.
+     */
+    public int getFocusedMonthDateColor() {
+        return mFocusedMonthDateColor;
+    }
+
+    /**
+     * Sets the color for the dates of a not focused month.
+     *
+     * @param color A not focused month date color.
+     */
+    public void setUnfocusedMonthDateColor(int color) {
+        if (mUnfocusedMonthDateColor != color) {
+            mUnfocusedMonthDateColor = color;
+            final int childCount = mListView.getChildCount();
+            for (int i = 0; i < childCount; i++) {
+                WeekView weekView = (WeekView) mListView.getChildAt(i);
+                if (weekView.mHasUnfocusedDay) {
+                    weekView.invalidate();
+                }
+            }
+        }
+    }
+
+    /**
+     * Gets the color for the dates in a not focused month.
+     *
+     * @return A not focused month date color.
+     */
+    public int getUnfocusedMonthDateColor() {
+        return mFocusedMonthDateColor;
+    }
+
+    /**
+     * Sets the color for the week numbers.
+     *
+     * @param color The week number color.
+     */
+    public void setWeekNumberColor(int color) {
+        if (mWeekNumberColor != color) {
+            mWeekNumberColor = color;
+            if (mShowWeekNumber) {
+                invalidateAllWeekViews();
+            }
+        }
+    }
+
+    /**
+     * Gets the color for the week numbers.
+     *
+     * @return The week number color.
+     */
+    public int getWeekNumberColor() {
+        return mWeekNumberColor;
+    }
+
+    /**
+     * Sets the color for the separator line between weeks.
+     *
+     * @param color The week separator color.
+     */
+    public void setWeekSeparatorLineColor(int color) {
+        if (mWeekSeparatorLineColor != color) {
+            mWeekSeparatorLineColor = color;
+            invalidateAllWeekViews();
+        }
+    }
+
+    /**
+     * Gets the color for the separator line between weeks.
+     *
+     * @return The week separator color.
+     */
+    public int getWeekSeparatorLineColor() {
+        return mWeekSeparatorLineColor;
+    }
+
+    /**
+     * Sets the drawable for the vertical bar shown at the beginning and at
+     * the end of the selected date.
+     *
+     * @param resourceId The vertical bar drawable resource id.
+     */
+    public void setSelectedDateVerticalBar(int resourceId) {
+        Drawable drawable = getResources().getDrawable(resourceId);
+        setSelectedDateVerticalBar(drawable);
+    }
+
+    /**
+     * Sets the drawable for the vertical bar shown at the beginning and at
+     * the end of the selected date.
+     *
+     * @param drawable The vertical bar drawable.
+     */
+    public void setSelectedDateVerticalBar(Drawable drawable) {
+        if (mSelectedDateVerticalBar != drawable) {
+            mSelectedDateVerticalBar = drawable;
+            final int childCount = mListView.getChildCount();
+            for (int i = 0; i < childCount; i++) {
+                WeekView weekView = (WeekView) mListView.getChildAt(i);
+                if (weekView.mHasSelectedDay) {
+                    weekView.invalidate();
+                }
+            }
+        }
+    }
+
+    /**
+     * Gets the drawable for the vertical bar shown at the beginning and at
+     * the end of the selected date.
+     *
+     * @return The vertical bar drawable.
+     */
+    public Drawable getSelectedDateVerticalBar() {
+        return mSelectedDateVerticalBar;
+    }
+
+    /**
+     * Sets the text appearance for the week day abbreviation of the calendar header.
+     *
+     * @param resourceId The text appearance resource id.
+     */
+    public void setWeekDayTextAppearance(int resourceId) {
+        if (mWeekDayTextAppearanceResId != resourceId) {
+            mWeekDayTextAppearanceResId = resourceId;
+            setUpHeader();
+        }
+    }
+
+    /**
+     * Gets the text appearance for the week day abbreviation of the calendar header.
+     *
+     * @return The text appearance resource id.
+     */
+    public int getWeekDayTextAppearance() {
+        return mWeekDayTextAppearanceResId;
+    }
+
+    /**
+     * Sets the text appearance for the calendar dates.
+     *
+     * @param resourceId The text appearance resource id.
+     */
+    public void setDateTextAppearance(int resourceId) {
+        if (mDateTextAppearanceResId != resourceId) {
+            mDateTextAppearanceResId = resourceId;
+            updateDateTextSize();
+            invalidateAllWeekViews();
+        }
+    }
+
+    /**
+     * Gets the text appearance for the calendar dates.
+     *
+     * @return The text appearance resource id.
+     */
+    public int getDateTextAppearance() {
+        return mDateTextAppearanceResId;
+    }
+
     @Override
     public void setEnabled(boolean enabled) {
         mListView.setEnabled(enabled);
@@ -545,7 +774,7 @@
         }
         mShowWeekNumber = showWeekNumber;
         mAdapter.notifyDataSetChanged();
-        setUpHeader(DEFAULT_WEEK_DAY_TEXT_APPEARANCE_RES_ID);
+        setUpHeader();
     }
 
     /**
@@ -594,7 +823,7 @@
         mFirstDayOfWeek = firstDayOfWeek;
         mAdapter.init();
         mAdapter.notifyDataSetChanged();
-        setUpHeader(DEFAULT_WEEK_DAY_TEXT_APPEARANCE_RES_ID);
+        setUpHeader();
     }
 
     /**
@@ -655,6 +884,25 @@
         goTo(mTempDate, animate, true, center);
     }
 
+    private void updateDateTextSize() {
+        TypedArray dateTextAppearance = getContext().obtainStyledAttributes(
+                mDateTextAppearanceResId, R.styleable.TextAppearance);
+        mDateTextSize = dateTextAppearance.getDimensionPixelSize(
+                R.styleable.TextAppearance_textSize, DEFAULT_DATE_TEXT_SIZE);
+        dateTextAppearance.recycle();
+    }
+
+    /**
+     * Invalidates all week views.
+     */
+    private void invalidateAllWeekViews() {
+        final int childCount = mListView.getChildCount();
+        for (int i = 0; i < childCount; i++) {
+            View view = mListView.getChildAt(i);
+            view.invalidate();
+        }
+    }
+
     /**
      * Sets the current locale.
      *
@@ -727,7 +975,7 @@
     /**
      * Sets up the strings to be used by the header.
      */
-    private void setUpHeader(int weekDayTextAppearanceResId) {
+    private void setUpHeader() {
         mDayLabels = new String[mDaysPerWeek];
         for (int i = mFirstDayOfWeek, count = mFirstDayOfWeek + mDaysPerWeek; i < count; i++) {
             int calendarDay = (i > Calendar.SATURDAY) ? i - Calendar.SATURDAY : i;
@@ -743,8 +991,8 @@
         }
         for (int i = 1, count = mDayNamesHeader.getChildCount(); i < count; i++) {
             label = (TextView) mDayNamesHeader.getChildAt(i);
-            if (weekDayTextAppearanceResId > -1) {
-                label.setTextAppearance(mContext, weekDayTextAppearanceResId);
+            if (mWeekDayTextAppearanceResId > -1) {
+                label.setTextAppearance(mContext, mWeekDayTextAppearanceResId);
             }
             if (i < mDaysPerWeek + 1) {
                 label.setText(mDayLabels[i - 1]);
@@ -1198,6 +1446,12 @@
         // Quick lookup for checking which days are in the focus month
         private boolean[] mFocusDay;
 
+        // Whether this view has a focused day.
+        private boolean mHasFocusedDay;
+
+        // Whether this view has only focused days.
+        private boolean mHasUnfocusedDay;
+
         // The first day displayed by this item
         private Calendar mFirstDay;
 
@@ -1235,11 +1489,8 @@
         public WeekView(Context context) {
             super(context);
 
-            mHeight = (mListView.getHeight() - mListView.getPaddingTop() - mListView
-                    .getPaddingBottom()) / mShownWeekCount;
-
             // Sets up any standard paints that will be used
-            setPaintProperties();
+            initilaizePaints();
         }
 
         /**
@@ -1281,8 +1532,12 @@
             mFirstDay = (Calendar) mTempDate.clone();
             mMonthOfFirstWeekDay = mTempDate.get(Calendar.MONTH);
 
+            mHasUnfocusedDay = true;
             for (; i < mNumCells; i++) {
-                mFocusDay[i] = (mTempDate.get(Calendar.MONTH) == focusedMonth);
+                final boolean isFocusedDay = (mTempDate.get(Calendar.MONTH) == focusedMonth);
+                mFocusDay[i] = isFocusedDay;
+                mHasFocusedDay |= isFocusedDay;
+                mHasUnfocusedDay &= !isFocusedDay;
                 // do not draw dates outside the valid range to avoid user confusion
                 if (mTempDate.before(mMinDate) || mTempDate.after(mMaxDate)) {
                     mDayNumbers[i] = "";
@@ -1302,18 +1557,15 @@
         }
 
         /**
-         * Sets up the text and style properties for painting.
+         * Initialize the paint isntances.
          */
-        private void setPaintProperties() {
+        private void initilaizePaints() {
             mDrawPaint.setFakeBoldText(false);
             mDrawPaint.setAntiAlias(true);
-            mDrawPaint.setTextSize(mDateTextSize);
             mDrawPaint.setStyle(Style.FILL);
 
             mMonthNumDrawPaint.setFakeBoldText(true);
             mMonthNumDrawPaint.setAntiAlias(true);
-            mMonthNumDrawPaint.setTextSize(mDateTextSize);
-            mMonthNumDrawPaint.setColor(mFocusedMonthDateColor);
             mMonthNumDrawPaint.setStyle(Style.FILL);
             mMonthNumDrawPaint.setTextAlign(Align.CENTER);
         }
@@ -1369,7 +1621,7 @@
         @Override
         protected void onDraw(Canvas canvas) {
             drawBackground(canvas);
-            drawWeekNumbers(canvas);
+            drawWeekNumbersAndDates(canvas);
             drawWeekSeparators(canvas);
             drawSelectedDateVerticalBars(canvas);
         }
@@ -1401,12 +1653,13 @@
          *
          * @param canvas The canvas to draw on
          */
-        private void drawWeekNumbers(Canvas canvas) {
+        private void drawWeekNumbersAndDates(Canvas canvas) {
             float textHeight = mDrawPaint.getTextSize();
             int y = (int) ((mHeight + textHeight) / 2) - mWeekSeperatorLineWidth;
             int nDays = mNumCells;
 
             mDrawPaint.setTextAlign(Align.CENTER);
+            mDrawPaint.setTextSize(mDateTextSize);
             int i = 0;
             int divisor = 2 * nDays;
             if (mShowWeekNumber) {
@@ -1487,6 +1740,8 @@
 
         @Override
         protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+            mHeight = (mListView.getHeight() - mListView.getPaddingTop() - mListView
+                    .getPaddingBottom()) / mShownWeekCount;
             setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec), mHeight);
         }
     }
diff --git a/core/java/android/widget/DatePicker.java b/core/java/android/widget/DatePicker.java
index 110c8f3..fd93980 100644
--- a/core/java/android/widget/DatePicker.java
+++ b/core/java/android/widget/DatePicker.java
@@ -162,7 +162,7 @@
         int endYear = attributesArray.getInt(R.styleable.DatePicker_endYear, DEFAULT_END_YEAR);
         String minDate = attributesArray.getString(R.styleable.DatePicker_minDate);
         String maxDate = attributesArray.getString(R.styleable.DatePicker_maxDate);
-        int layoutResourceId = attributesArray.getResourceId(R.styleable.DatePicker_layout,
+        int layoutResourceId = attributesArray.getResourceId(R.styleable.DatePicker_internalLayout,
                 R.layout.date_picker);
         attributesArray.recycle();
 
diff --git a/core/java/android/widget/LinearLayout.java b/core/java/android/widget/LinearLayout.java
index b5deec7..a1bea43 100644
--- a/core/java/android/widget/LinearLayout.java
+++ b/core/java/android/widget/LinearLayout.java
@@ -309,7 +309,7 @@
             if (child != null && child.getVisibility() != GONE) {
                 if (hasDividerBeforeChildAt(i)) {
                     final LayoutParams lp = (LayoutParams) child.getLayoutParams();
-                    final int top = child.getTop() - lp.topMargin;
+                    final int top = child.getTop() - lp.topMargin - mDividerHeight;
                     drawHorizontalDivider(canvas, top);
                 }
             }
@@ -336,7 +336,7 @@
             if (child != null && child.getVisibility() != GONE) {
                 if (hasDividerBeforeChildAt(i)) {
                     final LayoutParams lp = (LayoutParams) child.getLayoutParams();
-                    final int left = child.getLeft() - lp.leftMargin;
+                    final int left = child.getLeft() - lp.leftMargin - mDividerWidth;
                     drawVerticalDivider(canvas, left);
                 }
             }
diff --git a/core/java/android/widget/NumberPicker.java b/core/java/android/widget/NumberPicker.java
index 6405ee9..3335da0 100644
--- a/core/java/android/widget/NumberPicker.java
+++ b/core/java/android/widget/NumberPicker.java
@@ -559,17 +559,17 @@
                 getResources().getDisplayMetrics());
         mSelectionDividerHeight = attributesArray.getDimensionPixelSize(
                 R.styleable.NumberPicker_selectionDividerHeight, defSelectionDividerHeight);
-        mMinHeight = attributesArray.getDimensionPixelSize(R.styleable.NumberPicker_minHeight,
-                SIZE_UNSPECIFIED);
-        mMaxHeight = attributesArray.getDimensionPixelSize(R.styleable.NumberPicker_maxHeight,
-                SIZE_UNSPECIFIED);
+        mMinHeight = attributesArray.getDimensionPixelSize(
+                R.styleable.NumberPicker_internalMinHeight, SIZE_UNSPECIFIED);
+        mMaxHeight = attributesArray.getDimensionPixelSize(
+                R.styleable.NumberPicker_internalMaxHeight, SIZE_UNSPECIFIED);
         if (mMinHeight != SIZE_UNSPECIFIED && mMaxHeight != SIZE_UNSPECIFIED
                 && mMinHeight > mMaxHeight) {
             throw new IllegalArgumentException("minHeight > maxHeight");
         }
-        mMinWidth = attributesArray.getDimensionPixelSize(R.styleable.NumberPicker_minWidth,
+        mMinWidth = attributesArray.getDimensionPixelSize(R.styleable.NumberPicker_internalMinWidth,
                 SIZE_UNSPECIFIED);
-        mMaxWidth = attributesArray.getDimensionPixelSize(R.styleable.NumberPicker_maxWidth,
+        mMaxWidth = attributesArray.getDimensionPixelSize(R.styleable.NumberPicker_internalMaxWidth,
                 SIZE_UNSPECIFIED);
         if (mMinWidth != SIZE_UNSPECIFIED && mMaxWidth != SIZE_UNSPECIFIED
                 && mMinWidth > mMaxWidth) {
diff --git a/core/java/android/widget/ProgressBar.java b/core/java/android/widget/ProgressBar.java
index ace3f60..e298acb 100644
--- a/core/java/android/widget/ProgressBar.java
+++ b/core/java/android/widget/ProgressBar.java
@@ -39,6 +39,7 @@
 import android.os.Parcelable;
 import android.os.SystemClock;
 import android.util.AttributeSet;
+import android.view.Choreographer;
 import android.view.Gravity;
 import android.view.RemotableViewMethod;
 import android.view.View;
@@ -189,7 +190,6 @@
 @RemoteView
 public class ProgressBar extends View {
     private static final int MAX_LEVEL = 10000;
-    private static final int ANIMATION_RESOLUTION = 200;
     private static final int TIMEOUT_SEND_ACCESSIBILITY_EVENT = 200;
 
     int mMinWidth;
@@ -216,12 +216,9 @@
     private RefreshProgressRunnable mRefreshProgressRunnable;
     private long mUiThreadId;
     private boolean mShouldStartAnimationDrawable;
-    private long mLastDrawTime;
 
     private boolean mInDrawing;
 
-    private int mAnimationResolution;
-
     private AccessibilityEventSender mAccessibilityEventSender;
 
     /**
@@ -299,9 +296,6 @@
         setIndeterminate(mOnlyIndeterminate || a.getBoolean(
                 R.styleable.ProgressBar_indeterminate, mIndeterminate));
 
-        mAnimationResolution = a.getInteger(R.styleable.ProgressBar_animationResolution,
-                ANIMATION_RESOLUTION);
-
         a.recycle();
     }
 
@@ -988,10 +982,7 @@
                 } finally {
                     mInDrawing = false;
                 }
-                if (SystemClock.uptimeMillis() - mLastDrawTime >= mAnimationResolution) {
-                    mLastDrawTime = SystemClock.uptimeMillis();
-                    postInvalidateDelayed(mAnimationResolution);
-                }
+                postInvalidateOnAnimation();
             }
             d.draw(canvas);
             canvas.restore();
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index 62afd61..55acb74 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -1217,7 +1217,7 @@
     /**
      * Equivalent to calling ImageView.setImageBitmap
      * 
-     * @param viewId The id of the view whose drawable should change
+     * @param viewId The id of the view whose bitmap should change
      * @param bitmap The new Bitmap for the drawable
      */
     public void setImageViewBitmap(int viewId, Bitmap bitmap) {
@@ -1240,7 +1240,7 @@
      * and {@link Chronometer#start Chronometer.start()} or
      * {@link Chronometer#stop Chronometer.stop()}.
      * 
-     * @param viewId The id of the view whose text should change
+     * @param viewId The id of the {@link Chronometer} to change
      * @param base The time at which the timer would have read 0:00.  This
      *             time should be based off of
      *             {@link android.os.SystemClock#elapsedRealtime SystemClock.elapsedRealtime()}.
@@ -1261,7 +1261,7 @@
      *
      * If indeterminate is true, then the values for max and progress are ignored.
      * 
-     * @param viewId The id of the view whose text should change
+     * @param viewId The id of the {@link ProgressBar} to change
      * @param max The 100% value for the progress bar
      * @param progress The current value of the progress bar.
      * @param indeterminate True if the progress bar is indeterminate, 
@@ -1367,7 +1367,7 @@
     /**
      * Equivalent to calling {@link android.widget.TextView#setTextColor(int)}.
      * 
-     * @param viewId The id of the view whose text should change
+     * @param viewId The id of the view whose text color should change
      * @param color Sets the text color for all the states (normal, selected,
      *            focused) to be this color.
      */
@@ -1380,7 +1380,7 @@
      *
      * @param appWidgetId The id of the app widget which contains the specified view. (This
      *      parameter is ignored in this deprecated method)
-     * @param viewId The id of the view whose text should change
+     * @param viewId The id of the {@link AbsListView}
      * @param intent The intent of the service which will be
      *            providing data to the RemoteViewsAdapter
      * @deprecated This method has been deprecated. See
@@ -1395,7 +1395,7 @@
      * Equivalent to calling {@link android.widget.AbsListView#setRemoteViewsAdapter(Intent)}.
      * Can only be used for App Widgets.
      *
-     * @param viewId The id of the view whose text should change
+     * @param viewId The id of the {@link AbsListView}
      * @param intent The intent of the service which will be
      *            providing data to the RemoteViewsAdapter
      */
@@ -1406,7 +1406,7 @@
     /**
      * Equivalent to calling {@link android.widget.AbsListView#smoothScrollToPosition(int, int)}.
      *
-     * @param viewId The id of the view whose text should change
+     * @param viewId The id of the view to change
      * @param position Scroll to this adapter position
      */
     public void setScrollPosition(int viewId, int position) {
@@ -1416,7 +1416,7 @@
     /**
      * Equivalent to calling {@link android.widget.AbsListView#smoothScrollToPosition(int, int)}.
      *
-     * @param viewId The id of the view whose text should change
+     * @param viewId The id of the view to change
      * @param offset Scroll by this adapter position offset
      */
     public void setRelativeScrollPosition(int viewId, int offset) {
@@ -1426,7 +1426,7 @@
     /**
      * Call a method taking one boolean on a view in the layout for this RemoteViews.
      *
-     * @param viewId The id of the view whose text should change
+     * @param viewId The id of the view on which to call the method.
      * @param methodName The name of the method to call.
      * @param value The value to pass to the method.
      */
@@ -1437,7 +1437,7 @@
     /**
      * Call a method taking one byte on a view in the layout for this RemoteViews.
      *
-     * @param viewId The id of the view whose text should change
+     * @param viewId The id of the view on which to call the method.
      * @param methodName The name of the method to call.
      * @param value The value to pass to the method.
      */
@@ -1448,7 +1448,7 @@
     /**
      * Call a method taking one short on a view in the layout for this RemoteViews.
      *
-     * @param viewId The id of the view whose text should change
+     * @param viewId The id of the view on which to call the method.
      * @param methodName The name of the method to call.
      * @param value The value to pass to the method.
      */
@@ -1459,7 +1459,7 @@
     /**
      * Call a method taking one int on a view in the layout for this RemoteViews.
      *
-     * @param viewId The id of the view whose text should change
+     * @param viewId The id of the view on which to call the method.
      * @param methodName The name of the method to call.
      * @param value The value to pass to the method.
      */
@@ -1470,7 +1470,7 @@
     /**
      * Call a method taking one long on a view in the layout for this RemoteViews.
      *
-     * @param viewId The id of the view whose text should change
+     * @param viewId The id of the view on which to call the method.
      * @param methodName The name of the method to call.
      * @param value The value to pass to the method.
      */
@@ -1481,7 +1481,7 @@
     /**
      * Call a method taking one float on a view in the layout for this RemoteViews.
      *
-     * @param viewId The id of the view whose text should change
+     * @param viewId The id of the view on which to call the method.
      * @param methodName The name of the method to call.
      * @param value The value to pass to the method.
      */
@@ -1492,7 +1492,7 @@
     /**
      * Call a method taking one double on a view in the layout for this RemoteViews.
      *
-     * @param viewId The id of the view whose text should change
+     * @param viewId The id of the view on which to call the method.
      * @param methodName The name of the method to call.
      * @param value The value to pass to the method.
      */
@@ -1503,7 +1503,7 @@
     /**
      * Call a method taking one char on a view in the layout for this RemoteViews.
      *
-     * @param viewId The id of the view whose text should change
+     * @param viewId The id of the view on which to call the method.
      * @param methodName The name of the method to call.
      * @param value The value to pass to the method.
      */
@@ -1514,7 +1514,7 @@
     /**
      * Call a method taking one String on a view in the layout for this RemoteViews.
      *
-     * @param viewId The id of the view whose text should change
+     * @param viewId The id of the view on which to call the method.
      * @param methodName The name of the method to call.
      * @param value The value to pass to the method.
      */
@@ -1525,7 +1525,7 @@
     /**
      * Call a method taking one CharSequence on a view in the layout for this RemoteViews.
      *
-     * @param viewId The id of the view whose text should change
+     * @param viewId The id of the view on which to call the method.
      * @param methodName The name of the method to call.
      * @param value The value to pass to the method.
      */
@@ -1536,7 +1536,7 @@
     /**
      * Call a method taking one Uri on a view in the layout for this RemoteViews.
      *
-     * @param viewId The id of the view whose text should change
+     * @param viewId The id of the view on which to call the method.
      * @param methodName The name of the method to call.
      * @param value The value to pass to the method.
      */
@@ -1550,7 +1550,7 @@
      * <p class="note">The bitmap will be flattened into the parcel if this object is
      * sent across processes, so it may end up using a lot of memory, and may be fairly slow.</p>
      *
-     * @param viewId The id of the view whose text should change
+     * @param viewId The id of the view on which to call the method.
      * @param methodName The name of the method to call.
      * @param value The value to pass to the method.
      */
@@ -1561,7 +1561,7 @@
     /**
      * Call a method taking one Bundle on a view in the layout for this RemoteViews.
      *
-     * @param viewId The id of the view whose text should change
+     * @param viewId The id of the view on which to call the method.
      * @param methodName The name of the method to call.
      * @param value The value to pass to the method.
      */
@@ -1570,10 +1570,11 @@
     }
 
     /**
+     * Call a method taking one Intent on a view in the layout for this RemoteViews.
      *
-     * @param viewId
-     * @param methodName
-     * @param value
+     * @param viewId The id of the view on which to call the method.
+     * @param methodName The name of the method to call.
+     * @param value The {@link android.content.Intent} to pass the method.
      */
     public void setIntent(int viewId, String methodName, Intent value) {
         addAction(new ReflectionAction(viewId, methodName, ReflectionAction.INTENT, value));
diff --git a/core/java/android/widget/SpellChecker.java b/core/java/android/widget/SpellChecker.java
index df2996c..9afaee3 100644
--- a/core/java/android/widget/SpellChecker.java
+++ b/core/java/android/widget/SpellChecker.java
@@ -290,7 +290,7 @@
 
     private SpellCheckSpan onGetSuggestionsInternal(
             SuggestionsInfo suggestionsInfo, int offset, int length) {
-        if (suggestionsInfo.getCookie() != mCookie) {
+        if (suggestionsInfo == null || suggestionsInfo.getCookie() != mCookie) {
             return null;
         }
         final Editable editable = (Editable) mTextView.getText();
@@ -335,9 +335,15 @@
 
         for (int i = 0; i < results.length; ++i) {
             final SentenceSuggestionsInfo ssi = results[i];
+            if (ssi == null) {
+                continue;
+            }
             SpellCheckSpan spellCheckSpan = null;
             for (int j = 0; j < ssi.getSuggestionsCount(); ++j) {
                 final SuggestionsInfo suggestionsInfo = ssi.getSuggestionsInfoAt(j);
+                if (suggestionsInfo == null) {
+                    continue;
+                }
                 final int offset = ssi.getOffsetAt(j);
                 final int length = ssi.getLengthAt(j);
                 final SpellCheckSpan scs = onGetSuggestionsInternal(
@@ -488,11 +494,15 @@
                     editable.removeSpan(mRange);
                     return;
                 }
+                // Stop spell checking when there are no characters in the range.
+                if (wordEnd < start) {
+                    return;
+                }
                 wordStart = regionEnd;
                 // TODO: Find the start position of the sentence.
                 // Set span with the context
-                final int spellCheckStart =  Math.min(
-                        start, Math.max(wordStart, regionEnd - WORD_ITERATOR_INTERVAL));
+                final int spellCheckStart =  Math.max(
+                        0, Math.min(wordStart, regionEnd - WORD_ITERATOR_INTERVAL));
                 if (regionEnd <= spellCheckStart) {
                     return;
                 }
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 56a0d1e..47e10cc 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -216,6 +216,8 @@
  * @attr ref android.R.styleable#TextView_drawableBottom
  * @attr ref android.R.styleable#TextView_drawableRight
  * @attr ref android.R.styleable#TextView_drawableLeft
+ * @attr ref android.R.styleable#TextView_drawableStart
+ * @attr ref android.R.styleable#TextView_drawableEnd
  * @attr ref android.R.styleable#TextView_drawablePadding
  * @attr ref android.R.styleable#TextView_lineSpacingExtra
  * @attr ref android.R.styleable#TextView_lineSpacingMultiplier
@@ -1520,8 +1522,6 @@
     /**
      * Returns the start padding of the view, plus space for the start
      * Drawable if any.
-     *
-     * @hide
      */
     public int getCompoundPaddingStart() {
         resolveDrawables();
@@ -1537,8 +1537,6 @@
     /**
      * Returns the end padding of the view, plus space for the end
      * Drawable if any.
-     *
-     * @hide
      */
     public int getCompoundPaddingEnd() {
         resolveDrawables();
@@ -1636,8 +1634,6 @@
     /**
      * Returns the total start padding of the view, including the start
      * Drawable if any.
-     *
-     * @hide
      */
     public int getTotalPaddingStart() {
         return getCompoundPaddingStart();
@@ -1646,8 +1642,6 @@
     /**
      * Returns the total end padding of the view, including the end
      * Drawable if any.
-     *
-     * @hide
      */
     public int getTotalPaddingEnd() {
         return getCompoundPaddingEnd();
@@ -1849,8 +1843,6 @@
      * @attr ref android.R.styleable#TextView_drawableTop
      * @attr ref android.R.styleable#TextView_drawableEnd
      * @attr ref android.R.styleable#TextView_drawableBottom
-     *
-     * @hide
      */
     public void setCompoundDrawablesRelative(Drawable start, Drawable top,
                                      Drawable end, Drawable bottom) {
@@ -1972,8 +1964,6 @@
      * @attr ref android.R.styleable#TextView_drawableTop
      * @attr ref android.R.styleable#TextView_drawableEnd
      * @attr ref android.R.styleable#TextView_drawableBottom
-     *
-     * @hide
      */
     public void setCompoundDrawablesRelativeWithIntrinsicBounds(int start, int top, int end,
             int bottom) {
@@ -1996,8 +1986,6 @@
      * @attr ref android.R.styleable#TextView_drawableTop
      * @attr ref android.R.styleable#TextView_drawableEnd
      * @attr ref android.R.styleable#TextView_drawableBottom
-     *
-     * @hide
      */
     public void setCompoundDrawablesRelativeWithIntrinsicBounds(Drawable start, Drawable top,
             Drawable end, Drawable bottom) {
@@ -2034,8 +2022,6 @@
 
     /**
      * Returns drawables for the start, top, end, and bottom borders.
-     *
-     * @hide
      */
     public Drawable[] getCompoundDrawablesRelative() {
         final Drawables dr = mDrawables;
@@ -6946,7 +6932,6 @@
      */
     protected void onSelectionChanged(int selStart, int selEnd) {
         sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED);
-        if (mEditor != null) getEditor().mTextDisplayListIsValid = false;
     }
 
     /**
@@ -7772,18 +7757,6 @@
                 hasPrimaryClip());
     }
 
-    private static long packRangeInLong(int start, int end) {
-        return (((long) start) << 32) | end;
-    }
-
-    private static int extractRangeStartFromLong(long range) {
-        return (int) (range >>> 32);
-    }
-
-    private static int extractRangeEndFromLong(long range) {
-        return (int) (range & 0x00000000FFFFFFFFL);
-    }
-
     private boolean selectAll() {
         final int length = mText.length();
         Selection.setSelection((Spannable) mText, 0, length);
@@ -7822,8 +7795,8 @@
         }
 
         long lastTouchOffsets = getLastTouchOffsets();
-        final int minOffset = extractRangeStartFromLong(lastTouchOffsets);
-        final int maxOffset = extractRangeEndFromLong(lastTouchOffsets);
+        final int minOffset = TextUtils.unpackRangeStartFromLong(lastTouchOffsets);
+        final int maxOffset = TextUtils.unpackRangeEndFromLong(lastTouchOffsets);
 
         // Safety check in case standard touch event handling has been bypassed
         if (minOffset < 0 || minOffset >= mText.length()) return false;
@@ -7848,8 +7821,8 @@
                     selectionStart == selectionEnd) {
                 // Possible when the word iterator does not properly handle the text's language
                 long range = getCharRange(minOffset);
-                selectionStart = extractRangeStartFromLong(range);
-                selectionEnd = extractRangeEndFromLong(range);
+                selectionStart = TextUtils.unpackRangeStartFromLong(range);
+                selectionEnd = TextUtils.unpackRangeEndFromLong(range);
             }
         }
 
@@ -7897,30 +7870,30 @@
             final char currentChar = mText.charAt(offset);
             final char nextChar = mText.charAt(offset + 1);
             if (Character.isSurrogatePair(currentChar, nextChar)) {
-                return packRangeInLong(offset,  offset + 2);
+                return TextUtils.packRangeInLong(offset,  offset + 2);
             }
         }
         if (offset < textLength) {
-            return packRangeInLong(offset,  offset + 1);
+            return TextUtils.packRangeInLong(offset,  offset + 1);
         }
         if (offset - 2 >= 0) {
             final char previousChar = mText.charAt(offset - 1);
             final char previousPreviousChar = mText.charAt(offset - 2);
             if (Character.isSurrogatePair(previousPreviousChar, previousChar)) {
-                return packRangeInLong(offset - 2,  offset);
+                return TextUtils.packRangeInLong(offset - 2,  offset);
             }
         }
         if (offset - 1 >= 0) {
-            return packRangeInLong(offset - 1,  offset);
+            return TextUtils.packRangeInLong(offset - 1,  offset);
         }
-        return packRangeInLong(offset,  offset);
+        return TextUtils.packRangeInLong(offset,  offset);
     }
 
     private long getLastTouchOffsets() {
         SelectionModifierCursorController selectionController = getSelectionController();
         final int minOffset = selectionController.getMinTouchOffset();
         final int maxOffset = selectionController.getMaxTouchOffset();
-        return packRangeInLong(minOffset, maxOffset);
+        return TextUtils.packRangeInLong(minOffset, maxOffset);
     }
 
     @Override
@@ -8111,7 +8084,7 @@
             }
         }
 
-        return packRangeInLong(min, max);
+        return TextUtils.packRangeInLong(min, max);
     }
 
     private DragShadowBuilder getTextThumbnailBuilder(CharSequence text) {
@@ -8470,8 +8443,8 @@
                 if (paste != null) {
                     if (!didFirst) {
                         long minMax = prepareSpacesAroundPaste(min, max, paste);
-                        min = extractRangeStartFromLong(minMax);
-                        max = extractRangeEndFromLong(minMax);
+                        min = TextUtils.unpackRangeStartFromLong(minMax);
+                        max = TextUtils.unpackRangeEndFromLong(minMax);
                         Selection.setSelection((Spannable) mText, max);
                         ((Editable) mText).replace(min, max, paste);
                         didFirst = true;
@@ -8630,8 +8603,8 @@
 
         final int originalLength = mText.length();
         long minMax = prepareSpacesAroundPaste(offset, offset, content);
-        int min = extractRangeStartFromLong(minMax);
-        int max = extractRangeEndFromLong(minMax);
+        int min = TextUtils.unpackRangeStartFromLong(minMax);
+        int max = TextUtils.unpackRangeEndFromLong(minMax);
 
         Selection.setSelection((Spannable) mText, max);
         replaceText_internal(min, max, content);
@@ -9175,7 +9148,7 @@
                 int top = getExtendedPaddingTop() + getVerticalOffset(true);
 
                 if (delayed) {
-                    TextView.this.postInvalidateDelayed(16, // 60 Hz update
+                    TextView.this.postInvalidateOnAnimation(
                             left + (int) TEMP_RECTF.left, top + (int) TEMP_RECTF.top,
                             left + (int) TEMP_RECTF.right, top + (int) TEMP_RECTF.bottom);
                 } else {
@@ -11667,33 +11640,7 @@
             }
 
             if (canHaveDisplayList() && canvas.isHardwareAccelerated()) {
-                final int width = mRight - mLeft;
-                final int height = mBottom - mTop;
-
-                if (mTextDisplayList == null || !mTextDisplayList.isValid() ||
-                        !mTextDisplayListIsValid) {
-                    if (mTextDisplayList == null) {
-                        mTextDisplayList = getHardwareRenderer().createDisplayList("Text");
-                    }
-
-                    final HardwareCanvas hardwareCanvas = mTextDisplayList.start();
-                    try {
-                        hardwareCanvas.setViewport(width, height);
-                        // The dirty rect should always be null for a display list
-                        hardwareCanvas.onPreDraw(null);
-                        hardwareCanvas.translate(-mScrollX, -mScrollY);
-                        layout.draw(hardwareCanvas, highlight, mHighlightPaint, cursorOffsetVertical);
-                        hardwareCanvas.translate(mScrollX, mScrollY);
-                    } finally {
-                        hardwareCanvas.onPostDraw();
-                        mTextDisplayList.end();
-                        mTextDisplayListIsValid = true;
-                    }
-                }
-                canvas.translate(mScrollX, mScrollY);
-                ((HardwareCanvas) canvas).drawDisplayList(mTextDisplayList, width, height, null,
-                        DisplayList.FLAG_CLIP_CHILDREN);
-                canvas.translate(-mScrollX, -mScrollY);
+                drawHardwareAccelerated(canvas, layout, highlight, cursorOffsetVertical);
             } else {
                 layout.draw(canvas, highlight, mHighlightPaint, cursorOffsetVertical);
             }
@@ -11704,6 +11651,46 @@
             }
         }
 
+        private void drawHardwareAccelerated(Canvas canvas, Layout layout, Path highlight,
+                int cursorOffsetVertical) {
+            final int width = mRight - mLeft;
+            final int height = mBottom - mTop;
+
+            final long lineRange = layout.getLineRangeForDraw(canvas);
+            int firstLine = TextUtils.unpackRangeStartFromLong(lineRange);
+            int lastLine = TextUtils.unpackRangeEndFromLong(lineRange);
+            if (lastLine < 0) return;
+
+            layout.drawBackground(canvas, highlight, mHighlightPaint, cursorOffsetVertical,
+                    firstLine, lastLine);
+
+            if (mTextDisplayList == null || !mTextDisplayList.isValid() ||
+                    !mTextDisplayListIsValid) {
+                if (mTextDisplayList == null) {
+                    mTextDisplayList = getHardwareRenderer().createDisplayList("Text");
+                }
+
+                final HardwareCanvas hardwareCanvas = mTextDisplayList.start();
+                try {
+                    hardwareCanvas.setViewport(width, height);
+                    // The dirty rect should always be null for a display list
+                    hardwareCanvas.onPreDraw(null);
+                    hardwareCanvas.translate(-mScrollX, -mScrollY);
+                    layout.drawText(hardwareCanvas, firstLine, lastLine);
+                    //layout.draw(hardwareCanvas, highlight, mHighlightPaint, cursorOffsetVertical);
+                    hardwareCanvas.translate(mScrollX, mScrollY);
+                } finally {
+                    hardwareCanvas.onPostDraw();
+                    mTextDisplayList.end();
+                    mTextDisplayListIsValid = true;
+                }
+            }
+            canvas.translate(mScrollX, mScrollY);
+            ((HardwareCanvas) canvas).drawDisplayList(mTextDisplayList, width, height, null,
+                    DisplayList.FLAG_CLIP_CHILDREN);
+            canvas.translate(-mScrollX, -mScrollY);
+        }
+
         private void drawCursor(Canvas canvas, int cursorOffsetVertical) {
             final boolean translate = cursorOffsetVertical != 0;
             if (translate) canvas.translate(0, cursorOffsetVertical);
diff --git a/core/java/android/widget/TimePicker.java b/core/java/android/widget/TimePicker.java
index ef1d7d0..7eff1aa 100644
--- a/core/java/android/widget/TimePicker.java
+++ b/core/java/android/widget/TimePicker.java
@@ -136,7 +136,7 @@
         TypedArray attributesArray = context.obtainStyledAttributes(
                 attrs, R.styleable.TimePicker, defStyle, 0);
         int layoutResourceId = attributesArray.getResourceId(
-                R.styleable.TimePicker_layout, R.layout.time_picker);
+                R.styleable.TimePicker_internalLayout, R.layout.time_picker);
         attributesArray.recycle();
 
         LayoutInflater inflater = (LayoutInflater) context.getSystemService(
diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index 3fba1be..0563846 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -17,6 +17,8 @@
 package com.android.internal.app;
 
 import com.android.internal.R;
+import com.android.internal.content.PackageMonitor;
+
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.DialogInterface;
@@ -58,6 +60,12 @@
     private TextView mClearDefaultHint;
     private PackageManager mPm;
 
+    private final PackageMonitor mPackageMonitor = new PackageMonitor() {
+        @Override public void onSomePackagesChanged() {
+            mAdapter.handlePackagesChanged();
+        }
+    };
+
     private Intent makeMyIntent() {
         Intent intent = new Intent(getIntent());
         // The resolver activity is set to be hidden from recent tasks.
@@ -88,6 +96,8 @@
         ap.mTitle = title;
         ap.mOnClickListener = this;
 
+        mPackageMonitor.register(this, false);
+
         if (alwaysUseOption) {
             LayoutInflater inflater = (LayoutInflater) getSystemService(
                     Context.LAYOUT_INFLATER_SERVICE);
@@ -114,6 +124,19 @@
         setupAlert();
     }
 
+    @Override
+    protected void onRestart() {
+        super.onRestart();
+        mPackageMonitor.register(this, false);
+        mAdapter.handlePackagesChanged();
+    }
+
+    @Override
+    protected void onStop() {
+        super.onStop();
+        mPackageMonitor.unregister();
+    }
+
     public void onClick(DialogInterface dialog, int which) {
         ResolveInfo ri = mAdapter.resolveInfoForPosition(which);
         Intent intent = mAdapter.intentForPosition(which);
@@ -225,29 +248,48 @@
     }
 
     private final class ResolveListAdapter extends BaseAdapter {
+        private final Intent[] mInitialIntents;
+        private final List<ResolveInfo> mBaseResolveList;
         private final Intent mIntent;
         private final LayoutInflater mInflater;
 
+        private List<ResolveInfo> mCurrentResolveList;
         private List<DisplayResolveInfo> mList;
 
         public ResolveListAdapter(Context context, Intent intent,
                 Intent[] initialIntents, List<ResolveInfo> rList) {
             mIntent = new Intent(intent);
             mIntent.setComponent(null);
+            mInitialIntents = initialIntents;
+            mBaseResolveList = rList;
             mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+            rebuildList();
+        }
 
-            if (rList == null) {
-                rList = mPm.queryIntentActivities(
-                        intent, PackageManager.MATCH_DEFAULT_ONLY
+        public void handlePackagesChanged() {
+            rebuildList();
+            notifyDataSetChanged();
+            if (mList.size() <= 0) {
+                // We no longer have any items...  just finish the activity.
+                finish();
+            }
+        }
+
+        private void rebuildList() {
+            if (mBaseResolveList != null) {
+                mCurrentResolveList = mBaseResolveList;
+            } else {
+                mCurrentResolveList = mPm.queryIntentActivities(
+                        mIntent, PackageManager.MATCH_DEFAULT_ONLY
                         | (mAlwaysCheck != null ? PackageManager.GET_RESOLVED_FILTER : 0));
             }
             int N;
-            if ((rList != null) && ((N = rList.size()) > 0)) {
+            if ((mCurrentResolveList != null) && ((N = mCurrentResolveList.size()) > 0)) {
                 // Only display the first matches that are either of equal
                 // priority or have asked to be default options.
-                ResolveInfo r0 = rList.get(0);
+                ResolveInfo r0 = mCurrentResolveList.get(0);
                 for (int i=1; i<N; i++) {
-                    ResolveInfo ri = rList.get(i);
+                    ResolveInfo ri = mCurrentResolveList.get(i);
                     if (false) Log.v(
                         "ResolveListActivity",
                         r0.activityInfo.name + "=" +
@@ -257,7 +299,7 @@
                    if (r0.priority != ri.priority ||
                         r0.isDefault != ri.isDefault) {
                         while (i < N) {
-                            rList.remove(i);
+                            mCurrentResolveList.remove(i);
                             N--;
                         }
                     }
@@ -265,15 +307,15 @@
                 if (N > 1) {
                     ResolveInfo.DisplayNameComparator rComparator =
                             new ResolveInfo.DisplayNameComparator(mPm);
-                    Collections.sort(rList, rComparator);
+                    Collections.sort(mCurrentResolveList, rComparator);
                 }
                 
                 mList = new ArrayList<DisplayResolveInfo>();
                 
                 // First put the initial items at the top.
-                if (initialIntents != null) {
-                    for (int i=0; i<initialIntents.length; i++) {
-                        Intent ii = initialIntents[i];
+                if (mInitialIntents != null) {
+                    for (int i=0; i<mInitialIntents.length; i++) {
+                        Intent ii = mInitialIntents[i];
                         if (ii == null) {
                             continue;
                         }
@@ -300,14 +342,14 @@
                 
                 // Check for applications with same name and use application name or
                 // package name if necessary
-                r0 = rList.get(0);
+                r0 = mCurrentResolveList.get(0);
                 int start = 0;
                 CharSequence r0Label =  r0.loadLabel(mPm);
                 for (int i = 1; i < N; i++) {
                     if (r0Label == null) {
                         r0Label = r0.activityInfo.packageName;
                     }
-                    ResolveInfo ri = rList.get(i);
+                    ResolveInfo ri = mCurrentResolveList.get(i);
                     CharSequence riLabel = ri.loadLabel(mPm);
                     if (riLabel == null) {
                         riLabel = ri.activityInfo.packageName;
@@ -315,13 +357,13 @@
                     if (riLabel.equals(r0Label)) {
                         continue;
                     }
-                    processGroup(rList, start, (i-1), r0, r0Label);
+                    processGroup(mCurrentResolveList, start, (i-1), r0, r0Label);
                     r0 = ri;
                     r0Label = riLabel;
                     start = i;
                 }
                 // Process last group
-                processGroup(rList, start, (N-1), r0, r0Label);
+                processGroup(mCurrentResolveList, start, (N-1), r0, r0Label);
             }
         }
 
diff --git a/core/java/com/android/internal/view/BaseIWindow.java b/core/java/com/android/internal/view/BaseIWindow.java
index b227700..e695f8e 100644
--- a/core/java/com/android/internal/view/BaseIWindow.java
+++ b/core/java/com/android/internal/view/BaseIWindow.java
@@ -49,6 +49,9 @@
     public void dispatchGetNewSurface() {
     }
 
+    public void dispatchScreenStatus(boolean on) {
+    }
+
     public void windowFocusChanged(boolean hasFocus, boolean touchEnabled) {
     }
 
diff --git a/core/java/com/android/internal/view/menu/ActionMenuItemView.java b/core/java/com/android/internal/view/menu/ActionMenuItemView.java
index a10d241..d5c2018 100644
--- a/core/java/com/android/internal/view/menu/ActionMenuItemView.java
+++ b/core/java/com/android/internal/view/menu/ActionMenuItemView.java
@@ -27,28 +27,26 @@
 import android.view.MotionEvent;
 import android.view.View;
 import android.view.accessibility.AccessibilityEvent;
-import android.widget.Button;
-import android.widget.ImageButton;
-import android.widget.LinearLayout;
+import android.widget.TextView;
 import android.widget.Toast;
 
 /**
  * @hide
  */
-public class ActionMenuItemView extends LinearLayout
+public class ActionMenuItemView extends TextView
         implements MenuView.ItemView, View.OnClickListener, View.OnLongClickListener,
         ActionMenuView.ActionMenuChildView {
     private static final String TAG = "ActionMenuItemView";
 
     private MenuItemImpl mItemData;
     private CharSequence mTitle;
+    private Drawable mIcon;
     private MenuBuilder.ItemInvoker mItemInvoker;
 
-    private ImageButton mImageButton;
-    private Button mTextButton;
     private boolean mAllowTextWithIcon;
     private boolean mExpandedFormat;
     private int mMinWidth;
+    private int mSavedPaddingLeft;
 
     public ActionMenuItemView(Context context) {
         this(context, null);
@@ -68,17 +66,12 @@
         mMinWidth = a.getDimensionPixelSize(
                 com.android.internal.R.styleable.ActionMenuItemView_minWidth, 0);
         a.recycle();
-    }
 
-    @Override
-    public void onFinishInflate() {
-        mImageButton = (ImageButton) findViewById(com.android.internal.R.id.imageButton);
-        mTextButton = (Button) findViewById(com.android.internal.R.id.textButton);
-        mImageButton.setOnClickListener(this);
-        mTextButton.setOnClickListener(this);
-        mImageButton.setOnLongClickListener(this);
         setOnClickListener(this);
         setOnLongClickListener(this);
+
+        // Save the inflated padding for later, we'll need it.
+        mSavedPaddingLeft = getPaddingLeft();
     }
 
     public MenuItemImpl getItemData() {
@@ -96,13 +89,6 @@
         setEnabled(itemData.isEnabled());
     }
 
-    @Override
-    public void setEnabled(boolean enabled) {
-        super.setEnabled(enabled);
-        mImageButton.setEnabled(enabled);
-        mTextButton.setEnabled(enabled);
-    }
-
     public void onClick(View v) {
         if (mItemInvoker != null) {
             mItemInvoker.invokeItem(mItemData);
@@ -135,26 +121,22 @@
     }
 
     private void updateTextButtonVisibility() {
-        boolean visible = !TextUtils.isEmpty(mTextButton.getText());
-        visible &= mImageButton.getDrawable() == null ||
+        boolean visible = !TextUtils.isEmpty(mTitle);
+        visible &= mIcon == null ||
                 (mItemData.showsTextAsAction() && (mAllowTextWithIcon || mExpandedFormat));
 
-        mTextButton.setVisibility(visible ? VISIBLE : GONE);
+        setText(visible ? mTitle : null);
     }
 
     public void setIcon(Drawable icon) {
-        mImageButton.setImageDrawable(icon);
-        if (icon != null) {
-            mImageButton.setVisibility(VISIBLE);
-        } else {
-            mImageButton.setVisibility(GONE);
-        }
+        mIcon = icon;
+        setCompoundDrawablesWithIntrinsicBounds(icon, null, null, null);
 
         updateTextButtonVisibility();
     }
 
     public boolean hasText() {
-        return mTextButton.getVisibility() != GONE;
+        return !TextUtils.isEmpty(getText());
     }
 
     public void setShortcut(boolean showShortcut, char shortcutKey) {
@@ -164,8 +146,6 @@
     public void setTitle(CharSequence title) {
         mTitle = title;
 
-        mTextButton.setText(mTitle);
-
         setContentDescription(mTitle);
         updateTextButtonVisibility();
     }
@@ -236,12 +216,17 @@
 
     @Override
     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        final boolean textVisible = hasText();
+        if (textVisible) {
+            setPadding(mSavedPaddingLeft, getPaddingTop(), getPaddingRight(), getPaddingBottom());
+        }
+
         super.onMeasure(widthMeasureSpec, heightMeasureSpec);
 
         final int widthMode = MeasureSpec.getMode(widthMeasureSpec);
-        final int specSize = MeasureSpec.getSize(widthMeasureSpec);
+        final int widthSize = MeasureSpec.getSize(widthMeasureSpec);
         final int oldMeasuredWidth = getMeasuredWidth();
-        final int targetWidth = widthMode == MeasureSpec.AT_MOST ? Math.min(specSize, mMinWidth)
+        final int targetWidth = widthMode == MeasureSpec.AT_MOST ? Math.min(widthSize, mMinWidth)
                 : mMinWidth;
 
         if (widthMode != MeasureSpec.EXACTLY && mMinWidth > 0 && oldMeasuredWidth < targetWidth) {
@@ -249,5 +234,13 @@
             super.onMeasure(MeasureSpec.makeMeasureSpec(targetWidth, MeasureSpec.EXACTLY),
                     heightMeasureSpec);
         }
+
+        if (!textVisible && mIcon != null) {
+            // TextView won't center compound drawables in both dimensions without
+            // a little coercion. Pad in to center the icon after we've measured.
+            final int w = getMeasuredWidth();
+            final int dw = mIcon.getIntrinsicWidth();
+            setPadding((w - dw) / 2, getPaddingTop(), getPaddingRight(), getPaddingBottom());
+        }
     }
 }
diff --git a/core/java/com/android/internal/view/menu/ActionMenuPresenter.java b/core/java/com/android/internal/view/menu/ActionMenuPresenter.java
index 530809b..dca45a9 100644
--- a/core/java/com/android/internal/view/menu/ActionMenuPresenter.java
+++ b/core/java/com/android/internal/view/menu/ActionMenuPresenter.java
@@ -116,9 +116,9 @@
         if (!mMaxItemsSet) {
             mMaxItems = mContext.getResources().getInteger(
                     com.android.internal.R.integer.max_action_buttons);
-            if (mMenu != null) {
-                mMenu.onItemsChanged(true);
-            }
+        }
+        if (mMenu != null) {
+            mMenu.onItemsChanged(true);
         }
     }
 
diff --git a/core/java/com/android/internal/view/menu/ActionMenuView.java b/core/java/com/android/internal/view/menu/ActionMenuView.java
index 8d8c72c..e00fe9f 100644
--- a/core/java/com/android/internal/view/menu/ActionMenuView.java
+++ b/core/java/com/android/internal/view/menu/ActionMenuView.java
@@ -96,6 +96,13 @@
         if (mFormatItems) {
             onMeasureExactFormat(widthMeasureSpec, heightMeasureSpec);
         } else {
+            // Previous measurement at exact format may have set margins - reset them.
+            final int childCount = getChildCount();
+            for (int i = 0; i < childCount; i++) {
+                final View child = getChildAt(i);
+                final LayoutParams lp = (LayoutParams) child.getLayoutParams();
+                lp.leftMargin = lp.rightMargin = 0;
+            }
             super.onMeasure(widthMeasureSpec, heightMeasureSpec);
         }
     }
diff --git a/core/java/com/android/internal/widget/ActionBarView.java b/core/java/com/android/internal/widget/ActionBarView.java
index 2f325bf..8c05459 100644
--- a/core/java/com/android/internal/widget/ActionBarView.java
+++ b/core/java/com/android/internal/widget/ActionBarView.java
@@ -324,13 +324,31 @@
                     if (mSplitView != null) {
                         mSplitView.addView(mMenuView);
                     }
+                    mMenuView.getLayoutParams().width = LayoutParams.MATCH_PARENT;
                 } else {
                     addView(mMenuView);
+                    mMenuView.getLayoutParams().width = LayoutParams.WRAP_CONTENT;
                 }
+                mMenuView.requestLayout();
             }
             if (mSplitView != null) {
                 mSplitView.setVisibility(splitActionBar ? VISIBLE : GONE);
             }
+
+            if (mActionMenuPresenter != null) {
+                if (!splitActionBar) {
+                    mActionMenuPresenter.setExpandedActionViewsExclusive(
+                            getResources().getBoolean(
+                                    com.android.internal.R.bool.action_bar_expanded_action_views_exclusive));
+                } else {
+                    mActionMenuPresenter.setExpandedActionViewsExclusive(false);
+                    // Allow full screen width in split mode.
+                    mActionMenuPresenter.setWidthLimit(
+                            getContext().getResources().getDisplayMetrics().widthPixels, true);
+                    // No limit to the item count; use whatever will fit.
+                    mActionMenuPresenter.setItemLimit(Integer.MAX_VALUE);
+                }
+            }
             super.setSplitActionBar(splitActionBar);
         }
     }
diff --git a/core/java/com/android/internal/widget/TransportControlView.java b/core/java/com/android/internal/widget/TransportControlView.java
index 979eb81..2f52585 100644
--- a/core/java/com/android/internal/widget/TransportControlView.java
+++ b/core/java/com/android/internal/widget/TransportControlView.java
@@ -314,7 +314,7 @@
         final int flags = mTransportControlFlags;
         setVisibilityBasedOnFlag(mBtnPrev, flags, RemoteControlClient.FLAG_KEY_MEDIA_PREVIOUS);
         setVisibilityBasedOnFlag(mBtnNext, flags, RemoteControlClient.FLAG_KEY_MEDIA_NEXT);
-        setVisibilityBasedOnFlag(mBtnPrev, flags,
+        setVisibilityBasedOnFlag(mBtnPlay, flags,
                 RemoteControlClient.FLAG_KEY_MEDIA_PLAY
                 | RemoteControlClient.FLAG_KEY_MEDIA_PAUSE
                 | RemoteControlClient.FLAG_KEY_MEDIA_PLAY_PAUSE
diff --git a/core/java/com/google/android/mms/pdu/PduPersister.java b/core/java/com/google/android/mms/pdu/PduPersister.java
index 7037b61..b04f890 100644
--- a/core/java/com/google/android/mms/pdu/PduPersister.java
+++ b/core/java/com/google/android/mms/pdu/PduPersister.java
@@ -513,6 +513,9 @@
         PduCacheEntry cacheEntry;
         synchronized(PDU_CACHE_INSTANCE) {
             if (PDU_CACHE_INSTANCE.isUpdating(uri)) {
+                if (LOCAL_LOGV) {
+                    Log.v(TAG, "load: " + uri + " blocked by isUpdating()");
+                }
                 try {
                     PDU_CACHE_INSTANCE.wait();
                 } catch (InterruptedException e) {
@@ -840,6 +843,9 @@
             // If the cache item is getting updated, wait until it's done updating before
             // purging it.
             if (PDU_CACHE_INSTANCE.isUpdating(uri)) {
+                if (LOCAL_LOGV) {
+                    Log.v(TAG, "updateHeaders: " + uri + " blocked by isUpdating()");
+                }
                 try {
                     PDU_CACHE_INSTANCE.wait();
                 } catch (InterruptedException e) {
@@ -1002,6 +1008,9 @@
             PduCacheEntry cacheEntry;
             synchronized(PDU_CACHE_INSTANCE) {
                 if (PDU_CACHE_INSTANCE.isUpdating(uri)) {
+                    if (LOCAL_LOGV) {
+                        Log.v(TAG, "updateParts: " + uri + " blocked by isUpdating()");
+                    }
                     try {
                         PDU_CACHE_INSTANCE.wait();
                     } catch (InterruptedException e) {
@@ -1097,6 +1106,9 @@
             // If the cache item is getting updated, wait until it's done updating before
             // purging it.
             if (PDU_CACHE_INSTANCE.isUpdating(uri)) {
+                if (LOCAL_LOGV) {
+                    Log.v(TAG, "persist: " + uri + " blocked by isUpdating()");
+                }
                 try {
                     PDU_CACHE_INSTANCE.wait();
                 } catch (InterruptedException e) {
diff --git a/core/java/com/google/android/mms/util/PduCache.java b/core/java/com/google/android/mms/util/PduCache.java
index 87cb48e..de83124 100644
--- a/core/java/com/google/android/mms/util/PduCache.java
+++ b/core/java/com/google/android/mms/util/PduCache.java
@@ -161,6 +161,7 @@
     }
 
     private PduCacheEntry purgeSingleEntry(Uri key) {
+        mUpdating.remove(key);
         PduCacheEntry entry = super.purge(key);
         if (entry != null) {
             removeFromThreads(key, entry);
@@ -176,6 +177,7 @@
 
         mMessageBoxes.clear();
         mThreads.clear();
+        mUpdating.clear();
     }
 
     /**
@@ -216,6 +218,7 @@
             HashSet<Uri> msgBox = mMessageBoxes.remove(msgBoxId);
             if (msgBox != null) {
                 for (Uri key : msgBox) {
+                    mUpdating.remove(key);
                     PduCacheEntry entry = super.purge(key);
                     if (entry != null) {
                         removeFromThreads(key, entry);
@@ -240,6 +243,7 @@
         HashSet<Uri> thread = mThreads.remove(threadId);
         if (thread != null) {
             for (Uri key : thread) {
+                mUpdating.remove(key);
                 PduCacheEntry entry = super.purge(key);
                 if (entry != null) {
                     removeFromMessageBoxes(key, entry);
diff --git a/core/jni/android_database_SQLiteGlobal.cpp b/core/jni/android_database_SQLiteGlobal.cpp
index 9301183..acc2276 100644
--- a/core/jni/android_database_SQLiteGlobal.cpp
+++ b/core/jni/android_database_SQLiteGlobal.cpp
@@ -37,7 +37,7 @@
 // Called each time a message is logged.
 static void sqliteLogCallback(void* data, int iErrCode, const char* zMsg) {
     bool verboseLog = !!data;
-    if (iErrCode == 0 || iErrCode == SQLITE_CONSTRAINT) {
+    if (iErrCode == 0 || iErrCode == SQLITE_CONSTRAINT || iErrCode == SQLITE_SCHEMA) {
         if (verboseLog) {
             ALOGV(LOG_VERBOSE, SQLITE_LOG_TAG, "(%d) %s\n", iErrCode, zMsg);
         }
diff --git a/core/jni/android_util_Process.cpp b/core/jni/android_util_Process.cpp
index 07a7f22..41cc203 100644
--- a/core/jni/android_util_Process.cpp
+++ b/core/jni/android_util_Process.cpp
@@ -32,7 +32,6 @@
 #include <sys/errno.h>
 #include <sys/resource.h>
 #include <sys/types.h>
-#include <cutils/sched_policy.h>
 #include <dirent.h>
 #include <fcntl.h>
 #include <grp.h>
diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp
index f0560c1..8e5db36 100644
--- a/core/jni/android_view_GLES20Canvas.cpp
+++ b/core/jni/android_view_GLES20Canvas.cpp
@@ -679,7 +679,7 @@
 
 static void android_view_GLES20Canvas_destroyDisplayList(JNIEnv* env,
         jobject clazz, DisplayList* displayList) {
-    delete displayList;
+    DisplayList::destroyDisplayListDeferred(displayList);
 }
 
 static bool android_view_GLES20Canvas_drawDisplayList(JNIEnv* env,
@@ -770,6 +770,12 @@
     LayerRenderer::updateTextureLayer(layer, width, height, isOpaque, renderTarget, transform);
 }
 
+static void android_view_GLES20Canvas_updateRenderLayer(JNIEnv* env, jobject clazz,
+        Layer* layer, OpenGLRenderer* renderer, DisplayList* displayList,
+        jint left, jint top, jint right, jint bottom) {
+    layer->updateDeferred(renderer, displayList, left, top, right, bottom);
+}
+
 static void android_view_GLES20Canvas_setTextureLayerTransform(JNIEnv* env, jobject clazz,
         Layer* layer, SkMatrix* matrix) {
 
@@ -953,13 +959,15 @@
     { "nCreateTextureLayer",     "(Z[I)I",     (void*) android_view_GLES20Canvas_createTextureLayer },
     { "nUpdateTextureLayer",     "(IIIZLandroid/graphics/SurfaceTexture;)V",
                                                (void*) android_view_GLES20Canvas_updateTextureLayer },
-    { "nSetTextureLayerTransform", "(II)V",    (void*) android_view_GLES20Canvas_setTextureLayerTransform },
+    { "nUpdateRenderLayer",      "(IIIIIII)V", (void*) android_view_GLES20Canvas_updateRenderLayer },
     { "nDestroyLayer",           "(I)V",       (void*) android_view_GLES20Canvas_destroyLayer },
     { "nDestroyLayerDeferred",   "(I)V",       (void*) android_view_GLES20Canvas_destroyLayerDeferred },
     { "nFlushLayer",             "(I)V",       (void*) android_view_GLES20Canvas_flushLayer },
     { "nDrawLayer",              "(IIFFI)V",   (void*) android_view_GLES20Canvas_drawLayer },
     { "nCopyLayer",              "(II)Z",      (void*) android_view_GLES20Canvas_copyLayer },
 
+    { "nSetTextureLayerTransform", "(II)V",    (void*) android_view_GLES20Canvas_setTextureLayerTransform },
+
     { "nGetMaximumTextureWidth",  "()I",       (void*) android_view_GLES20Canvas_getMaxTextureWidth },
     { "nGetMaximumTextureHeight", "()I",       (void*) android_view_GLES20Canvas_getMaxTextureHeight },
 
diff --git a/core/res/res/anim/screen_rotate_0_frame.xml b/core/res/res/anim/screen_rotate_0_frame.xml
new file mode 100644
index 0000000..5ea9bf8
--- /dev/null
+++ b/core/res/res/anim/screen_rotate_0_frame.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+        android:shareInterpolator="false">
+    <alpha android:fromAlpha="1.0" android:toAlpha="1.0"
+            android:interpolator="@interpolator/decelerate_quint"
+            android:duration="@android:integer/config_shortAnimTime" />
+</set>
diff --git a/core/res/res/anim/screen_rotate_180_enter.xml b/core/res/res/anim/screen_rotate_180_enter.xml
index 470416b..688a8d5 100644
--- a/core/res/res/anim/screen_rotate_180_enter.xml
+++ b/core/res/res/anim/screen_rotate_180_enter.xml
@@ -25,4 +25,4 @@
             android:fillEnabled="true"
             android:fillBefore="true" android:fillAfter="true"
             android:duration="@android:integer/config_mediumAnimTime" />
-</set>
\ No newline at end of file
+</set>
diff --git a/core/res/res/anim/screen_rotate_180_frame.xml b/core/res/res/anim/screen_rotate_180_frame.xml
new file mode 100644
index 0000000..19dade1
--- /dev/null
+++ b/core/res/res/anim/screen_rotate_180_frame.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License. 
+*/
+-->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+        android:shareInterpolator="false">
+    <rotate android:fromDegrees="180" android:toDegrees="0"
+            android:pivotX="50%" android:pivotY="50%"
+            android:interpolator="@interpolator/decelerate_quint"
+            android:fillEnabled="true"
+            android:fillBefore="true" android:fillAfter="true"
+            android:duration="@android:integer/config_mediumAnimTime" />
+</set>
diff --git a/core/res/res/anim/screen_rotate_finish_enter.xml b/core/res/res/anim/screen_rotate_finish_enter.xml
index 849aa66..9d731e6 100644
--- a/core/res/res/anim/screen_rotate_finish_enter.xml
+++ b/core/res/res/anim/screen_rotate_finish_enter.xml
@@ -19,13 +19,14 @@
 
 <set xmlns:android="http://schemas.android.com/apk/res/android"
         android:shareInterpolator="false">
-    <scale android:fromXScale="1.0" android:toXScale="1.25"
-            android:fromYScale="1.0" android:toYScale="1.25"
+    <scale android:fromXScale="1.0" android:toXScale="1.1111111111111"
+            android:fromYScale="1.0" android:toYScale="1.1111111111111"
             android:pivotX="50%" android:pivotY="50%"
-            android:interpolator="@interpolator/decelerate_quint"
+            android:interpolator="@interpolator/accelerate_decelerate"
             android:fillEnabled="true"
             android:fillBefore="true" android:fillAfter="true"
-            android:duration="@android:integer/config_mediumAnimTime"/>
+            android:duration="@android:integer/config_shortAnimTime"/>
+    <!--
     <scale android:fromXScale="100%p" android:toXScale="100%"
             android:fromYScale="100%p" android:toYScale="100%"
             android:pivotX="50%" android:pivotY="50%"
@@ -33,4 +34,5 @@
             android:fillEnabled="true"
             android:fillBefore="true" android:fillAfter="true"
             android:duration="@android:integer/config_mediumAnimTime" />
+    -->
 </set>
diff --git a/core/res/res/anim/screen_rotate_finish_exit.xml b/core/res/res/anim/screen_rotate_finish_exit.xml
index 7f70dbc..60daa18 100644
--- a/core/res/res/anim/screen_rotate_finish_exit.xml
+++ b/core/res/res/anim/screen_rotate_finish_exit.xml
@@ -19,23 +19,21 @@
 
 <set xmlns:android="http://schemas.android.com/apk/res/android"
         android:shareInterpolator="false">
-    <scale android:fromXScale="1.0" android:toXScale="1.25"
-            android:fromYScale="1.0" android:toYScale="1.25"
+    <scale android:fromXScale="1.0" android:toXScale="1.0"
+            android:fromYScale="1.0" android:toYScale="1.0"
             android:pivotX="50%" android:pivotY="50%"
-            android:interpolator="@interpolator/decelerate_quint"
+            android:interpolator="@interpolator/accelerate_decelerate"
             android:fillEnabled="true"
             android:fillBefore="false" android:fillAfter="true"
-            android:duration="@android:integer/config_mediumAnimTime"/>
-    <!--
+            android:duration="@android:integer/config_shortAnimTime"/>
     <scale android:fromXScale="100%" android:toXScale="100%p"
             android:fromYScale="100%" android:toYScale="100%p"
             android:pivotX="50%" android:pivotY="50%"
-            android:interpolator="@interpolator/decelerate_quint"
+            android:interpolator="@interpolator/accelerate_decelerate"
             android:duration="@android:integer/config_mediumAnimTime" />
-    -->
     <alpha android:fromAlpha="1.0" android:toAlpha="0"
-            android:interpolator="@interpolator/decelerate_quint"
+            android:interpolator="@interpolator/accelerate_decelerate"
             android:fillEnabled="true"
             android:fillBefore="true" android:fillAfter="true"
-            android:duration="@android:integer/config_mediumAnimTime" />
+            android:duration="@android:integer/config_shortAnimTime" />
 </set>
diff --git a/core/res/res/anim/screen_rotate_finish_frame.xml b/core/res/res/anim/screen_rotate_finish_frame.xml
new file mode 100644
index 0000000..06dfc5e
--- /dev/null
+++ b/core/res/res/anim/screen_rotate_finish_frame.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+        android:shareInterpolator="false">
+    <scale android:fromXScale="1.0" android:toXScale="1.1111111111111"
+            android:fromYScale="1.0" android:toYScale="1.1111111111111"
+            android:pivotX="50%" android:pivotY="50%"
+            android:interpolator="@interpolator/accelerate_decelerate"
+            android:fillEnabled="true"
+            android:fillBefore="true" android:fillAfter="true"
+            android:duration="@android:integer/config_shortAnimTime"/>
+    <scale android:fromXScale="100%" android:toXScale="100%p"
+            android:fromYScale="100%" android:toYScale="100%p"
+            android:pivotX="50%" android:pivotY="50%"
+            android:fillEnabled="true"
+            android:fillBefore="true" android:fillAfter="true"
+            android:interpolator="@interpolator/accelerate_decelerate"
+            android:duration="@android:integer/config_shortAnimTime" />
+</set>
diff --git a/core/res/res/anim/screen_rotate_minus_90_frame.xml b/core/res/res/anim/screen_rotate_minus_90_frame.xml
new file mode 100644
index 0000000..874f2e9
--- /dev/null
+++ b/core/res/res/anim/screen_rotate_minus_90_frame.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+        android:shareInterpolator="false">
+    <rotate android:fromDegrees="0" android:toDegrees="90"
+            android:pivotX="50%" android:pivotY="50%"
+            android:interpolator="@interpolator/decelerate_quint"
+            android:fillEnabled="true"
+            android:fillBefore="true" android:fillAfter="true"
+            android:duration="@android:integer/config_mediumAnimTime" />
+</set>
diff --git a/core/res/res/anim/screen_rotate_plus_90_frame.xml b/core/res/res/anim/screen_rotate_plus_90_frame.xml
new file mode 100644
index 0000000..03c6aa6
--- /dev/null
+++ b/core/res/res/anim/screen_rotate_plus_90_frame.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+        android:shareInterpolator="false">
+    <rotate android:fromDegrees="0" android:toDegrees="-90"
+            android:pivotX="50%" android:pivotY="50%"
+            android:interpolator="@interpolator/decelerate_quint"
+            android:fillEnabled="true"
+            android:fillBefore="true" android:fillAfter="true"
+            android:duration="@android:integer/config_mediumAnimTime" />
+</set>
diff --git a/core/res/res/anim/screen_rotate_start_enter.xml b/core/res/res/anim/screen_rotate_start_enter.xml
index e3f48e4d..162ae8c 100644
--- a/core/res/res/anim/screen_rotate_start_enter.xml
+++ b/core/res/res/anim/screen_rotate_start_enter.xml
@@ -19,8 +19,8 @@
 
 <set xmlns:android="http://schemas.android.com/apk/res/android"
         android:shareInterpolator="false">
-    <scale android:fromXScale="1.0" android:toXScale="0.8"
-            android:fromYScale="1.0" android:toYScale="0.8"
+    <scale android:fromXScale="1.0" android:toXScale="0.9"
+            android:fromYScale="1.0" android:toYScale="0.9"
             android:pivotX="50%" android:pivotY="50%"
             android:interpolator="@interpolator/decelerate_quint"
             android:fillEnabled="true"
diff --git a/core/res/res/anim/screen_rotate_start_exit.xml b/core/res/res/anim/screen_rotate_start_exit.xml
index e3f48e4d..162ae8c 100644
--- a/core/res/res/anim/screen_rotate_start_exit.xml
+++ b/core/res/res/anim/screen_rotate_start_exit.xml
@@ -19,8 +19,8 @@
 
 <set xmlns:android="http://schemas.android.com/apk/res/android"
         android:shareInterpolator="false">
-    <scale android:fromXScale="1.0" android:toXScale="0.8"
-            android:fromYScale="1.0" android:toYScale="0.8"
+    <scale android:fromXScale="1.0" android:toXScale="0.9"
+            android:fromYScale="1.0" android:toYScale="0.9"
             android:pivotX="50%" android:pivotY="50%"
             android:interpolator="@interpolator/decelerate_quint"
             android:fillEnabled="true"
diff --git a/core/res/res/anim/screen_rotate_start_frame.xml b/core/res/res/anim/screen_rotate_start_frame.xml
new file mode 100644
index 0000000..162ae8c
--- /dev/null
+++ b/core/res/res/anim/screen_rotate_start_frame.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+        android:shareInterpolator="false">
+    <scale android:fromXScale="1.0" android:toXScale="0.9"
+            android:fromYScale="1.0" android:toYScale="0.9"
+            android:pivotX="50%" android:pivotY="50%"
+            android:interpolator="@interpolator/decelerate_quint"
+            android:fillEnabled="true"
+            android:fillBefore="true" android:fillAfter="true"
+            android:duration="@android:integer/config_mediumAnimTime"/>
+</set>
diff --git a/core/res/res/layout/action_menu_item_layout.xml b/core/res/res/layout/action_menu_item_layout.xml
index dca6c52..ba7cf3b 100644
--- a/core/res/res/layout/action_menu_item_layout.xml
+++ b/core/res/res/layout/action_menu_item_layout.xml
@@ -18,39 +18,12 @@
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
     android:layout_gravity="center"
-    android:addStatesFromChildren="true"
     android:gravity="center"
     android:focusable="true"
-    android:paddingLeft="4dip"
-    android:paddingRight="4dip"
-    style="?android:attr/actionButtonStyle">
-    <ImageButton android:id="@+id/imageButton"
-                 android:layout_width="wrap_content"
-                 android:layout_height="wrap_content"
-                 android:layout_gravity="center"
-                 android:visibility="gone"
-                 android:layout_marginTop="4dip"
-                 android:layout_marginBottom="4dip"
-                 android:layout_marginLeft="4dip"
-                 android:layout_marginRight="4dip"
-                 android:scaleType="fitCenter"
-                 android:adjustViewBounds="true"
-                 android:background="@null"
-                 android:focusable="false" />
-    <Button android:id="@+id/textButton"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_gravity="center"
-            android:visibility="gone"
-            android:textAppearance="?attr/actionMenuTextAppearance"
-            style="?attr/buttonStyleSmall"
-            android:textColor="?attr/actionMenuTextColor"
-            android:singleLine="true"
-            android:ellipsize="none"
-            android:background="@null"
-            android:paddingTop="4dip"
-            android:paddingBottom="4dip"
-            android:paddingLeft="4dip"
-            android:paddingRight="4dip"
-            android:focusable="false" />
-</com.android.internal.view.menu.ActionMenuItemView>
+    android:paddingTop="4dip"
+    android:paddingBottom="4dip"
+    android:paddingLeft="8dip"
+    android:paddingRight="8dip"
+    android:textAppearance="?attr/actionMenuTextAppearance"
+    android:textColor="?attr/actionMenuTextColor"
+    style="?android:attr/actionButtonStyle" />
diff --git a/core/res/res/layout/alert_dialog_holo.xml b/core/res/res/layout/alert_dialog_holo.xml
index 2b686bd..173efa7 100644
--- a/core/res/res/layout/alert_dialog_holo.xml
+++ b/core/res/res/layout/alert_dialog_holo.xml
@@ -108,7 +108,7 @@
             android:layoutDirection="locale"
             android:measureWithLargestChild="true">
             <Button android:id="@+id/button2"
-                android:layout_width="0dip"
+                android:layout_width="wrap_content"
                 android:layout_gravity="left"
                 android:layout_weight="1"
                 android:maxLines="2"
@@ -117,7 +117,7 @@
                 android:minHeight="@dimen/alert_dialog_button_bar_height"
                 android:layout_height="wrap_content" />
             <Button android:id="@+id/button3"
-                android:layout_width="0dip"
+                android:layout_width="wrap_content"
                 android:layout_gravity="center_horizontal"
                 android:layout_weight="1"
                 android:maxLines="2"
@@ -126,7 +126,7 @@
                 android:minHeight="@dimen/alert_dialog_button_bar_height"
                 android:layout_height="wrap_content" />
             <Button android:id="@+id/button1"
-                android:layout_width="0dip"
+                android:layout_width="wrap_content"
                 android:layout_gravity="right"
                 android:layout_weight="1"
                 android:maxLines="2"
diff --git a/core/res/res/layout/webview_select_singlechoice.xml b/core/res/res/layout/webview_select_singlechoice.xml
index c0753a8..d3c3c15 100644
--- a/core/res/res/layout/webview_select_singlechoice.xml
+++ b/core/res/res/layout/webview_select_singlechoice.xml
@@ -17,13 +17,7 @@
 <TextView xmlns:android="http://schemas.android.com/apk/res/android"
     android:id="@android:id/text1"
     android:layout_width="match_parent"
-    android:layout_height="wrap_content"
-    android:minHeight="?android:attr/listPreferredItemHeight"
-    android:textAppearance="?android:attr/textAppearanceLarge"
-    android:textColor="?android:attr/textColorAlertDialogListItem"
-    android:gravity="center_vertical"
-    android:paddingLeft="12dip"
-    android:paddingRight="7dip"
+    android:layout_height="?android:attr/dropdownListPreferredItemHeight"
     android:ellipsize="marquee"
     style="?android:attr/spinnerDropDownItemStyle"
     android:background="?android:attr/activatedBackgroundIndicator"
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index 1de0390..9ac20fa 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -26,7 +26,7 @@
     <string name="gigabyteShort" msgid="3259882455212193214">"GB"</string>
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
-    <string name="fileSizeSuffix" msgid="7670819340156489359">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="UNIT">%2$s</xliff:g><xliff:g id="NUMBER">%1$s</xliff:g>"</string>
     <string name="untitled" msgid="4638956954852782576">"&lt;Titelloos&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -215,10 +215,8 @@
     <string name="permdesc_reorderTasks" msgid="4175137612205663399">"Laat die program toe om take na die voorgrond en agtergrond te skuif. Kwaadwillige programme kan hulself sonder jou beheer na vore dwing."</string>
     <string name="permlab_removeTasks" msgid="6821513401870377403">"stop lopende programme"</string>
     <string name="permdesc_removeTasks" msgid="1394714352062635493">"Laat die program toe om take te verwyder en hul programme te dood. Kwaadwillige programme kan die gedrag van ander programme ontwrig."</string>
-    <!-- no translation found for permlab_setScreenCompatibility (6975387118861842061) -->
-    <skip />
-    <!-- no translation found for permdesc_setScreenCompatibility (692043618693917374) -->
-    <skip />
+    <string name="permlab_setScreenCompatibility" msgid="6975387118861842061">"stel skermversoenbaarheid"</string>
+    <string name="permdesc_setScreenCompatibility" msgid="692043618693917374">"Laat die program toe om om die skermversoenbaarheid-modus van ander programme te beheer. Kwaadwillige programme kan die gedrag van ander programme breek."</string>
     <string name="permlab_setDebugApp" msgid="3022107198686584052">"aktiveer programontfouting"</string>
     <string name="permdesc_setDebugApp" msgid="4474512416299013256">"Laat die program toe om ontfouting vir \'n ander program af te skakel. Kwaadwillige programme kan dit dalk gebruik om ander programme te dood."</string>
     <string name="permlab_changeConfiguration" msgid="8214475779521218295">"Verander jou UI-instellings"</string>
@@ -315,8 +313,8 @@
     <string name="permlab_changeComponentState" msgid="6335576775711095931">"aktiveer of deaktiveer programkomponente"</string>
     <string name="permdesc_changeComponentState" product="tablet" msgid="8887435740982237294">"Laat die program toe om te verander of \'n komponent van ander program geaktiveer is of nie. Kwaadwillige programme kan dit dalk gebruik om belangrike tabletvermoëns te deaktiveer. Wees versigtig met hierdie toestemming, want dit kan programkomponente tot \'n onbruikbare, inkonsekwente of onstabiele toestand bring."</string>
     <string name="permdesc_changeComponentState" product="default" msgid="1827232484416505615">"Laat die program toe om te verander of \'n komponent van ander program geaktiveer is of nie. Kwaadwillige programme kan dit gebruik om belangrike foonvermoëns te deaktiveer. Wees versigtig met hierdie toestemming, want dit kan programkomponente tot \'n onbruikbare, inkonsekwente of onstabiele toestand bring."</string>
-    <string name="permlab_grantRevokePermissions" msgid="4627315351093508795">"toestemmings te verleen of te herroep"</string>
-    <string name="permdesc_grantRevokePermissions" msgid="4088642654085850662">"Laat \'n program toe om spesifieke toestemmings te verleen of te herroep vir die betrokke program of ander programme. Skadelike programme kan dit gebruik om toegang te verkry tot kenmerke waarvoor jy nie toestemming verleen het nie."</string>
+    <string name="permlab_grantRevokePermissions" msgid="4627315351093508795">"verleen of herroep toestemmings"</string>
+    <string name="permdesc_grantRevokePermissions" msgid="4088642654085850662">"Laat \'n program toe om spesifieke toestemmings te verleen of te herroep vir die betrokke program of ander programme. Kwaadwillige programme kan dit gebruik om toegang te verkry tot kenmerke waarvoor jy nie toestemming verleen het nie."</string>
     <string name="permlab_setPreferredApplications" msgid="8463181628695396391">"stel voorkeurprogramme"</string>
     <string name="permdesc_setPreferredApplications" msgid="4973986762241783712">"Laat die program toe om jou voorkeur-programme te verander. Kwaadwillige programme kan stilweg die programme wat loop, verander, wat jou bestaande programme bedrieg om private data oor jou in te samel."</string>
     <string name="permlab_writeSettings" msgid="1365523497395143704">"verander globale stelselinstellings"</string>
@@ -673,7 +671,7 @@
     <string name="faceunlock_multiple_failures" msgid="754137583022792429">"Maksimum gesigontsluit-pogings oorskry"</string>
     <string name="lockscreen_plugged_in" msgid="8057762828355572315">"Laai, (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_charged" msgid="4938930459620989972">"Gehef."</string>
-    <string name="lockscreen_battery_short" msgid="3617549178603354656">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
+    <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"Koppel jou herlaaier."</string>
     <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"Geen SIM-kaart."</string>
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Geen SIM-kaart in tablet nie."</string>
@@ -722,8 +720,8 @@
     <string name="password_keyboard_label_symbol_key" msgid="992280756256536042">"?123"</string>
     <string name="password_keyboard_label_alpha_key" msgid="8001096175167485649">"ABC"</string>
     <string name="password_keyboard_label_alt_key" msgid="1284820942620288678">"ALT"</string>
-    <string name="hour_ampm" msgid="4329881288269772723">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string>
-    <string name="hour_cap_ampm" msgid="1829009197680861107">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string>
+    <string name="hour_ampm" msgid="4584338083529355982">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string>
+    <string name="hour_cap_ampm" msgid="2083465992940444366">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string>
     <string name="factorytest_failed" msgid="5410270329114212041">"Fabriektoets het gefaal"</string>
     <string name="factorytest_not_system" msgid="4435201656767276723">"Die FACTORY_TEST-handeling word net ondersteun vir pakkette wat in /system/app geïnstalleer is."</string>
     <string name="factorytest_no_action" msgid="872991874799998561">"Geen pakket is gevind wat die FACTORY_TEST-handeling bied nie."</string>
@@ -735,7 +733,7 @@
     <string name="double_tap_toast" msgid="4595046515400268881">"Wenk: Dubbeltik om in en uit te zoem."</string>
     <string name="autofill_this_form" msgid="4616758841157816676">"Outovul"</string>
     <string name="setup_autofill" msgid="7103495070180590814">"Stel outovul op"</string>
-    <string name="autofill_address_name_separator" msgid="2504700673286691795">" "</string>
+    <string name="autofill_address_name_separator" msgid="6350145154779706772">" "</string>
     <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string>
     <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string>
     <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
@@ -770,6 +768,8 @@
     <string name="permdesc_serialPort" msgid="2991639985224598193">"Laat die houer toe om toegang te verkry tot reekspoorte wat die SerialManager API gebruik."</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"verkry toegang tot inhoud ekstern"</string>
     <string name="permdesc_accessContentProvidersExternally" msgid="4544346486697853685">"Stel die houer in staat om toegang te verkry tot inhoudverskaffers vanuit die dop. Behoort nooit nodig te wees vir gewone programme nie."</string>
+    <string name="permlab_updateLock" msgid="3527558366616680889">"ontmoedig outomatiese toestelopdaterings"</string>
+    <string name="permdesc_updateLock" msgid="1655625832166778492">"Laat die houer toe om inligting aan die stelsel te bied oor wanneer \'n goeie tyd vir \'n nie-interaktiewe herlaai sal wees om die toestel op te gradeer."</string>
     <string name="save_password_message" msgid="767344687139195790">"Wil jy hê die blaaier moet hierdie wagwoord onthou?"</string>
     <string name="save_password_notnow" msgid="6389675316706699758">"Nie nou nie"</string>
     <string name="save_password_remember" msgid="6491879678996749466">"Onthou"</string>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index 262a102..dc74d94 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -26,7 +26,7 @@
     <string name="gigabyteShort" msgid="3259882455212193214">"GB"</string>
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
-    <string name="fileSizeSuffix" msgid="7670819340156489359">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
     <string name="untitled" msgid="4638956954852782576">"&lt;ርዕስ አልባ&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -314,9 +314,9 @@
     <string name="permdesc_changeComponentState" product="tablet" msgid="8887435740982237294">"የሌላ መተግበሪያ ክፍለ አካል እንደነቃ ወይም እንዳልነቃ መተግበሪያው እንዲለውጥ ይፈቅዳል፡፡ አስፈላጊ የጡባዊ ተኮ አቅሞችን ለማስወገድ ጎጂ መተግበሪያዎች ይሄንን ሊጠቀሙበት ይችላሉ፡፡ ከፍቃድ ጋር ጥንቃቄ መወሰድ ይገባል፤ ልክ የማያገለግል፣ ወጥ ያልሆነ፣ ወይም ያልተረጋጋ ሁኔታ ወደ የመተግበሪያ ክፍለ አካል ማግኘት እንደሚቻል ሁሉ፡፡"</string>
     <string name="permdesc_changeComponentState" product="default" msgid="1827232484416505615">"የሌላ መተግበሪያ ክፍለ አካል እንደነቃ ወይም እንዳልነቃ መተግበሪያው እንዲለውጥ ይፈቅዳል፡፡ አስፈላጊ የስልክ አቅሞችን ለማስወገድ ተንኮል አዘል መተግበሪያዎች ይሄንን ሊጠቀሙበት ይችላሉ፡፡ ከፍቃድ ጋር ጥንቃቄ መወሰድ ይገባል፤ ልክ የማያገለግል፣ ወጥ ያልሆነ፣ ወይም ያልተረጋጋ ሁኔታ ወደ የመተግበሪያ ክፍለ አካል ማግኘት እንደሚቻል ሁሉ፡፡"</string>
     <string name="permlab_grantRevokePermissions" msgid="4627315351093508795">"ፍቃዶች ስጥ ወይም ከልክል"</string>
-    <string name="permdesc_grantRevokePermissions" msgid="4088642654085850662">"የተወሰነ ፍቃዶች እንዲሰጥ ወይም እንዲከለክል ለመተግበሪያ ይፈቅዳል ወይም ሌላ መተግበሪያዎች፡፡ ተንኮል አዘል መተግበሪያዎች ያልፈቀድክላቸውን ባህሪያት ላይ ለመድረስ ይሄንን ሊጠቀሙት ይችላሉ፡፡"</string>
+    <string name="permdesc_grantRevokePermissions" msgid="4088642654085850662">"የተወሰነ ፍቃዶች እንዲሰጥ ወይም እንዲከለክል ለመተግበሪያ ይፈቅዳል ወይም ሌላ መተግበሪያዎች። ተንኮል አዘል መተግበሪያዎች ያልፈቀድክላቸውን ባህሪያት ላይ ለመድረስ ይሄንን ሊጠቀሙት ይችላሉ።"</string>
     <string name="permlab_setPreferredApplications" msgid="8463181628695396391">"ተመራጭ መተግበሪያዎች አዘጋጅ"</string>
-    <string name="permdesc_setPreferredApplications" msgid="4973986762241783712">"ተመራጭ መተግበሪያዎችህን ለመቀየር ለመተግበሪያው ይፈቅዳሉ፡፡ ካንተ የግል ውሂብ ለመሰብሰብ ያሉትን መተግበሪያዎች በመላክ፤ በመሄድ ላይ ያሉ መተግበሪያዎችን  ተንኮል አዘል መተግበሪያዎች በዝምታ ሊለውጡ ይችላሉ፡፡"</string>
+    <string name="permdesc_setPreferredApplications" msgid="4973986762241783712">"ተመራጭ መተግበሪያዎችህን ለመቀየር ለመተግበሪያው ይፈቅዳሉ፡፡ ከአንተ የግል ውሂብ ለመሰብሰብ ያሉትን መተግበሪያዎች በመላክ፤ በመሄድ ላይ ያሉ መተግበሪያዎችን  ተንኮል አዘል መተግበሪያዎች በዝምታ ሊለውጡ ይችላሉ፡፡"</string>
     <string name="permlab_writeSettings" msgid="1365523497395143704">"የሁሉንም ስርዓት ቅንብሮች ቀይር"</string>
     <string name="permdesc_writeSettings" msgid="7775723441558907181">"የስርዓት ቅንጅቶችን ውሂብ ለመቀየር ለመተግበሪያው ይፈቅዳሉ፡፡ ተንኮል አዘል መተግበሪያዎች የስርዓትህን አወቃቀር ብልሹ ሊያደርጉት ይችላሉ፡፡"</string>
     <string name="permlab_writeSecureSettings" msgid="204676251876718288">"የስርዓት ቅንብሮችንደህንነት ቀይር"</string>
@@ -339,9 +339,9 @@
     <string name="permdesc_readProfile" product="default" msgid="94520753797630679">"ልክ እንደ አንተ ስም እና የዕውቂያ መረጃ ፣ ባንተ መሳሪያ ወስጥ የተከማቹ የግል መገለጫ መረጃ ለማንበብ ለመተግበሪያው ይፈቅዳሉ፡፡ይሄም ማለት ሌሎች መተግበሪያዎች ሊለዩህ ይችላሉ እና ለሌሎች የመገለጫ መረጃህን ይልካሉ፡፡"</string>
     <string name="permlab_writeProfile" msgid="4679878325177177400">"የአርስዎ መገለጫ ውሂብ ላይ ይፃፉ"</string>
     <string name="permdesc_writeProfile" product="default" msgid="4637366723793045603">"ልክ እንደ አንተ ስም እና የዕውቂያ መረጃ ፣ ባንተ መሳሪያ ወስጥ የተከማቹ የግል መገለጫ መረጃ ለመለወጥ ወይም ለማከል ለመተግበሪያው ይፈቅዳሉ፡፡ይሄም ማለት ሌሎች መተግበሪያዎች ሊለዩህ ይችላሉ እና ለሌሎች የመገለጫ መረጃህን ይልካሉ፡፡"</string>
-    <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"ያንተን ማህበራዊ የውይይት ክፍሎች አንብብ"</string>
-    <string name="permdesc_readSocialStream" product="default" msgid="3419050808547335320">" ካንተ ጓደኞች ማህበራዊ ዝማኔዎችን እንዲደርስባቸው እና እንዲያመሳስል ለመተግበሪያውይፈቅዳሉ፡፡ ተንኮል አዘል መተግበሪያዎች ይህን መዳረሻ ባንተና በጓደኞችህ መካከል በማህበራዊ አውታረመረቦች ያሉ የግል ተግባቦቶችን ለመዳረስ ሊጠቀሙበት ይችላሉ፡፡"</string>
-    <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"ወደ ያንተ ማህበራዊ የውይይት ክፍሎች ጻፍ"</string>
+    <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"የአንተን ማህበራዊ የውይይት ክፍሎች አንብብ"</string>
+    <string name="permdesc_readSocialStream" product="default" msgid="3419050808547335320">" ከአንተ ጓደኞች ማህበራዊ ዝማኔዎችን እንዲደርስባቸው እና እንዲያመሳስል ለመተግበሪያውይፈቅዳሉ፡፡ ተንኮል አዘል መተግበሪያዎች ይህን መዳረሻ ባንተና በጓደኞችህ መካከል በማህበራዊ አውታረመረቦች ያሉ የግል ተግባቦቶችን ለመዳረስ ሊጠቀሙበት ይችላሉ፡፡"</string>
+    <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"ወደ የአንተ  ማህበራዊ የውይይት ክፍሎች ጻፍ"</string>
     <string name="permdesc_writeSocialStream" product="default" msgid="3496277176955721451">" የጓደኞችህን ማህበራዊ ዝማኔዎችን ለማሳየት ለመተግበሪያው ይፈቅዳሉ፡፡ ተንኮል አዘል መተግበሪያዎች ይህን መዳረሻ ጓደኛ መስለው ለመቅረብ እና የይለፍ ቃልና ሌላ ምስጢራዊ መረጃ እንድትሰጥ ለማድረግ ሊጠቀሙበት ይችላሉ፡፡"</string>
     <string name="permlab_readCalendar" msgid="5972727560257612398">"የቀን መቁጠሪያ ክስተቶች ተጨማሪ ሚስጥራዊ መረጃ አንብብ"</string>
     <string name="permdesc_readCalendar" product="tablet" msgid="2338414551004122687">"በጡባዊ ተኮህ ላይ የተከማቹ ሁሉንም የቀን መቁጠሪያ ክስተቶች መተግበሪያዎቹ እንዲያነቡ ይፈቅዳሉ፡፡ ያለ ባለቤቱ እውቅና ከነዚህ የቀን መቁጠሪያዎች የግል መረጃዎችን ጎጂ መተግበሪያዎች ያወጣሉ፡፡"</string>
@@ -671,7 +671,7 @@
     <string name="faceunlock_multiple_failures" msgid="754137583022792429">"የመጨረሻውን  የገጽ ክፈት ሙከራዎችን አልፏል"</string>
     <string name="lockscreen_plugged_in" msgid="8057762828355572315">"ኃይል በመሙላት ላይ፣ <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_charged" msgid="4938930459620989972">"ኃይል ሞልቷል።"</string>
-    <string name="lockscreen_battery_short" msgid="3617549178603354656">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
+    <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"ኃይል መሙያዎን ያያይዙ"</string>
     <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"ምንም SIM ካርድ የለም"</string>
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"በጡባዊ ውስጥ ምንም SIM ካርድ የለም።"</string>
@@ -720,8 +720,8 @@
     <string name="password_keyboard_label_symbol_key" msgid="992280756256536042">"?123"</string>
     <string name="password_keyboard_label_alpha_key" msgid="8001096175167485649">"ABC"</string>
     <string name="password_keyboard_label_alt_key" msgid="1284820942620288678">"ALT"</string>
-    <string name="hour_ampm" msgid="4329881288269772723">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string>
-    <string name="hour_cap_ampm" msgid="1829009197680861107">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string>
+    <string name="hour_ampm" msgid="4584338083529355982">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string>
+    <string name="hour_cap_ampm" msgid="2083465992940444366">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string>
     <string name="factorytest_failed" msgid="5410270329114212041">"የፋብሪካሙከራ ተስኗል"</string>
     <string name="factorytest_not_system" msgid="4435201656767276723">"የፋብሪካ_ ሙከራ ርምጃበ/system/app አካታች ውስጥ የተጫነ ብቻ ተደግፏል።"</string>
     <string name="factorytest_no_action" msgid="872991874799998561">"የፋብሪካ_ሙከራ ርምጃ የሚያቀርብምንም አካታች አልተገኘም።"</string>
@@ -733,7 +733,7 @@
     <string name="double_tap_toast" msgid="4595046515400268881">"ጠቃሚ ምክር፦ ለማጉላት እና ለማሳነስ ሁለቴ-መታ አድርግ።"</string>
     <string name="autofill_this_form" msgid="4616758841157816676">"ራስ ሙላ"</string>
     <string name="setup_autofill" msgid="7103495070180590814">"በራስ ሰር ሙላ አዘጋጅ"</string>
-    <string name="autofill_address_name_separator" msgid="2504700673286691795">" "</string>
+    <string name="autofill_address_name_separator" msgid="6350145154779706772">" "</string>
     <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string>
     <string name="autofill_address_summary_separator" msgid="7483307893170324129">"፣ "</string>
     <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
@@ -768,6 +768,8 @@
     <string name="permdesc_serialPort" msgid="2991639985224598193">"Allows the holder to access serial ports using the SerialManager API. የተከታታይ አደራጅ APIን በመጠቀም ያዡ የተከታታይ ወደቦችን እንዲደርስ ይፈቅዳል።"</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"ይዘት አቅራቢዎችን በውጭ በኩል ድረስባቸው"</string>
     <string name="permdesc_accessContentProvidersExternally" msgid="4544346486697853685">"ያዢውን ከቀፎው ወደሚመጡ የይዘት አቅራቢዎች እንዲደርስ ይፈቅድለታል። ለመደበኛ መተግበሪያዎች በፍጹም ማስፈለግ የለባቸውም።"</string>
+    <string name="permlab_updateLock" msgid="3527558366616680889">"ራስ-ሰር የመሳሪያ መሻሻሎች አታበረታታ"</string>
+    <string name="permdesc_updateLock" msgid="1655625832166778492">"ያዢው መሳሪያው ለማሻሻል መቼ መስተጋብራዊ ያልሆነ ዳግም ማስጀመር ቢደረግ ጥሩ ጊዜ እንደሆነ መረጃ ለስርዓቱ መረጃ እንዲያቀርብለት ያስችለዋል።"</string>
     <string name="save_password_message" msgid="767344687139195790">"አሳሹ ይህን ይለፍ ቃል እንዲያስታወስ ይፈልጋሉ?"</string>
     <string name="save_password_notnow" msgid="6389675316706699758">"አሁን አይደለም"</string>
     <string name="save_password_remember" msgid="6491879678996749466">"አስታውስ"</string>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index abdda71..193157b 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -26,7 +26,7 @@
     <string name="gigabyteShort" msgid="3259882455212193214">"غيغابايت"</string>
     <string name="terabyteShort" msgid="231613018159186962">"تيرابايت"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"بيتابايت"</string>
-    <string name="fileSizeSuffix" msgid="7670819340156489359">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
     <string name="untitled" msgid="4638956954852782576">"&lt;بلا عنوان&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -671,7 +671,7 @@
     <string name="faceunlock_multiple_failures" msgid="754137583022792429">"تم تجاوز الحد الأقصى لعدد محاولات تأمين الجهاز بالوجه"</string>
     <string name="lockscreen_plugged_in" msgid="8057762828355572315">"جارٍ الشحن، <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_charged" msgid="4938930459620989972">"تم الشحن."</string>
-    <string name="lockscreen_battery_short" msgid="3617549178603354656">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
+    <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"توصيل جهاز الشحن."</string>
     <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"ليس هناك بطاقة SIM."</string>
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"ليس هناك بطاقة SIM في الجهاز اللوحي."</string>
@@ -720,8 +720,8 @@
     <string name="password_keyboard_label_symbol_key" msgid="992280756256536042">"?123"</string>
     <string name="password_keyboard_label_alpha_key" msgid="8001096175167485649">"ب ت ث"</string>
     <string name="password_keyboard_label_alt_key" msgid="1284820942620288678">"ALT"</string>
-    <string name="hour_ampm" msgid="4329881288269772723">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string>
-    <string name="hour_cap_ampm" msgid="1829009197680861107">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string>
+    <string name="hour_ampm" msgid="4584338083529355982">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string>
+    <string name="hour_cap_ampm" msgid="2083465992940444366">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string>
     <string name="factorytest_failed" msgid="5410270329114212041">"أخفق اختبار المصنع"</string>
     <string name="factorytest_not_system" msgid="4435201656767276723">"إجراء FACTORY_TEST غير متاح سوى للحزم المثبتة في /system/app."</string>
     <string name="factorytest_no_action" msgid="872991874799998561">"لم يتم العثور على أية حزمة توفر إجراء FACTORY_TEST."</string>
@@ -733,7 +733,7 @@
     <string name="double_tap_toast" msgid="4595046515400268881">"نصيحة: اضغط مرتين للتكبير والتصغير."</string>
     <string name="autofill_this_form" msgid="4616758841157816676">"ملء تلقائي"</string>
     <string name="setup_autofill" msgid="7103495070180590814">"إعداد الملء التلقائي"</string>
-    <string name="autofill_address_name_separator" msgid="2504700673286691795">" "</string>
+    <string name="autofill_address_name_separator" msgid="6350145154779706772">" "</string>
     <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string>
     <string name="autofill_address_summary_separator" msgid="7483307893170324129">"، "</string>
     <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
@@ -768,6 +768,8 @@
     <string name="permdesc_serialPort" msgid="2991639985224598193">"يسمح لحامله بالدخول إلى المنافذ التسلسلية باستخدام واجهة برمجة التطبيقات."</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"الدخول إلى مزودي المحتوى خارجيًا"</string>
     <string name="permdesc_accessContentProvidersExternally" msgid="4544346486697853685">"السماح للمالك بالدخول إلى مزودي المحتوى من الوعاء. لن تكون هناك حاجة إليه مطلقًا مع التطبيقات العادية."</string>
+    <string name="permlab_updateLock" msgid="3527558366616680889">"عدم التوصية بالتحديثات التلقائية للجهاز"</string>
+    <string name="permdesc_updateLock" msgid="1655625832166778492">"للسماح للمالك بتقديم معلومات إلى النظام بشأن الوقت المناسب لإجراء إعادة تشغيل غير تفاعلية لترقية الجهاز."</string>
     <string name="save_password_message" msgid="767344687139195790">"هل تريد من المتصفح تذكر كلمة المرور هذه؟"</string>
     <string name="save_password_notnow" msgid="6389675316706699758">"ليس الآن"</string>
     <string name="save_password_remember" msgid="6491879678996749466">"تذكّر"</string>
diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml
index 5cfa349..a37e231 100644
--- a/core/res/res/values-be/strings.xml
+++ b/core/res/res/values-be/strings.xml
@@ -26,7 +26,7 @@
     <string name="gigabyteShort" msgid="3259882455212193214">"Гб"</string>
     <string name="terabyteShort" msgid="231613018159186962">"Тб"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"Пб"</string>
-    <string name="fileSizeSuffix" msgid="7670819340156489359">"запаўняльнік<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
     <string name="untitled" msgid="4638956954852782576">"&lt;Без назвы&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"..."</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">".."</string>
@@ -671,7 +671,7 @@
     <string name="faceunlock_multiple_failures" msgid="754137583022792429">"Перавышана максімальная колькасць спроб разблакоўкі праз Фэйскантроль"</string>
     <string name="lockscreen_plugged_in" msgid="8057762828355572315">"Зарадка, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_charged" msgid="4938930459620989972">"Зараджаны."</string>
-    <string name="lockscreen_battery_short" msgid="3617549178603354656">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
+    <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"Падлучыце зарадную прыладу."</string>
     <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"Няма SIM-карты."</string>
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Няма SIM-карты ў планшэце."</string>
@@ -720,8 +720,8 @@
     <string name="password_keyboard_label_symbol_key" msgid="992280756256536042">"123"</string>
     <string name="password_keyboard_label_alpha_key" msgid="8001096175167485649">"ABC"</string>
     <string name="password_keyboard_label_alt_key" msgid="1284820942620288678">"Alt"</string>
-    <string name="hour_ampm" msgid="4329881288269772723">"запаўняльнік<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string>
-    <string name="hour_cap_ampm" msgid="1829009197680861107">"запаўняльнік<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string>
+    <string name="hour_ampm" msgid="4584338083529355982">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string>
+    <string name="hour_cap_ampm" msgid="2083465992940444366">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string>
     <string name="factorytest_failed" msgid="5410270329114212041">"Не атрымалася выканаць заводскую праверку"</string>
     <string name="factorytest_not_system" msgid="4435201656767276723">"Дзеянне FACTORY_TEST падтрымліваецца толькі для пакетаў, усталяваных на шляху /system/app."</string>
     <string name="factorytest_no_action" msgid="872991874799998561">"Пакет, які выконвае дзеянне FACTORY_TEST, не знойдзены."</string>
@@ -733,7 +733,7 @@
     <string name="double_tap_toast" msgid="4595046515400268881">"Падказка: двойчы націсніце, каб павялічыць або паменшыць."</string>
     <string name="autofill_this_form" msgid="4616758841157816676">"Аўтазапаўненне"</string>
     <string name="setup_autofill" msgid="7103495070180590814">"Усталяванне аўтазапаўнення"</string>
-    <string name="autofill_address_name_separator" msgid="2504700673286691795">" "</string>
+    <string name="autofill_address_name_separator" msgid="6350145154779706772">" "</string>
     <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string>
     <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string>
     <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
@@ -768,6 +768,8 @@
     <string name="permdesc_serialPort" msgid="2991639985224598193">"Дазваляе ўладальніку атрымліваць доступ да паслядоўных партоў з дапамогай API SerialManager."</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"знешнi доступ да кантэнт-правайдэраў"</string>
     <string name="permdesc_accessContentProvidersExternally" msgid="4544346486697853685">"Дае ўладальніку доступ да кантэнт-правайдэраў з абалонкi. Не патрабуецца для звычайных прыкладанняў."</string>
+    <string name="permlab_updateLock" msgid="3527558366616680889">"адмянiць аўтаматычнае абнаўленне прылад"</string>
+    <string name="permdesc_updateLock" msgid="1655625832166778492">"Дазваляе ўладальніку адпраўляць у сiстэму звесткi пра тое, калі будзе зручны час для неінтерактыўнага перазапуску ў мэтах абнаўлення прылады."</string>
     <string name="save_password_message" msgid="767344687139195790">"Вы хочаце, каб браўзэр запомніў гэты пароль?"</string>
     <string name="save_password_notnow" msgid="6389675316706699758">"Не цяпер"</string>
     <string name="save_password_remember" msgid="6491879678996749466">"Запомніць"</string>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index 06a2577..c277ee9 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -26,7 +26,7 @@
     <string name="gigabyteShort" msgid="3259882455212193214">"ГБ"</string>
     <string name="terabyteShort" msgid="231613018159186962">"ТБ"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"ПБ"</string>
-    <string name="fileSizeSuffix" msgid="7670819340156489359">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
     <string name="untitled" msgid="4638956954852782576">"&lt;Без заглавие&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">".."</string>
@@ -313,10 +313,8 @@
     <string name="permlab_changeComponentState" msgid="6335576775711095931">"активиране или деактивиране на компоненти на приложенията"</string>
     <string name="permdesc_changeComponentState" product="tablet" msgid="8887435740982237294">"Разрешава на приложението да активира или деактивира компонент на друго приложение. Злонамерените приложения могат да използват това, за да деактивират важни възможности на таблета. С това разрешение трябва да се внимава, тъй като компонентите на приложенията може да бъдат приведени в неизползваемо, несъгласувано или нестабилно състояние."</string>
     <string name="permdesc_changeComponentState" product="default" msgid="1827232484416505615">"Разрешава на приложението да активира или деактивира компонент на друго приложение. Злонамерените приложения могат да използват това, за да деактивират важни възможности на телефона. С това разрешение трябва да се внимава, тъй като компонентите на приложенията може да бъдат приведени в неизползваемо, несъгласувано или нестабилно състояние."</string>
-    <!-- no translation found for permlab_grantRevokePermissions (4627315351093508795) -->
-    <skip />
-    <!-- no translation found for permdesc_grantRevokePermissions (4088642654085850662) -->
-    <skip />
+    <string name="permlab_grantRevokePermissions" msgid="4627315351093508795">"даване или отмяна на разрешения"</string>
+    <string name="permdesc_grantRevokePermissions" msgid="4088642654085850662">"Разрешава на приложението да дава или отменя конкретни разрешения за себе си или други приложения. Злонамерените програми могат да използват това, за да осъществяват неразрешен от вас достъп до функции."</string>
     <string name="permlab_setPreferredApplications" msgid="8463181628695396391">"задаване на предпочитани приложения"</string>
     <string name="permdesc_setPreferredApplications" msgid="4973986762241783712">"Разрешава на приложението да променя предпочитаните ви приложения. Злонамерените приложения могат скрито да променят приложенията, които се изпълняват, като ги фалшифицират, за да се сдобият с ваши лични данни."</string>
     <string name="permlab_writeSettings" msgid="1365523497395143704">"промяна на глобалните системни настройки"</string>
@@ -673,7 +671,7 @@
     <string name="faceunlock_multiple_failures" msgid="754137583022792429">"Максималният брой опити за отключване с лице е надвишен"</string>
     <string name="lockscreen_plugged_in" msgid="8057762828355572315">"Зарежда се, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_charged" msgid="4938930459620989972">"Зареден."</string>
-    <string name="lockscreen_battery_short" msgid="3617549178603354656">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
+    <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"Свържете зарядното си устройство."</string>
     <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"Няма SIM карта."</string>
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"В таблета няма SIM карта."</string>
@@ -722,8 +720,8 @@
     <string name="password_keyboard_label_symbol_key" msgid="992280756256536042">"?123"</string>
     <string name="password_keyboard_label_alpha_key" msgid="8001096175167485649">"АБВ"</string>
     <string name="password_keyboard_label_alt_key" msgid="1284820942620288678">"ALT"</string>
-    <string name="hour_ampm" msgid="4329881288269772723">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string>
-    <string name="hour_cap_ampm" msgid="1829009197680861107">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string>
+    <string name="hour_ampm" msgid="4584338083529355982">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string>
+    <string name="hour_cap_ampm" msgid="2083465992940444366">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string>
     <string name="factorytest_failed" msgid="5410270329114212041">"Фабричният тест не бе успешен"</string>
     <string name="factorytest_not_system" msgid="4435201656767276723">"Действието FACTORY_TEST се поддържа само за пакети, инсталирани в /system/app."</string>
     <string name="factorytest_no_action" msgid="872991874799998561">"Не бе намерен пакет, предоставящ действието FACTORY_TEST."</string>
@@ -735,7 +733,7 @@
     <string name="double_tap_toast" msgid="4595046515400268881">"Съвет: Докоснете двукратно, за да увеличите или намалите мащаба."</string>
     <string name="autofill_this_form" msgid="4616758841157816676">"Автопоп."</string>
     <string name="setup_autofill" msgid="7103495070180590814">"Автопоп.: Настройка"</string>
-    <string name="autofill_address_name_separator" msgid="2504700673286691795">" "</string>
+    <string name="autofill_address_name_separator" msgid="6350145154779706772">" "</string>
     <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string>
     <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string>
     <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
@@ -770,6 +768,8 @@
     <string name="permdesc_serialPort" msgid="2991639985224598193">"Разрешава на притежателя достъп до серийни портове посредством приложния програмен интерфейс (API) SerialManager."</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"външен достъп до доставчиците на съдърж."</string>
     <string name="permdesc_accessContentProvidersExternally" msgid="4544346486697853685">"Разрешава на притежателя достъп до доставчиците на съдържание от командния ред. Нормалните приложения би трябвало никога да не се нуждаят от това."</string>
+    <string name="permlab_updateLock" msgid="3527558366616680889">"без авт. актуализации на устройството"</string>
+    <string name="permdesc_updateLock" msgid="1655625832166778492">"Разрешава на притежателя да предложи на системата информация за това, кога ще е възможно неинтерактивно рестартиране за надстройване на устройството."</string>
     <string name="save_password_message" msgid="767344687139195790">"Искате ли браузърът да запомни тази парола?"</string>
     <string name="save_password_notnow" msgid="6389675316706699758">"Не сега"</string>
     <string name="save_password_remember" msgid="6491879678996749466">"Запомняне"</string>
@@ -1008,8 +1008,7 @@
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Задаване на дата"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Задаване"</string>
     <string name="default_permission_group" msgid="2690160991405646128">"По подразбиране"</string>
-    <!-- no translation found for perms_new_perm_prefix (8257740710754301407) -->
-    <skip />
+    <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ffffa3a3">"НОВО: "</font></string>
     <string name="no_permissions" msgid="7283357728219338112">"Не се изискват разрешения"</string>
     <string name="perms_hide" msgid="7283915391320676226"><b>"Скриване"</b></string>
     <string name="perms_show_all" msgid="2671791163933091180"><b>"Показване на всички"</b></string>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index c66451a..189225e 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -26,7 +26,7 @@
     <string name="gigabyteShort" msgid="3259882455212193214">"GB"</string>
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
-    <string name="fileSizeSuffix" msgid="7670819340156489359">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
     <string name="untitled" msgid="4638956954852782576">"&lt;Sense títol&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -314,7 +314,7 @@
     <string name="permdesc_changeComponentState" product="tablet" msgid="8887435740982237294">"Permet que l\'aplicació canviï si un component d\'una altra aplicació està activat o no. Les aplicacions malicioses poden utilitzar aquesta funció per desactivar funcions importants de la tauleta. Cal anar amb compte amb aquest permís, ja que és possible que els components de l\'aplicació esdevinguin inutilitzables, incoherents o inestables."</string>
     <string name="permdesc_changeComponentState" product="default" msgid="1827232484416505615">"Permet que l\'aplicació canviï si un component d\'una altra aplicació està activat o no. Les aplicacions malicioses poden utilitzar aquesta funció per desactivar funcions importants del telèfon. Cal anar amb compte amb aquest permís, perquè és possible que els components de l\'aplicació esdevinguin inutilitzables, incoherents o inestables."</string>
     <string name="permlab_grantRevokePermissions" msgid="4627315351093508795">"concedeix o denega permisos"</string>
-    <string name="permdesc_grantRevokePermissions" msgid="4088642654085850662">"Permet que una aplicació concedeixi o denegui permisos específics per a aquesta o per a altres aplicacions. És possible que les aplicacions malicioses ho facin servir per accedir a funcions a les quals no heu concedit accés."</string>
+    <string name="permdesc_grantRevokePermissions" msgid="4088642654085850662">"Permet que una aplicació concedeixi o denegui permisos específics per a aquesta o per a altres aplicacions. És possible que les aplicacions malicioses ho facin servir per accedir a funcions a les quals no has concedit accés."</string>
     <string name="permlab_setPreferredApplications" msgid="8463181628695396391">"defineix les aplicacions preferides"</string>
     <string name="permdesc_setPreferredApplications" msgid="4973986762241783712">"Permet que l\'aplicació modifiqui les aplicacions preferides. Les aplicacions malicioses poden canviar silenciosament les aplicacions que s\'executen, falsejar les aplicacions existents o recollir dades privades de l\'usuari."</string>
     <string name="permlab_writeSettings" msgid="1365523497395143704">"modificar la configuració global del sistema"</string>
@@ -671,7 +671,7 @@
     <string name="faceunlock_multiple_failures" msgid="754137583022792429">"S\'ha superat el nombre màxim d\'intents de desbloqueig facial"</string>
     <string name="lockscreen_plugged_in" msgid="8057762828355572315">"S\'està carregant, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_charged" msgid="4938930459620989972">"Carregada."</string>
-    <string name="lockscreen_battery_short" msgid="3617549178603354656">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
+    <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g> <xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"Connecteu el carregador."</string>
     <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"No hi ha cap targeta SIM."</string>
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"No hi ha cap targeta SIM a la tauleta."</string>
@@ -720,8 +720,8 @@
     <string name="password_keyboard_label_symbol_key" msgid="992280756256536042">"?123"</string>
     <string name="password_keyboard_label_alpha_key" msgid="8001096175167485649">"ABC"</string>
     <string name="password_keyboard_label_alt_key" msgid="1284820942620288678">"ALT"</string>
-    <string name="hour_ampm" msgid="4329881288269772723">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string>
-    <string name="hour_cap_ampm" msgid="1829009197680861107">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string>
+    <string name="hour_ampm" msgid="4584338083529355982">"<xliff:g id="HOUR">%-l</xliff:g> <xliff:g id="AMPM">%P</xliff:g>"</string>
+    <string name="hour_cap_ampm" msgid="2083465992940444366">"<xliff:g id="HOUR">%-l</xliff:g> <xliff:g id="AMPM">%p</xliff:g>"</string>
     <string name="factorytest_failed" msgid="5410270329114212041">"Error a la prova de fàbrica"</string>
     <string name="factorytest_not_system" msgid="4435201656767276723">"L\'acció FACTORY_TEST només és compatible amb els paquets instal·lats a /system/app."</string>
     <string name="factorytest_no_action" msgid="872991874799998561">"No s\'ha trobat cap paquet que proporcioni l\'acció FACTORY_TEST."</string>
@@ -733,7 +733,7 @@
     <string name="double_tap_toast" msgid="4595046515400268881">"Consell: Pica dos cops per ampliar i per reduir."</string>
     <string name="autofill_this_form" msgid="4616758841157816676">"Em. aut."</string>
     <string name="setup_autofill" msgid="7103495070180590814">"Conf. empl. aut."</string>
-    <string name="autofill_address_name_separator" msgid="2504700673286691795">" "</string>
+    <string name="autofill_address_name_separator" msgid="6350145154779706772">" "</string>
     <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string>
     <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string>
     <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
@@ -768,6 +768,8 @@
     <string name="permdesc_serialPort" msgid="2991639985224598193">"Permet que el titular accedeixi a ports sèrie amb l\'API SerialManager."</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"accedeix als proveïdors de contingut externament"</string>
     <string name="permdesc_accessContentProvidersExternally" msgid="4544346486697853685">"Permet que el titular accedeixi als proveïdors de contingut des de l\'intèrpret d\'ordres. No és necessari per a les aplicacions normals."</string>
+    <string name="permlab_updateLock" msgid="3527558366616680889">"no permetis actualitzacions automàtiques del dispositiu"</string>
+    <string name="permdesc_updateLock" msgid="1655625832166778492">"Permet que el titular ofereixi informació al sistema sobre el moment més adequat per reiniciar el sistema de manera no interactiva per actualitzar-lo."</string>
     <string name="save_password_message" msgid="767344687139195790">"Voleu que el navegador recordi aquesta contrasenya?"</string>
     <string name="save_password_notnow" msgid="6389675316706699758">"Ara no"</string>
     <string name="save_password_remember" msgid="6491879678996749466">"Recorda-ho"</string>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index 89ff9cff3..389a672 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -26,7 +26,7 @@
     <string name="gigabyteShort" msgid="3259882455212193214">"GB"</string>
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
-    <string name="fileSizeSuffix" msgid="7670819340156489359">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
     <string name="untitled" msgid="4638956954852782576">"&lt;Bez názvu&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">".."</string>
@@ -671,7 +671,7 @@
     <string name="faceunlock_multiple_failures" msgid="754137583022792429">"Překročili jste maximální povolený počet pokusů o odemknutí obličejem."</string>
     <string name="lockscreen_plugged_in" msgid="8057762828355572315">"Nabíjení, <xliff:g id="NUMBER">%d</xliff:g> <xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_charged" msgid="4938930459620989972">"Nabito."</string>
-    <string name="lockscreen_battery_short" msgid="3617549178603354656">"<xliff:g id="NUMBER">%d</xliff:g> <xliff:g id="PERCENT">%%</xliff:g>"</string>
+    <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g> <xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"Připojte dobíjecí zařízení."</string>
     <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"Není vložena SIM karta."</string>
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"V tabletu není karta SIM."</string>
@@ -720,8 +720,8 @@
     <string name="password_keyboard_label_symbol_key" msgid="992280756256536042">"?123"</string>
     <string name="password_keyboard_label_alpha_key" msgid="8001096175167485649">"ABC"</string>
     <string name="password_keyboard_label_alt_key" msgid="1284820942620288678">"Alt"</string>
-    <string name="hour_ampm" msgid="4329881288269772723">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string>
-    <string name="hour_cap_ampm" msgid="1829009197680861107">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string>
+    <string name="hour_ampm" msgid="4584338083529355982">"<xliff:g id="HOUR">%-l</xliff:g> <xliff:g id="AMPM">%P</xliff:g>"</string>
+    <string name="hour_cap_ampm" msgid="2083465992940444366">"<xliff:g id="HOUR">%-l</xliff:g> <xliff:g id="AMPM">%p</xliff:g>"</string>
     <string name="factorytest_failed" msgid="5410270329114212041">"Test továrního nastavení se nezdařil"</string>
     <string name="factorytest_not_system" msgid="4435201656767276723">"Test FACTORY_TEST lze provést pouze u balíčků nainstalovaných ve složce /system/app."</string>
     <string name="factorytest_no_action" msgid="872991874799998561">"Nebyl nalezen žádný balíček umožňující test FACTORY_TEST."</string>
@@ -733,7 +733,7 @@
     <string name="double_tap_toast" msgid="4595046515400268881">"Tip: Dvojitým klepnutím můžete zobrazení přiblížit nebo oddálit."</string>
     <string name="autofill_this_form" msgid="4616758841157816676">"Aut.vyp."</string>
     <string name="setup_autofill" msgid="7103495070180590814">"Nastav aut. vyp."</string>
-    <string name="autofill_address_name_separator" msgid="2504700673286691795">" "</string>
+    <string name="autofill_address_name_separator" msgid="6350145154779706772">" "</string>
     <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string>
     <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string>
     <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
@@ -768,6 +768,8 @@
     <string name="permdesc_serialPort" msgid="2991639985224598193">"Umožňuje držiteli přístup k sériovým portům pomocí rozhraní SerialManager API."</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"externí přístup k poskytovatelům obsahu"</string>
     <string name="permdesc_accessContentProvidersExternally" msgid="4544346486697853685">"Umožňuje držiteli získat z příkazového řádku přístup k poskytovatelům obsahu. Běžné aplikace by toto oprávnění neměly nikdy požadovat."</string>
+    <string name="permlab_updateLock" msgid="3527558366616680889">"varovat před automatickou aktualizací"</string>
+    <string name="permdesc_updateLock" msgid="1655625832166778492">"Umožňuje držiteli navrhnout systému informace o vhodné době pro upgrade zařízení neinteraktivním restartováním."</string>
     <string name="save_password_message" msgid="767344687139195790">"Chcete, aby si prohlížeč zapamatoval toto heslo?"</string>
     <string name="save_password_notnow" msgid="6389675316706699758">"Nyní ne"</string>
     <string name="save_password_remember" msgid="6491879678996749466">"Zapamatovat"</string>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index 114cac2..3ca0534 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -26,7 +26,7 @@
     <string name="gigabyteShort" msgid="3259882455212193214">"Gb"</string>
     <string name="terabyteShort" msgid="231613018159186962">"Tb"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"Pb"</string>
-    <string name="fileSizeSuffix" msgid="7670819340156489359">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
     <string name="untitled" msgid="4638956954852782576">"&lt;Uden titel&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">".."</string>
@@ -671,7 +671,7 @@
     <string name="faceunlock_multiple_failures" msgid="754137583022792429">"Det maksimale antal forsøg på at bruge Ansigtslås er overskredet"</string>
     <string name="lockscreen_plugged_in" msgid="8057762828355572315">"Oplader, <xliff:g id="NUMBER">%d</xliff:g> <xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_charged" msgid="4938930459620989972">"Opladt."</string>
-    <string name="lockscreen_battery_short" msgid="3617549178603354656">"<xliff:g id="NUMBER">%d</xliff:g> <xliff:g id="PERCENT">%%</xliff:g>"</string>
+    <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g> <xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"Tilslut din oplader."</string>
     <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"Der er ikke noget SIM-kort."</string>
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Der er ikke noget SIM-kort i tabletcomputeren."</string>
@@ -720,8 +720,8 @@
     <string name="password_keyboard_label_symbol_key" msgid="992280756256536042">"?123"</string>
     <string name="password_keyboard_label_alpha_key" msgid="8001096175167485649">"ABC"</string>
     <string name="password_keyboard_label_alt_key" msgid="1284820942620288678">"ALT"</string>
-    <string name="hour_ampm" msgid="4329881288269772723">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string>
-    <string name="hour_cap_ampm" msgid="1829009197680861107">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string>
+    <string name="hour_ampm" msgid="4584338083529355982">"<xliff:g id="HOUR">%-l</xliff:g> <xliff:g id="AMPM">%P</xliff:g>"</string>
+    <string name="hour_cap_ampm" msgid="2083465992940444366">"<xliff:g id="HOUR">%-l</xliff:g> <xliff:g id="AMPM">%p</xliff:g>"</string>
     <string name="factorytest_failed" msgid="5410270329114212041">"Fabrikstest mislykkedes"</string>
     <string name="factorytest_not_system" msgid="4435201656767276723">"Handlingen FACTORY_TEST understøttes kun af pakker installeret i /system/app."</string>
     <string name="factorytest_no_action" msgid="872991874799998561">"Der blev ikke fundet nogen pakke, som leverer handlingen FACTORY_TEST."</string>
@@ -733,7 +733,7 @@
     <string name="double_tap_toast" msgid="4595046515400268881">"Tip: Dobbeltklik for at zoome ind eller ud."</string>
     <string name="autofill_this_form" msgid="4616758841157816676">"Autofyld"</string>
     <string name="setup_autofill" msgid="7103495070180590814">"Konfigurer Autofyld"</string>
-    <string name="autofill_address_name_separator" msgid="2504700673286691795">" "</string>
+    <string name="autofill_address_name_separator" msgid="6350145154779706772">" "</string>
     <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string>
     <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string>
     <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
@@ -768,6 +768,8 @@
     <string name="permdesc_serialPort" msgid="2991639985224598193">"Tillader, at indehaveren kan få adgang til serielle porte ved hjælp af SerialManager API."</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"adgang til indholdsleverandører eksternt"</string>
     <string name="permdesc_accessContentProvidersExternally" msgid="4544346486697853685">"Giver indehaveren adgang til indholdsleverandører fra startsiden. Bør aldrig være nødvendigt for normale apps."</string>
+    <string name="permlab_updateLock" msgid="3527558366616680889">"undgå automatiske enhedsopdateringer"</string>
+    <string name="permdesc_updateLock" msgid="1655625832166778492">"Giver indehaveren ret til at give systemet oplysninger om, hvornår det vil være et godt tidspunkt for en ikke-interaktiv genstart for at opgradere enheden."</string>
     <string name="save_password_message" msgid="767344687139195790">"Ønsker du, at browseren skal huske denne adgangskode?"</string>
     <string name="save_password_notnow" msgid="6389675316706699758">"Ikke nu"</string>
     <string name="save_password_remember" msgid="6491879678996749466">"Husk"</string>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index 426a8c8..72ac55f 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -26,7 +26,7 @@
     <string name="gigabyteShort" msgid="3259882455212193214">"GB"</string>
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
-    <string name="fileSizeSuffix" msgid="7670819340156489359">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
     <string name="untitled" msgid="4638956954852782576">"&lt;Unbenannt&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -671,7 +671,7 @@
     <string name="faceunlock_multiple_failures" msgid="754137583022792429">"Die maximal zulässige Anzahl an Face Unlock-Versuchen wurde überschritten."</string>
     <string name="lockscreen_plugged_in" msgid="8057762828355572315">"Wird geladen... (<xliff:g id="NUMBER">%d</xliff:g> <xliff:g id="PERCENT">%%</xliff:g>)"</string>
     <string name="lockscreen_charged" msgid="4938930459620989972">"Aufgeladen"</string>
-    <string name="lockscreen_battery_short" msgid="3617549178603354656">"<xliff:g id="NUMBER">%d</xliff:g> <xliff:g id="PERCENT">%%</xliff:g>"</string>
+    <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g> <xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"Bitte Ladegerät anschließen"</string>
     <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"Keine SIM-Karte"</string>
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Keine SIM-Karte im Tablet"</string>
@@ -720,8 +720,8 @@
     <string name="password_keyboard_label_symbol_key" msgid="992280756256536042">"?123"</string>
     <string name="password_keyboard_label_alpha_key" msgid="8001096175167485649">"ABC"</string>
     <string name="password_keyboard_label_alt_key" msgid="1284820942620288678">"ALT"</string>
-    <string name="hour_ampm" msgid="4329881288269772723">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string>
-    <string name="hour_cap_ampm" msgid="1829009197680861107">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string>
+    <string name="hour_ampm" msgid="4584338083529355982">"<xliff:g id="HOUR">%-l</xliff:g> <xliff:g id="AMPM">%P</xliff:g>"</string>
+    <string name="hour_cap_ampm" msgid="2083465992940444366">"<xliff:g id="HOUR">%-l</xliff:g> <xliff:g id="AMPM">%p</xliff:g>"</string>
     <string name="factorytest_failed" msgid="5410270329114212041">"Werkstest fehlgeschlagen"</string>
     <string name="factorytest_not_system" msgid="4435201656767276723">"Die Aktion FACTORY_TEST wird nur für unter \"/system/app\" gespeicherte Pakete unterstützt."</string>
     <string name="factorytest_no_action" msgid="872991874799998561">"Es wurden kein Paket mit der Aktion FACTORY_TEST gefunden."</string>
@@ -733,7 +733,8 @@
     <string name="double_tap_toast" msgid="4595046515400268881">"Tipp: Zum Vergrößern und Verkleinern zweimal tippen"</string>
     <string name="autofill_this_form" msgid="4616758841157816676">"AutoFill"</string>
     <string name="setup_autofill" msgid="7103495070180590814">"AutoFill konfig."</string>
-    <string name="autofill_address_name_separator" msgid="2504700673286691795">" "</string>
+    <!-- no translation found for autofill_address_name_separator (6350145154779706772) -->
+    <skip />
     <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string>
     <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string>
     <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
@@ -768,6 +769,8 @@
     <string name="permdesc_serialPort" msgid="2991639985224598193">"Ermöglicht dem Inhaber den Zugriff auf serielle Schnittstellen über das SerialManager-API"</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"Extern auf Content-Anbieter zugreifen"</string>
     <string name="permdesc_accessContentProvidersExternally" msgid="4544346486697853685">"Berechtigt den Inhaber, extern auf Content-Anbieter zuzugreifen. Bei normalen Apps nicht notwendig"</string>
+    <string name="permlab_updateLock" msgid="3527558366616680889">"Automatische Geräte-Updates abweisen"</string>
+    <string name="permdesc_updateLock" msgid="1655625832166778492">"Ermöglicht dem Inhaber, dem System Informationen zu einem günstigen Zeitpunkt mitzuteilen, an dem ein nicht interaktiver Neustart zur Aktualisierung des Geräts möglich ist"</string>
     <string name="save_password_message" msgid="767344687139195790">"Möchten Sie, dass der Browser dieses Passwort speichert?"</string>
     <string name="save_password_notnow" msgid="6389675316706699758">"Nicht jetzt"</string>
     <string name="save_password_remember" msgid="6491879678996749466">"Speichern"</string>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index 91da279..0e5dd10 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -26,7 +26,7 @@
     <string name="gigabyteShort" msgid="3259882455212193214">"GB"</string>
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
-    <string name="fileSizeSuffix" msgid="7670819340156489359">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
     <string name="untitled" msgid="4638956954852782576">"&lt;Χωρίς τίτλο&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -671,7 +671,7 @@
     <string name="faceunlock_multiple_failures" msgid="754137583022792429">"Έγινε υπέρβαση του μέγιστου αριθμού προσπαθειών Face Unlock"</string>
     <string name="lockscreen_plugged_in" msgid="8057762828355572315">"Φόρτιση, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_charged" msgid="4938930459620989972">"Φορτίστηκε."</string>
-    <string name="lockscreen_battery_short" msgid="3617549178603354656">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
+    <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"Συνδέστε τον φορτιστή."</string>
     <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"Δεν υπάρχει κάρτα SIM."</string>
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Δεν υπάρχει κάρτα SIM στο tablet."</string>
@@ -720,8 +720,8 @@
     <string name="password_keyboard_label_symbol_key" msgid="992280756256536042">"?123"</string>
     <string name="password_keyboard_label_alpha_key" msgid="8001096175167485649">"ΑΒΓ"</string>
     <string name="password_keyboard_label_alt_key" msgid="1284820942620288678">"ALT"</string>
-    <string name="hour_ampm" msgid="4329881288269772723">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string>
-    <string name="hour_cap_ampm" msgid="1829009197680861107">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string>
+    <string name="hour_ampm" msgid="4584338083529355982">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string>
+    <string name="hour_cap_ampm" msgid="2083465992940444366">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string>
     <string name="factorytest_failed" msgid="5410270329114212041">"Η εργοστασιακή δοκιμή απέτυχε"</string>
     <string name="factorytest_not_system" msgid="4435201656767276723">"Η ενέργεια FACTORY_TEST υποστηρίζεται μόνο για πακέτα που είναι εγκατεστημένα στον κατάλογο /system/app."</string>
     <string name="factorytest_no_action" msgid="872991874799998561">"Δεν βρέθηκε πακέτο που να παρέχει την ενέργεια FACTORY_TEST."</string>
@@ -733,7 +733,7 @@
     <string name="double_tap_toast" msgid="4595046515400268881">"Συμβουλή: Πατήστε δύο φορές για μεγέθυνση και σμίκρυνση."</string>
     <string name="autofill_this_form" msgid="4616758841157816676">"Αυτόματη συμπλήρωση"</string>
     <string name="setup_autofill" msgid="7103495070180590814">"Ρύθμ.αυτ.συμπλ."</string>
-    <string name="autofill_address_name_separator" msgid="2504700673286691795">" "</string>
+    <string name="autofill_address_name_separator" msgid="6350145154779706772">" "</string>
     <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string>
     <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string>
     <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
@@ -768,6 +768,8 @@
     <string name="permdesc_serialPort" msgid="2991639985224598193">"Επιτρέπει στον κάτοχο την πρόσβαση στις σειριακές θύρες με τη χρήση του SerialManager API."</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"εξωτερική πρόσβαση σε παρόχους περιεχ."</string>
     <string name="permdesc_accessContentProvidersExternally" msgid="4544346486697853685">"Επιτρέπει στον κάτοχο να έχει πρόσβαση στους παρόχους περιεχομένου από το κέλυφος. Να μην απαιτείται ποτέ για τις κανονικές εφαρμογές."</string>
+    <string name="permlab_updateLock" msgid="3527558366616680889">"απόρριψη αυτόματων ενημερώσεων συσκευής"</string>
+    <string name="permdesc_updateLock" msgid="1655625832166778492">"Επιτρέπει στον κάτοχο να παρέχει στο σύστημα πληροφορίες σχετικά με την κατάλληλη ώρα πραγματοποίησης μιας μη διαδραστικής επανεκκίνησης για την αναβάθμιση της συσκευής."</string>
     <string name="save_password_message" msgid="767344687139195790">"Θέλετε το πρόγραμμα περιήγησης να διατηρήσει αυτόν τον κωδικό πρόσβασης;"</string>
     <string name="save_password_notnow" msgid="6389675316706699758">"Να μην γίνει τώρα"</string>
     <string name="save_password_remember" msgid="6491879678996749466">"Διατήρηση"</string>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index cfd9965..e7ff973 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -26,7 +26,7 @@
     <string name="gigabyteShort" msgid="3259882455212193214">"GB"</string>
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
-    <string name="fileSizeSuffix" msgid="7670819340156489359">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
     <string name="untitled" msgid="4638956954852782576">"&lt;Untitled&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -671,7 +671,7 @@
     <string name="faceunlock_multiple_failures" msgid="754137583022792429">"Maximum Face Unlock attempts exceeded"</string>
     <string name="lockscreen_plugged_in" msgid="8057762828355572315">"Charging, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_charged" msgid="4938930459620989972">"Charged."</string>
-    <string name="lockscreen_battery_short" msgid="3617549178603354656">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
+    <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"Connect your charger."</string>
     <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"No SIM card."</string>
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"No SIM card in tablet."</string>
@@ -720,8 +720,8 @@
     <string name="password_keyboard_label_symbol_key" msgid="992280756256536042">"?123"</string>
     <string name="password_keyboard_label_alpha_key" msgid="8001096175167485649">"ABC"</string>
     <string name="password_keyboard_label_alt_key" msgid="1284820942620288678">"ALT"</string>
-    <string name="hour_ampm" msgid="4329881288269772723">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string>
-    <string name="hour_cap_ampm" msgid="1829009197680861107">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string>
+    <string name="hour_ampm" msgid="4584338083529355982">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string>
+    <string name="hour_cap_ampm" msgid="2083465992940444366">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string>
     <string name="factorytest_failed" msgid="5410270329114212041">"Factory test failed"</string>
     <string name="factorytest_not_system" msgid="4435201656767276723">"The FACTORY_TEST action is only supported for packages installed in /system/app."</string>
     <string name="factorytest_no_action" msgid="872991874799998561">"No package was found that provides the FACTORY_TEST action."</string>
@@ -733,7 +733,7 @@
     <string name="double_tap_toast" msgid="4595046515400268881">"Tip: double-tap to zoom in and out."</string>
     <string name="autofill_this_form" msgid="4616758841157816676">"Auto-fill"</string>
     <string name="setup_autofill" msgid="7103495070180590814">"Set up Auto-fill"</string>
-    <string name="autofill_address_name_separator" msgid="2504700673286691795">" "</string>
+    <string name="autofill_address_name_separator" msgid="6350145154779706772">" "</string>
     <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string>
     <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string>
     <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
@@ -768,6 +768,8 @@
     <string name="permdesc_serialPort" msgid="2991639985224598193">"Allows the holder to access serial ports using the SerialManager API."</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"access content providers externally"</string>
     <string name="permdesc_accessContentProvidersExternally" msgid="4544346486697853685">"Allows the holder to access content providers from the shell. Should never be needed for normal apps."</string>
+    <string name="permlab_updateLock" msgid="3527558366616680889">"discourage automatic device updates"</string>
+    <string name="permdesc_updateLock" msgid="1655625832166778492">"Allows the holder to offer information to the system about when would be a good time for a non-interactive reboot to upgrade the device."</string>
     <string name="save_password_message" msgid="767344687139195790">"Do you want the browser to remember this password?"</string>
     <string name="save_password_notnow" msgid="6389675316706699758">"Not now"</string>
     <string name="save_password_remember" msgid="6491879678996749466">"Remember"</string>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index fe292e6..1a0d479 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -26,7 +26,7 @@
     <string name="gigabyteShort" msgid="3259882455212193214">"GB"</string>
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
-    <string name="fileSizeSuffix" msgid="7670819340156489359">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
     <string name="untitled" msgid="4638956954852782576">"&lt;Sin título&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -671,7 +671,7 @@
     <string name="faceunlock_multiple_failures" msgid="754137583022792429">"Se superó el máximo de intentos permitido para el desbloqueo facial del dispositivo."</string>
     <string name="lockscreen_plugged_in" msgid="8057762828355572315">"Cargando <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_charged" msgid="4938930459620989972">"Cargada."</string>
-    <string name="lockscreen_battery_short" msgid="3617549178603354656">"<xliff:g id="NUMBER">%d</xliff:g> <xliff:g id="PERCENT">%%</xliff:g>"</string>
+    <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g> <xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"Conecta tu cargador."</string>
     <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"No hay tarjeta SIM."</string>
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"No hay tarjeta SIM en el tablet."</string>
@@ -720,8 +720,8 @@
     <string name="password_keyboard_label_symbol_key" msgid="992280756256536042">"?123"</string>
     <string name="password_keyboard_label_alpha_key" msgid="8001096175167485649">"ABC"</string>
     <string name="password_keyboard_label_alt_key" msgid="1284820942620288678">"ALT"</string>
-    <string name="hour_ampm" msgid="4329881288269772723">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string>
-    <string name="hour_cap_ampm" msgid="1829009197680861107">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string>
+    <string name="hour_ampm" msgid="4584338083529355982">"<xliff:g id="HOUR">%-l</xliff:g> <xliff:g id="AMPM">%P</xliff:g>"</string>
+    <string name="hour_cap_ampm" msgid="2083465992940444366">"<xliff:g id="HOUR">%-l</xliff:g> <xliff:g id="AMPM">%p</xliff:g>"</string>
     <string name="factorytest_failed" msgid="5410270329114212041">"Error en la prueba de fábrica"</string>
     <string name="factorytest_not_system" msgid="4435201656767276723">"La acción FACTORY_TEST se admite solamente en paquetes instalados en /system/app."</string>
     <string name="factorytest_no_action" msgid="872991874799998561">"No se ha encontrado ningún paquete que proporcione la acción FACTORY_TEST ."</string>
@@ -733,7 +733,7 @@
     <string name="double_tap_toast" msgid="4595046515400268881">"Consejo: Toca dos veces para acercar y alejar la imagen."</string>
     <string name="autofill_this_form" msgid="4616758841157816676">"Autocompletar"</string>
     <string name="setup_autofill" msgid="7103495070180590814">"Conf. Autocompl."</string>
-    <string name="autofill_address_name_separator" msgid="2504700673286691795">" "</string>
+    <string name="autofill_address_name_separator" msgid="6350145154779706772">" "</string>
     <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string>
     <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string>
     <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
@@ -768,6 +768,8 @@
     <string name="permdesc_serialPort" msgid="2991639985224598193">"Permite acceder a puertos serie a través de la API SerialManager."</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"acceder a proveedores externamente"</string>
     <string name="permdesc_accessContentProvidersExternally" msgid="4544346486697853685">"Permite acceder a los proveedores de contenido desde la interfaz. Las aplicaciones normales nunca deberían necesitarlo."</string>
+    <string name="permlab_updateLock" msgid="3527558366616680889">"desalentar a las actualizaciones automáticas de dispositivos"</string>
+    <string name="permdesc_updateLock" msgid="1655625832166778492">"Permite a su titular a ofrecer información al sistema acerca de cuándo sería un buen momento para reiniciar el sistema no interactivo para actualizar el dispositivo."</string>
     <string name="save_password_message" msgid="767344687139195790">"¿Quieres recordar esta contraseña en el navegador?"</string>
     <string name="save_password_notnow" msgid="6389675316706699758">"Ahora no."</string>
     <string name="save_password_remember" msgid="6491879678996749466">"Recuerda"</string>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index d0c0cb9..a4638fa 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -26,7 +26,7 @@
     <string name="gigabyteShort" msgid="3259882455212193214">"GB"</string>
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
-    <string name="fileSizeSuffix" msgid="7670819340156489359">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
     <string name="untitled" msgid="4638956954852782576">"&lt;Sin título&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"..."</string>
@@ -671,7 +671,7 @@
     <string name="faceunlock_multiple_failures" msgid="754137583022792429">"Se ha superado el número máximo de intentos de desbloqueo facial."</string>
     <string name="lockscreen_plugged_in" msgid="8057762828355572315">"Cargando (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string>
     <string name="lockscreen_charged" msgid="4938930459620989972">"Cargado"</string>
-    <string name="lockscreen_battery_short" msgid="3617549178603354656">"<xliff:g id="NUMBER">%d</xliff:g> <xliff:g id="PERCENT">%%</xliff:g>"</string>
+    <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"Conecta el cargador"</string>
     <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"Falta la tarjeta SIM"</string>
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"No se ha insertado ninguna tarjeta SIM en el tablet."</string>
@@ -720,8 +720,8 @@
     <string name="password_keyboard_label_symbol_key" msgid="992280756256536042">"?123"</string>
     <string name="password_keyboard_label_alpha_key" msgid="8001096175167485649">"ABC"</string>
     <string name="password_keyboard_label_alt_key" msgid="1284820942620288678">"ALT"</string>
-    <string name="hour_ampm" msgid="4329881288269772723">"<xliff:g id="HOUR">%-l</xliff:g> <xliff:g id="AMPM">%P</xliff:g>"</string>
-    <string name="hour_cap_ampm" msgid="1829009197680861107">"<xliff:g id="HOUR">%-l</xliff:g> <xliff:g id="AMPM">%p</xliff:g>"</string>
+    <string name="hour_ampm" msgid="4584338083529355982">"<xliff:g id="HOUR">%-l</xliff:g> <xliff:g id="AMPM">%P</xliff:g>"</string>
+    <string name="hour_cap_ampm" msgid="2083465992940444366">"<xliff:g id="HOUR">%-l</xliff:g> <xliff:g id="AMPM">%p</xliff:g>"</string>
     <string name="factorytest_failed" msgid="5410270329114212041">"Fallo en la prueba de fábrica"</string>
     <string name="factorytest_not_system" msgid="4435201656767276723">"La acción FACTORY_TEST solo es compatible con los paquetes instalados en /system/app."</string>
     <string name="factorytest_no_action" msgid="872991874799998561">"No se ha encontrado ningún paquete que proporcione la acción FACTORY_TEST."</string>
@@ -733,7 +733,7 @@
     <string name="double_tap_toast" msgid="4595046515400268881">"Sugerencia: toca dos veces para ampliar o reducir el contenido."</string>
     <string name="autofill_this_form" msgid="4616758841157816676">"Autocompletar"</string>
     <string name="setup_autofill" msgid="7103495070180590814">"Configurar Autocompletar"</string>
-    <string name="autofill_address_name_separator" msgid="2504700673286691795">" "</string>
+    <string name="autofill_address_name_separator" msgid="6350145154779706772">" "</string>
     <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string>
     <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string>
     <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
@@ -768,6 +768,8 @@
     <string name="permdesc_serialPort" msgid="2991639985224598193">"Permite acceder a puertos serie a través de SerialManager API."</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"acceder a proveedores de contenido externamente"</string>
     <string name="permdesc_accessContentProvidersExternally" msgid="4544346486697853685">"Permite acceder a los proveedores de contenido desde el shell. Las aplicaciones normales nunca deberían necesitar este permiso."</string>
+    <string name="permlab_updateLock" msgid="3527558366616680889">"omitir actualizaciones automáticas"</string>
+    <string name="permdesc_updateLock" msgid="1655625832166778492">"Permite ofrecer información al sistema sobre el momento óptimo para reiniciarse de forma no interactiva y actualizar el dispositivo."</string>
     <string name="save_password_message" msgid="767344687139195790">"¿Quieres que el navegador recuerde esta contraseña?"</string>
     <string name="save_password_notnow" msgid="6389675316706699758">"Ahora no"</string>
     <string name="save_password_remember" msgid="6491879678996749466">"Recordar"</string>
diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml
index 2a4352d..697c8f1 100644
--- a/core/res/res/values-et/strings.xml
+++ b/core/res/res/values-et/strings.xml
@@ -26,7 +26,7 @@
     <string name="gigabyteShort" msgid="3259882455212193214">"GB"</string>
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
-    <string name="fileSizeSuffix" msgid="7670819340156489359">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
     <string name="untitled" msgid="4638956954852782576">"&lt;Pealkirjata&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥."</string>
@@ -671,7 +671,7 @@
     <string name="faceunlock_multiple_failures" msgid="754137583022792429">"Maksimaalne teenusega Face Unlock avamise katsete arv on ületatud"</string>
     <string name="lockscreen_plugged_in" msgid="8057762828355572315">"Laadimine, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_charged" msgid="4938930459620989972">"Laetud."</string>
-    <string name="lockscreen_battery_short" msgid="3617549178603354656">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
+    <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g> <xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"Ühendage laadija."</string>
     <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"SIM-kaarti pole."</string>
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Tahvelarvutis pole SIM-kaarti."</string>
@@ -720,8 +720,8 @@
     <string name="password_keyboard_label_symbol_key" msgid="992280756256536042">"?123"</string>
     <string name="password_keyboard_label_alpha_key" msgid="8001096175167485649">"ABC"</string>
     <string name="password_keyboard_label_alt_key" msgid="1284820942620288678">"ALT"</string>
-    <string name="hour_ampm" msgid="4329881288269772723">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string>
-    <string name="hour_cap_ampm" msgid="1829009197680861107">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string>
+    <string name="hour_ampm" msgid="4584338083529355982">"<xliff:g id="HOUR">%-l</xliff:g> <xliff:g id="AMPM">%P</xliff:g>"</string>
+    <string name="hour_cap_ampm" msgid="2083465992940444366">"<xliff:g id="HOUR">%-l</xliff:g> <xliff:g id="AMPM">%p</xliff:g>"</string>
     <string name="factorytest_failed" msgid="5410270329114212041">"Tehasetest ebaõnnestus"</string>
     <string name="factorytest_not_system" msgid="4435201656767276723">"Toimingut FACTORY_TEST toetatakse ainult kausta \\system\\app installitud pakettide puhul."</string>
     <string name="factorytest_no_action" msgid="872991874799998561">"Ei leitud ühtegi paketti, mis võimaldaks toimingut FACTORY_TEST."</string>
@@ -733,7 +733,7 @@
     <string name="double_tap_toast" msgid="4595046515400268881">"Vihje: suurendamiseks ja vähendamiseks puudutage kaks korda."</string>
     <string name="autofill_this_form" msgid="4616758841157816676">"Automaatne täitmine"</string>
     <string name="setup_autofill" msgid="7103495070180590814">"Automaatse täitmise seadistamine"</string>
-    <string name="autofill_address_name_separator" msgid="2504700673286691795">" "</string>
+    <string name="autofill_address_name_separator" msgid="6350145154779706772">" "</string>
     <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string>
     <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string>
     <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
@@ -768,6 +768,8 @@
     <string name="permdesc_serialPort" msgid="2991639985224598193">"Võimaldab omanikul SerialManageri API-liidese abil jadaportidele juurde pääseda."</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"väline juurdepääs sisupakkujatele"</string>
     <string name="permdesc_accessContentProvidersExternally" msgid="4544346486697853685">"Võimaldab valdajal hankida juurdepääsu sisupakkujatele kesta kaudu. Pole kunagi vajalik tavaliste rakenduste puhul."</string>
+    <string name="permlab_updateLock" msgid="3527558366616680889">"seadme autom. värskendamiste takistamine"</string>
+    <string name="permdesc_updateLock" msgid="1655625832166778492">"Võimaldab valdajal pakkuda süsteemile teavet selle kohta, kas on sobiv aeg mitteinteraktiivseks taaskäivitamiseks, et viia seade üle uuele versioonile."</string>
     <string name="save_password_message" msgid="767344687139195790">"Kas soovite, et brauser jätaks selle parooli meelde?"</string>
     <string name="save_password_notnow" msgid="6389675316706699758">"Mitte praegu"</string>
     <string name="save_password_remember" msgid="6491879678996749466">"Pidage meeles"</string>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index 084e16d..a4a9bff 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -26,7 +26,7 @@
     <string name="gigabyteShort" msgid="3259882455212193214">"گیگابایت"</string>
     <string name="terabyteShort" msgid="231613018159186962">"ترابایت"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"پتابایت"</string>
-    <string name="fileSizeSuffix" msgid="7670819340156489359">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
     <string name="untitled" msgid="4638956954852782576">"&lt;بدون عنوان&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">".."</string>
@@ -313,10 +313,8 @@
     <string name="permlab_changeComponentState" msgid="6335576775711095931">"فعال یا غیر فعال کردن اجزای برنامه"</string>
     <string name="permdesc_changeComponentState" product="tablet" msgid="8887435740982237294">"به برنامه اجازه می‎دهد تا فعال بودن یا نبودن اجزای برنامه دیگر را تغییر دهد. برنامه‎های مخرب می‎توانند از آن استفاده کنند تا قابلیتهای مهم رایانه لوحی را غیرفعال کنند. باید دقت کرد که با این مجوز ممکن است وضعیت اجزای برنامه ناپایدار، ناهماهنگ یا غیرقابل استفاده شود."</string>
     <string name="permdesc_changeComponentState" product="default" msgid="1827232484416505615">"به برنامه اجازه می‎دهد تا فعال بودن یا غیرفعال بودن جزئیات برنامه دیگر را تغییر دهد. برنامه‎های مخرب می‎توانند از آن استفاده کنند تا ویژگیهای مهم را غیرفعال کنند. برای این مجوز باید دقت کنید چون ممکن است وضعیت جزئیات برنامه ناپایدار، بی‎ثبات یا غیرقابل استفاده شود."</string>
-    <!-- no translation found for permlab_grantRevokePermissions (4627315351093508795) -->
-    <skip />
-    <!-- no translation found for permdesc_grantRevokePermissions (4088642654085850662) -->
-    <skip />
+    <string name="permlab_grantRevokePermissions" msgid="4627315351093508795">"ارائه یا لغو مجوزها"</string>
+    <string name="permdesc_grantRevokePermissions" msgid="4088642654085850662">"به یک برنامه کاربردی اجازه می‌دهد تا مجوزهای خاصی را برای خود یا دیگر برنامه‌ها ارائه کرده یا آنها را لغو کند. برنامه‌های مضر از این حالت برای دسترسی به ویژگی‌هایی استفاده می‌کنند که شما اجازه آن را در اختیارشان قرار نداده‌اید."</string>
     <string name="permlab_setPreferredApplications" msgid="8463181628695396391">"تنظیم برنامه‎های ترجیحی"</string>
     <string name="permdesc_setPreferredApplications" msgid="4973986762241783712">"به برنامه اجازه می‎دهد تا برنامه‎های ترجیحی شما را تغییر دهد. برنامه‎های مخرب می‎توانند بدون اعلان برنامه‎هایی را که اجرا می‎شوند، تغییر دهند خود را به جای برنامه‎های کنونی قلمداد کنند تا داده‎های شخصی را از شما جمع آوری کنند."</string>
     <string name="permlab_writeSettings" msgid="1365523497395143704">"اصلاح کردن تنظیمات سیستم کلی"</string>
@@ -673,7 +671,7 @@
     <string name="faceunlock_multiple_failures" msgid="754137583022792429">"دفعات تلاش برای Face Unlock از حداکثر مجاز بیشتر شد"</string>
     <string name="lockscreen_plugged_in" msgid="8057762828355572315">"در حال شارژ،<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_charged" msgid="4938930459620989972">"شارژ شد."</string>
-    <string name="lockscreen_battery_short" msgid="3617549178603354656">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
+    <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"شارژر خود را متصل کنید."</string>
     <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"سیم کارت موجود نیست."</string>
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"سیم کارت درون رایانه لوحی نیست."</string>
@@ -722,8 +720,8 @@
     <string name="password_keyboard_label_symbol_key" msgid="992280756256536042">"?123"</string>
     <string name="password_keyboard_label_alpha_key" msgid="8001096175167485649">"ABC"</string>
     <string name="password_keyboard_label_alt_key" msgid="1284820942620288678">"ALT"</string>
-    <string name="hour_ampm" msgid="4329881288269772723">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string>
-    <string name="hour_cap_ampm" msgid="1829009197680861107">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string>
+    <string name="hour_ampm" msgid="4584338083529355982">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string>
+    <string name="hour_cap_ampm" msgid="2083465992940444366">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string>
     <string name="factorytest_failed" msgid="5410270329114212041">"تست کارخانه انجام نشد"</string>
     <string name="factorytest_not_system" msgid="4435201656767276723">"عملکرد FACTORY_TEST تنها برای بسته های نصب شده در /system/app پشتیبانی می شود."</string>
     <string name="factorytest_no_action" msgid="872991874799998561">"بسته ای یافت نشد که عملکرد FACTORY_TEST را ارائه کند."</string>
@@ -735,7 +733,7 @@
     <string name="double_tap_toast" msgid="4595046515400268881">"نکته: برای بزرگنمایی و کوچکنمایی، دو بار ضربه بزنید."</string>
     <string name="autofill_this_form" msgid="4616758841157816676">"تکمیل خودکار"</string>
     <string name="setup_autofill" msgid="7103495070180590814">"راه‌اندازی تکمیل خودکار"</string>
-    <string name="autofill_address_name_separator" msgid="2504700673286691795">" "</string>
+    <string name="autofill_address_name_separator" msgid="6350145154779706772">" "</string>
     <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string>
     <string name="autofill_address_summary_separator" msgid="7483307893170324129">"، "</string>
     <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
@@ -770,6 +768,8 @@
     <string name="permdesc_serialPort" msgid="2991639985224598193">"به دارنده اجازه می‌دهد با استفاده از SerialManager API به درگاه‌های سریال دسترسی داشته باشد."</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"دسترسی خارجی به ارائه‌دهندگان محتوا"</string>
     <string name="permdesc_accessContentProvidersExternally" msgid="4544346486697853685">"به دارنده اجازه می‌دهد تا از خارج برنامه به ارائه‌دهندگان محتوا دسترسی داشته باشد. هرگز برای برنامه‌های معمولی به آن نیازی نیست."</string>
+    <string name="permlab_updateLock" msgid="3527558366616680889">"ترغیب به انجام ندادن به‌روزرسانی‌های خودکار دستگاه"</string>
+    <string name="permdesc_updateLock" msgid="1655625832166778492">"به دارنده اجازه می‌دهد اطلاعاتی در مورد زمان مناسب برای یک راه‌اندازی مجدد غیرتعاملی جهت ارتقای دستگاه را به سیستم ارائه دهد."</string>
     <string name="save_password_message" msgid="767344687139195790">"می خواهید مرورگر این رمز ورود را به خاطر داشته باشد؟"</string>
     <string name="save_password_notnow" msgid="6389675316706699758">"اکنون خیر"</string>
     <string name="save_password_remember" msgid="6491879678996749466">"به خاطر سپردن"</string>
@@ -1008,8 +1008,7 @@
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"تاریخ تنظیم"</string>
     <string name="date_time_set" msgid="5777075614321087758">"تنظیم"</string>
     <string name="default_permission_group" msgid="2690160991405646128">"پیش فرض"</string>
-    <!-- no translation found for perms_new_perm_prefix (8257740710754301407) -->
-    <skip />
+    <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ffffa3a3">"جدید: "</font></string>
     <string name="no_permissions" msgid="7283357728219338112">"مجوزی لازم نیست"</string>
     <string name="perms_hide" msgid="7283915391320676226"><b>"پنهان کردن"</b></string>
     <string name="perms_show_all" msgid="2671791163933091180"><b>"نمایش همه"</b></string>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index ee7efc8..1b8b18a 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -26,7 +26,7 @@
     <string name="gigabyteShort" msgid="3259882455212193214">"Gt"</string>
     <string name="terabyteShort" msgid="231613018159186962">"Tt"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"Pt"</string>
-    <string name="fileSizeSuffix" msgid="7670819340156489359">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
     <string name="untitled" msgid="4638956954852782576">"&lt;Nimetön&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">".."</string>
@@ -671,7 +671,7 @@
     <string name="faceunlock_multiple_failures" msgid="754137583022792429">"Face Unlock -yrityksiä tehty suurin sallittu määrä."</string>
     <string name="lockscreen_plugged_in" msgid="8057762828355572315">"Ladataan (<xliff:g id="NUMBER">%d</xliff:g> <xliff:g id="PERCENT">%%</xliff:g>)"</string>
     <string name="lockscreen_charged" msgid="4938930459620989972">"Muutettu."</string>
-    <string name="lockscreen_battery_short" msgid="3617549178603354656">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
+    <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g> <xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"Kytke laturi."</string>
     <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"Ei SIM-korttia."</string>
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Tablet-laitteessa ei ole SIM-korttia."</string>
@@ -720,8 +720,8 @@
     <string name="password_keyboard_label_symbol_key" msgid="992280756256536042">"?123"</string>
     <string name="password_keyboard_label_alpha_key" msgid="8001096175167485649">"ABC"</string>
     <string name="password_keyboard_label_alt_key" msgid="1284820942620288678">"ALT"</string>
-    <string name="hour_ampm" msgid="4329881288269772723">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string>
-    <string name="hour_cap_ampm" msgid="1829009197680861107">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string>
+    <string name="hour_ampm" msgid="4584338083529355982">"<xliff:g id="HOUR">%-l</xliff:g> <xliff:g id="AMPM">%P</xliff:g>"</string>
+    <string name="hour_cap_ampm" msgid="2083465992940444366">"<xliff:g id="HOUR">%-l</xliff:g> <xliff:g id="AMPM">%p</xliff:g>"</string>
     <string name="factorytest_failed" msgid="5410270329114212041">"Tehdastesti epäonnistui"</string>
     <string name="factorytest_not_system" msgid="4435201656767276723">"FACTORY_TEST-toimintoa tuetaan vain paketeille, jotka on tallennettu kansioon /system/app."</string>
     <string name="factorytest_no_action" msgid="872991874799998561">"FACTORY_TEST-toiminnon tarjoavaa pakettia ei löytynyt."</string>
@@ -733,7 +733,7 @@
     <string name="double_tap_toast" msgid="4595046515400268881">"Vinkki: lähennä ja loitonna kaksoisnapauttamalla."</string>
     <string name="autofill_this_form" msgid="4616758841157816676">"Aut. täyttö"</string>
     <string name="setup_autofill" msgid="7103495070180590814">"Määritä autom. täyttö"</string>
-    <string name="autofill_address_name_separator" msgid="2504700673286691795">" "</string>
+    <string name="autofill_address_name_separator" msgid="6350145154779706772">" "</string>
     <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string>
     <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string>
     <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
@@ -768,6 +768,8 @@
     <string name="permdesc_serialPort" msgid="2991639985224598193">"Luvan haltija voi käyttää sarjaportteja SerialManager-sovellusliittymän avulla."</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"käytä ulkoisia sisällöntarjoajia"</string>
     <string name="permdesc_accessContentProvidersExternally" msgid="4544346486697853685">"Antaa luvan haltijan käyttää liittymän sisällöntarjoajia. Ei normaalien sovelluksien käyttöön."</string>
+    <string name="permlab_updateLock" msgid="3527558366616680889">"estä automaattiset laitteen päivitykset"</string>
+    <string name="permdesc_updateLock" msgid="1655625832166778492">"Antaa luvan haltijan ilmoittaa järjestelmälle, milloin on hyvä aika suorittaa laitteen päivitys."</string>
     <string name="save_password_message" msgid="767344687139195790">"Haluatko selaimen muistavan tämän salasanan?"</string>
     <string name="save_password_notnow" msgid="6389675316706699758">"Ei nyt"</string>
     <string name="save_password_remember" msgid="6491879678996749466">"Muista"</string>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index bca5701..b19a7de 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -26,7 +26,7 @@
     <string name="gigabyteShort" msgid="3259882455212193214">"Go"</string>
     <string name="terabyteShort" msgid="231613018159186962">"To"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"Po"</string>
-    <string name="fileSizeSuffix" msgid="7670819340156489359">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
     <string name="untitled" msgid="4638956954852782576">"&lt;Sans nom&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -671,7 +671,7 @@
     <string name="faceunlock_multiple_failures" msgid="754137583022792429">"Nombre maximal autorisé de tentatives Face Unlock atteint."</string>
     <string name="lockscreen_plugged_in" msgid="8057762828355572315">"En charge (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string>
     <string name="lockscreen_charged" msgid="4938930459620989972">"Chargé"</string>
-    <string name="lockscreen_battery_short" msgid="3617549178603354656">"<xliff:g id="NUMBER">%d</xliff:g> <xliff:g id="PERCENT">%%</xliff:g>"</string>
+    <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g> <xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"Branchez votre chargeur."</string>
     <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"Aucune carte SIM n\'a été trouvée."</string>
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Aucune carte SIM n\'est insérée dans la tablette."</string>
@@ -720,8 +720,8 @@
     <string name="password_keyboard_label_symbol_key" msgid="992280756256536042">"?123"</string>
     <string name="password_keyboard_label_alpha_key" msgid="8001096175167485649">"ABC"</string>
     <string name="password_keyboard_label_alt_key" msgid="1284820942620288678">"ALT"</string>
-    <string name="hour_ampm" msgid="4329881288269772723">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string>
-    <string name="hour_cap_ampm" msgid="1829009197680861107">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string>
+    <string name="hour_ampm" msgid="4584338083529355982">"<xliff:g id="HOUR">%-l</xliff:g> <xliff:g id="AMPM">%P</xliff:g>"</string>
+    <string name="hour_cap_ampm" msgid="2083465992940444366">"<xliff:g id="HOUR">%-l</xliff:g> <xliff:g id="AMPM">%p</xliff:g>"</string>
     <string name="factorytest_failed" msgid="5410270329114212041">"Échec du test usine"</string>
     <string name="factorytest_not_system" msgid="4435201656767276723">"L\'action FACTORY_TEST est uniquement prise en charge pour les paquets de données installés dans in/system/app."</string>
     <string name="factorytest_no_action" msgid="872991874799998561">"Impossible de trouver un paquet proposant l\'action FACTORY_TEST."</string>
@@ -733,7 +733,7 @@
     <string name="double_tap_toast" msgid="4595046515400268881">"Conseil : Appuyez deux fois pour faire un zoom avant ou arrière."</string>
     <string name="autofill_this_form" msgid="4616758841157816676">"Saisie auto"</string>
     <string name="setup_autofill" msgid="7103495070180590814">"Conf. saisie auto"</string>
-    <string name="autofill_address_name_separator" msgid="2504700673286691795">" "</string>
+    <string name="autofill_address_name_separator" msgid="6350145154779706772">" "</string>
     <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string>
     <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string>
     <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
@@ -768,6 +768,8 @@
     <string name="permdesc_serialPort" msgid="2991639985224598193">"Permet à l\'application autorisée d\'accéder aux ports série avec l\'API SerialManager."</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"accès externe fournisseurs de contenu"</string>
     <string name="permdesc_accessContentProvidersExternally" msgid="4544346486697853685">"Permettre à l\'application titulaire d\'accéder à des fournisseurs de contenu depuis la commande shell. Les applications standards ne devraient jamais avoir recours à cette autorisation."</string>
+    <string name="permlab_updateLock" msgid="3527558366616680889">"déconseiller mises à jour auto appareil"</string>
+    <string name="permdesc_updateLock" msgid="1655625832166778492">"Permet à l\'application autorisée d\'indiquer au système le moment opportun pour un redémarrage non interactif en vue de la mise à jour de l\'appareil."</string>
     <string name="save_password_message" msgid="767344687139195790">"Voulez-vous que le navigateur se souvienne de ce mot de passe ?"</string>
     <string name="save_password_notnow" msgid="6389675316706699758">"Pas maintenant"</string>
     <string name="save_password_remember" msgid="6491879678996749466">"Mémoriser"</string>
@@ -863,8 +865,8 @@
     <string name="days" msgid="4774547661021344602">"jours"</string>
     <string name="hour" msgid="2126771916426189481">"heure"</string>
     <string name="hours" msgid="894424005266852993">"heures"</string>
-    <string name="minute" msgid="9148878657703769868">"mn"</string>
-    <string name="minutes" msgid="5646001005827034509">"mn"</string>
+    <string name="minute" msgid="9148878657703769868">"min"</string>
+    <string name="minutes" msgid="5646001005827034509">"min"</string>
     <string name="second" msgid="3184235808021478">"s"</string>
     <string name="seconds" msgid="3161515347216589235">"s"</string>
     <string name="week" msgid="5617961537173061583">"semaine"</string>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index 1454253..d4b921f 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -26,7 +26,7 @@
     <string name="gigabyteShort" msgid="3259882455212193214">"GB"</string>
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
-    <string name="fileSizeSuffix" msgid="7670819340156489359">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
     <string name="untitled" msgid="4638956954852782576">"&lt;शीर्षक-रहित&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -314,7 +314,7 @@
     <string name="permdesc_changeComponentState" product="tablet" msgid="8887435740982237294">"एप्‍लिकेशन को यह बदलने देता है कि किसी अन्‍य एप्‍लिकेशन का घटक सक्षम है या नहीं. दुर्भावनापूर्ण एप्‍लिकेशन महत्‍वपूर्ण फ़ोन क्षमताओं को अक्षम करने में इसका उपयोग कर सकते हैं. इस अनुमति का उपयोग सावधानी के साथ करना चाहिए, क्योंकि इससे एप्‍लिकेशन घटकों के अनुपयोगी, असंगत, या अस्‍थिर स्‍थिति में जाने की संभावना है."</string>
     <string name="permdesc_changeComponentState" product="default" msgid="1827232484416505615">"एप्‍लिकेशन को यह बदलने देता है कि किसी अन्‍य एप्‍लिकेशन का घटक सक्षम है या नहीं. दुर्भावनापूर्ण एप्‍लिकेशन महत्‍वपूर्ण फ़ोन क्षमताओं को अक्षम करने में इसका उपयोग कर सकते हैं. इस अनुमति का उपयोग सावधानी के साथ करना चाहिए, क्योंकि इससे एप्‍लिकेशन घटकों के अनुपयोगी, असंगत, या अस्‍थिर स्‍थिति में जाने की संभावना है."</string>
     <string name="permlab_grantRevokePermissions" msgid="4627315351093508795">"अनुमति दें या रद्द करें"</string>
-    <string name="permdesc_grantRevokePermissions" msgid="4088642654085850662">"एप्लिकेशन को उसके या अन्य एप्लिकेशन के लिए विशेष अनुमतियां देने या रद्द करने देता है. दुर्भावनापूर्ण एप्लिकेशन इसका उपयोग उन विशेषताओं तक पहुंचने के लिए कर सकते हैं जो आपने उन्हें नहीं दी हैं."</string>
+    <string name="permdesc_grantRevokePermissions" msgid="4088642654085850662">"एप्लिकेशन को उसके या अन्य एप्लिकेशन के लिए विशेष अनुमतियां देने या रद्द करने देता है. दुर्भावनापूर्ण एप्लिकेशन इसका उपयोग उन सुविधाओं तक पहुंचने के लिए कर सकते हैं जो आपने उन्हें नहीं दी हैं."</string>
     <string name="permlab_setPreferredApplications" msgid="8463181628695396391">"पसंदीदा एप्‍लिकेशन सेट करें"</string>
     <string name="permdesc_setPreferredApplications" msgid="4973986762241783712">"एप्लिकेशन को आपके पसंदीदा एप्लिकेशन को संशोधित करने देता है. दुर्भावनापूर्ण एप्लिकेशन आपसे निजी डेटा एकत्रित करने के लिए आपके मौजूदा एप्लिकेशन को स्पूफ़ करके, चलाए जाने वाले एप्लिकेशन को चुपचाप बदल सकते हैं."</string>
     <string name="permlab_writeSettings" msgid="1365523497395143704">"वैश्विक सिस्‍टम सेटिंग संशोधित करें"</string>
@@ -671,7 +671,7 @@
     <string name="faceunlock_multiple_failures" msgid="754137583022792429">"फेस अनलॉक के अधिकतम प्रयासों की सीमा पार हो गई"</string>
     <string name="lockscreen_plugged_in" msgid="8057762828355572315">"चार्ज हो रही है, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_charged" msgid="4938930459620989972">"चार्ज हो चुकी है."</string>
-    <string name="lockscreen_battery_short" msgid="3617549178603354656">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
+    <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"अपना चार्जर कनेक्‍ट करें."</string>
     <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"कोई सिम कार्ड नहीं है."</string>
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"टेबलेट में कोई सिम कार्ड नहीं है."</string>
@@ -720,8 +720,8 @@
     <string name="password_keyboard_label_symbol_key" msgid="992280756256536042">"?123"</string>
     <string name="password_keyboard_label_alpha_key" msgid="8001096175167485649">"ABC"</string>
     <string name="password_keyboard_label_alt_key" msgid="1284820942620288678">"ALT"</string>
-    <string name="hour_ampm" msgid="4329881288269772723">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string>
-    <string name="hour_cap_ampm" msgid="1829009197680861107">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string>
+    <string name="hour_ampm" msgid="4584338083529355982">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string>
+    <string name="hour_cap_ampm" msgid="2083465992940444366">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string>
     <string name="factorytest_failed" msgid="5410270329114212041">"फ़ैक्‍ट्री परीक्षण विफल"</string>
     <string name="factorytest_not_system" msgid="4435201656767276723">"FACTORY_TEST क्रिया केवल /system/app में इंस्‍टॉल किए गए पैकेज के लिए समर्थित है."</string>
     <string name="factorytest_no_action" msgid="872991874799998561">"ऐसा कोई पैकेज नहीं मिला था जो FACTORY_TEST कार्रवाई प्रदान करता हो."</string>
@@ -733,7 +733,7 @@
     <string name="double_tap_toast" msgid="4595046515400268881">"युक्ति: ज़ूम इन और आउट करने के लिए डबल-टैप करें."</string>
     <string name="autofill_this_form" msgid="4616758841157816676">"स्‍वत: भरण"</string>
     <string name="setup_autofill" msgid="7103495070180590814">"स्वत: भरण सेट करें"</string>
-    <string name="autofill_address_name_separator" msgid="2504700673286691795">" "</string>
+    <string name="autofill_address_name_separator" msgid="6350145154779706772">" "</string>
     <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string>
     <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string>
     <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
@@ -768,6 +768,8 @@
     <string name="permdesc_serialPort" msgid="2991639985224598193">"SerialManager API का उपयोग करके धारक को सीरियल पोर्ट पर पहुंच प्रदान करता है."</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"बाह्य रूप से सामग्री प्रदाताओं पर पहुंच"</string>
     <string name="permdesc_accessContentProvidersExternally" msgid="4544346486697853685">"धारक को शेल से सामग्री प्रदाताओं तक पहुंचने देता है. सामान्य एप्लिकेशन के लिए कभी भी आवश्यकता नहीं होनी चाहिए."</string>
+    <string name="permlab_updateLock" msgid="3527558366616680889">"स्वचालित उपकरण अपडेट का समर्थन न करें"</string>
+    <string name="permdesc_updateLock" msgid="1655625832166778492">"धारक को उपकरण अपग्रेड करने के लिए, गैर-सहभागी रीबूट के ठीक समय के बारे में सिस्टम पर जानकारी प्रस्तुत करने देता है."</string>
     <string name="save_password_message" msgid="767344687139195790">"क्‍या आप चाहते हैं कि ब्राउज़र पासवर्ड को याद रखे?"</string>
     <string name="save_password_notnow" msgid="6389675316706699758">"अभी नहीं"</string>
     <string name="save_password_remember" msgid="6491879678996749466">"याद रखें"</string>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index 1908840..fbd3a3d 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -26,7 +26,7 @@
     <string name="gigabyteShort" msgid="3259882455212193214">"GB"</string>
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
-    <string name="fileSizeSuffix" msgid="7670819340156489359">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
     <string name="untitled" msgid="4638956954852782576">"&lt;Bez naslova&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -671,7 +671,7 @@
     <string name="faceunlock_multiple_failures" msgid="754137583022792429">"Premašen je maksimalni broj Otključavanja licem"</string>
     <string name="lockscreen_plugged_in" msgid="8057762828355572315">"Punjenje, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_charged" msgid="4938930459620989972">"Napunjeno."</string>
-    <string name="lockscreen_battery_short" msgid="3617549178603354656">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
+    <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"Priključite punjač."</string>
     <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"Nema SIM kartice."</string>
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"U tabletnom uređaju nema SIM kartice."</string>
@@ -720,8 +720,8 @@
     <string name="password_keyboard_label_symbol_key" msgid="992280756256536042">"?123"</string>
     <string name="password_keyboard_label_alpha_key" msgid="8001096175167485649">"ABC"</string>
     <string name="password_keyboard_label_alt_key" msgid="1284820942620288678">"ALT"</string>
-    <string name="hour_ampm" msgid="4329881288269772723">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string>
-    <string name="hour_cap_ampm" msgid="1829009197680861107">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string>
+    <string name="hour_ampm" msgid="4584338083529355982">"<xliff:g id="HOUR">%-l</xliff:g> <xliff:g id="AMPM">%P</xliff:g>"</string>
+    <string name="hour_cap_ampm" msgid="2083465992940444366">"<xliff:g id="HOUR">%-l</xliff:g> <xliff:g id="AMPM">%p</xliff:g>"</string>
     <string name="factorytest_failed" msgid="5410270329114212041">"Tvorničko testiranje nije uspjelo"</string>
     <string name="factorytest_not_system" msgid="4435201656767276723">"Radnja FACTORY_TEST podržana je samo za pakete instalirane na /sustavu/aplikaciji."</string>
     <string name="factorytest_no_action" msgid="872991874799998561">"Nije pronađen paket koji sadrži radnju FACTORY_TEST."</string>
@@ -733,7 +733,7 @@
     <string name="double_tap_toast" msgid="4595046515400268881">"Savjet: Dvaput dotaknite za povećavanje i smanjivanje."</string>
     <string name="autofill_this_form" msgid="4616758841157816676">"Aut.pop."</string>
     <string name="setup_autofill" msgid="7103495070180590814">"Post. Auto. pop."</string>
-    <string name="autofill_address_name_separator" msgid="2504700673286691795">" "</string>
+    <string name="autofill_address_name_separator" msgid="6350145154779706772">" "</string>
     <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string>
     <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string>
     <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
@@ -768,6 +768,8 @@
     <string name="permdesc_serialPort" msgid="2991639985224598193">"Rukovatelju omogućuje pristup serijskim priključcima pomoću značajke SerialManager API."</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"pristup pružateljima sadržaja izvana"</string>
     <string name="permdesc_accessContentProvidersExternally" msgid="4544346486697853685">"Omogućuje vlasniku pristup pružateljima sadržaja iz programske ovojnice. Ne bi trebalo biti potrebno za normalne aplikacije."</string>
+    <string name="permlab_updateLock" msgid="3527558366616680889">"odvratiti automatska ažuriranja uređaja"</string>
+    <string name="permdesc_updateLock" msgid="1655625832166778492">"Omogućuje vlasniku davanje informacija sustavu o pogodnom trenutku za nadogradnju uređaja ponovnim pokretanjem bez interakcije."</string>
     <string name="save_password_message" msgid="767344687139195790">"Želite li da preglednik zapamti ovu zaporku?"</string>
     <string name="save_password_notnow" msgid="6389675316706699758">"Ne sada"</string>
     <string name="save_password_remember" msgid="6491879678996749466">"Zapamti"</string>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index 81f697b..c6190fd 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -26,7 +26,7 @@
     <string name="gigabyteShort" msgid="3259882455212193214">"GB"</string>
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
-    <string name="fileSizeSuffix" msgid="7670819340156489359">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
     <string name="untitled" msgid="4638956954852782576">"&lt;Névtelen&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -671,7 +671,7 @@
     <string name="faceunlock_multiple_failures" msgid="754137583022792429">"Elérte az arcalapú feloldási kísérletek maximális számát"</string>
     <string name="lockscreen_plugged_in" msgid="8057762828355572315">"Töltés (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string>
     <string name="lockscreen_charged" msgid="4938930459620989972">"Feltöltve."</string>
-    <string name="lockscreen_battery_short" msgid="3617549178603354656">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
+    <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"Csatlakoztassa a töltőt."</string>
     <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"Nincs SIM-kártya."</string>
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Nincs SIM-kártya a táblagépben."</string>
@@ -720,8 +720,8 @@
     <string name="password_keyboard_label_symbol_key" msgid="992280756256536042">"?123"</string>
     <string name="password_keyboard_label_alpha_key" msgid="8001096175167485649">"ABC"</string>
     <string name="password_keyboard_label_alt_key" msgid="1284820942620288678">"ALT"</string>
-    <string name="hour_ampm" msgid="4329881288269772723">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string>
-    <string name="hour_cap_ampm" msgid="1829009197680861107">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string>
+    <string name="hour_ampm" msgid="4584338083529355982">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string>
+    <string name="hour_cap_ampm" msgid="2083465992940444366">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string>
     <string name="factorytest_failed" msgid="5410270329114212041">"A gyári teszt sikertelen"</string>
     <string name="factorytest_not_system" msgid="4435201656767276723">"A FACTORY_TEST művelet csak a /system/app könyvtárba telepített csomagok esetében használható."</string>
     <string name="factorytest_no_action" msgid="872991874799998561">"Nem található olyan csomag, amely tartalmazná a FACTORY_TEST műveletet."</string>
@@ -733,7 +733,7 @@
     <string name="double_tap_toast" msgid="4595046515400268881">"Tipp: érintse meg kétszer a nagyításhoz és kicsinyítéshez."</string>
     <string name="autofill_this_form" msgid="4616758841157816676">"Kitöltés"</string>
     <string name="setup_autofill" msgid="7103495070180590814">"Kitöltés beáll."</string>
-    <string name="autofill_address_name_separator" msgid="2504700673286691795">" "</string>
+    <string name="autofill_address_name_separator" msgid="6350145154779706772">" "</string>
     <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string>
     <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string>
     <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
@@ -768,6 +768,8 @@
     <string name="permdesc_serialPort" msgid="2991639985224598193">"Lehetővé teszi a tulajdonos számára a soros portok elérését a SerialManager API segítségével."</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"tartalomszolgáltatók külső elérése"</string>
     <string name="permdesc_accessContentProvidersExternally" msgid="4544346486697853685">"Lehetővé teszi, hogy a tulajdonos hozzáférjen a tartalomszolgáltatókhoz a shellből. Normál alkalmazásoknál nem szükséges."</string>
+    <string name="permlab_updateLock" msgid="3527558366616680889">"automatikus eszközfrissítés ellenzése"</string>
+    <string name="permdesc_updateLock" msgid="1655625832166778492">"Lehetővé teszi a tulajdonos számára, hogy információkat adjon meg a rendszer számára azzal kapcsolatban, hogy mikor lehet elvégezni egy beavatkozás nélküli újraindítást az eszköz frissítése céljából."</string>
     <string name="save_password_message" msgid="767344687139195790">"Szeretné, hogy a böngésző megjegyezze a jelszót?"</string>
     <string name="save_password_notnow" msgid="6389675316706699758">"Most nem"</string>
     <string name="save_password_remember" msgid="6491879678996749466">"Megjegyzés"</string>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index 08b0f60..7d08048 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -26,7 +26,7 @@
     <string name="gigabyteShort" msgid="3259882455212193214">"GB"</string>
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
-    <string name="fileSizeSuffix" msgid="7670819340156489359">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
     <string name="untitled" msgid="4638956954852782576">"&lt;Tanpa judul&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -68,7 +68,7 @@
     <string name="CLIRDefaultOffNextCallOn" msgid="6179425182856418465">"Nomor penelepon bawaan tidak dibatasi. Panggilan selanjutnya: Dibatasi"</string>
     <string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"Nomor penelepon bawaan tidak dibatasi. Panggilan selanjutnya: Tidak dibatasi"</string>
     <string name="serviceNotProvisioned" msgid="8614830180508686666">"Layanan tidak diperlengkapi."</string>
-    <string name="CLIRPermanent" msgid="3377371145926835671">"Anda tidak dapat mengubah setelan nomor penelepon."</string>
+    <string name="CLIRPermanent" msgid="3377371145926835671">"Anda tidak dapat mengubah pengaturan nomor penelepon."</string>
     <string name="RestrictedChangedTitle" msgid="5592189398956187498">"Akses terbatas berubah"</string>
     <string name="RestrictedOnData" msgid="8653794784690065540">"Layanan data dicekal."</string>
     <string name="RestrictedOnEmergency" msgid="6581163779072833665">"Layanan darurat dicekal."</string>
@@ -120,15 +120,15 @@
     <string name="httpErrorUnsupportedScheme" msgid="5015730812906192208">"Protokol tidak didukung."</string>
     <string name="httpErrorFailedSslHandshake" msgid="96549606000658641">"Tidak dapat membuat sambungan aman."</string>
     <string name="httpErrorBadUrl" msgid="3636929722728881972">"Tidak dapat membuka laman karena URL tidak valid."</string>
-    <string name="httpErrorFile" msgid="2170788515052558676">"Tidak dapat mengakses berkas."</string>
-    <string name="httpErrorFileNotFound" msgid="6203856612042655084">"Tidak dapat menemukan berkas yang diminta."</string>
+    <string name="httpErrorFile" msgid="2170788515052558676">"Tidak dapat mengakses file."</string>
+    <string name="httpErrorFileNotFound" msgid="6203856612042655084">"Tidak dapat menemukan file yang diminta."</string>
     <string name="httpErrorTooManyRequests" msgid="1235396927087188253">"Terlalu banyak permintaan yang diproses. Coba lagi nanti."</string>
     <string name="notification_title" msgid="8967710025036163822">"Galat saat masuk untuk <xliff:g id="ACCOUNT">%1$s</xliff:g>"</string>
     <string name="contentServiceSync" msgid="8353523060269335667">"Sinkron"</string>
     <string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"Sinkron"</string>
     <string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"Terlalu banyak <xliff:g id="CONTENT_TYPE">%s</xliff:g> penghapusan."</string>
-    <string name="low_memory" product="tablet" msgid="6494019234102154896">"Penyimpanan tablet penuh. Hapus beberapa berkas untuk mengosongkan ruang."</string>
-    <string name="low_memory" product="default" msgid="3475999286680000541">"Penyimpanan di ponsel penuh. Hapus sebagian berkas untuk mengosongkan ruang."</string>
+    <string name="low_memory" product="tablet" msgid="6494019234102154896">"Penyimpanan tablet penuh. Hapus beberapa file untuk mengosongkan ruang."</string>
+    <string name="low_memory" product="default" msgid="3475999286680000541">"Penyimpanan di ponsel penuh. Hapus sebagian file untuk mengosongkan ruang."</string>
     <string name="me" msgid="6545696007631404292">"Saya"</string>
     <string name="power_dialog" product="tablet" msgid="8545351420865202853">"Opsi tablet"</string>
     <string name="power_dialog" product="default" msgid="1319919075463988638">"Opsi telepon"</string>
@@ -219,7 +219,7 @@
     <string name="permdesc_setScreenCompatibility" msgid="692043618693917374">"Memungkinkan apl mengontrol mode kompatibilitas layar aplikasi lain. Aplikasi berbahaya dapat merusak perilaku aplikasi lain."</string>
     <string name="permlab_setDebugApp" msgid="3022107198686584052">"mengaktifkan debugging apl"</string>
     <string name="permdesc_setDebugApp" msgid="4474512416299013256">"Mengizinkan apl mengaktifkan debugging untuk apl lain. Apl berbahaya dapat menggunakan cara ini untuk menutup apl lain."</string>
-    <string name="permlab_changeConfiguration" msgid="8214475779521218295">"ubah setelan UI Anda"</string>
+    <string name="permlab_changeConfiguration" msgid="8214475779521218295">"ubah pengaturan UI Anda"</string>
     <string name="permdesc_changeConfiguration" msgid="4372223873154296076">"Mengizinkan apl mengubah konfigurasi saat ini, misalnya lokal atau ukuran fon keseluruhan."</string>
     <string name="permlab_enableCarMode" msgid="5684504058192921098">"aktifkan mode mobil"</string>
     <string name="permdesc_enableCarMode" msgid="4853187425751419467">"Mengizinkan apl mengaktifkan mode mobil."</string>
@@ -293,23 +293,23 @@
     <string name="permlab_clearAppUserData" msgid="274109191845842756">"menghapus data apl lainnya"</string>
     <string name="permdesc_clearAppUserData" msgid="4625323684125459488">"Mengizinkan apl menghapus data pengguna."</string>
     <string name="permlab_deleteCacheFiles" msgid="3128665571837408675">"menghapus tembolok apl lainnya"</string>
-    <string name="permdesc_deleteCacheFiles" msgid="3812998599006730196">"Mengizinkan apl menghapus berkas tembolok."</string>
+    <string name="permdesc_deleteCacheFiles" msgid="3812998599006730196">"Mengizinkan apl menghapus file tembolok."</string>
     <string name="permlab_getPackageSize" msgid="7472921768357981986">"mengukur ruang penyimpanan apl"</string>
     <string name="permdesc_getPackageSize" msgid="3921068154420738296">"Mengizinkan apl mengambil kode, data, dan ukuran temboloknya"</string>
     <string name="permlab_installPackages" msgid="2199128482820306924">"langsung memasang apl"</string>
     <string name="permdesc_installPackages" msgid="5628530972548071284">"Mengizinkan apl memasang paket Android yang baru atau diperbarui. Apl berbahaya dapat menggunakan ini untuk menambahkan apl baru dengan sembarang izin yang kuat."</string>
     <string name="permlab_clearAppCache" msgid="7487279391723526815">"menghapus semua data tembolok apl"</string>
-    <string name="permdesc_clearAppCache" product="tablet" msgid="3523396284474042284">"Mengizinkan apl mengosongkan penyimpanan tablet dengan menghapus berkas dalam direktori tembolok apl. Akses biasanya sangat terbatas dan hanya diberikan bagi proses sistem."</string>
-    <string name="permdesc_clearAppCache" product="default" msgid="5067988373366292186">"Mengizinkan apl mengosongkan penyimpanan ponsel dengan menghapus berkas dalam direktori tembolok apl. Akses biasanya sangat terbatas dan hanya diberikan bagi proses sistem."</string>
+    <string name="permdesc_clearAppCache" product="tablet" msgid="3523396284474042284">"Mengizinkan apl mengosongkan penyimpanan tablet dengan menghapus file dalam direktori tembolok apl. Akses biasanya sangat terbatas dan hanya diberikan bagi proses sistem."</string>
+    <string name="permdesc_clearAppCache" product="default" msgid="5067988373366292186">"Mengizinkan apl mengosongkan penyimpanan ponsel dengan menghapus file dalam direktori tembolok apl. Akses biasanya sangat terbatas dan hanya diberikan bagi proses sistem."</string>
     <string name="permlab_movePackage" msgid="3289890271645921411">"memindahkan sumber daya apl"</string>
     <string name="permdesc_movePackage" msgid="319562217778244524">"Mengizinkan apl memindahkan sumber daya apl dari media internal ke eksternal dan sebaliknya."</string>
     <string name="permlab_readLogs" msgid="6615778543198967614">"baca data log sensitif"</string>
-    <string name="permdesc_readLogs" product="tablet" msgid="82061313293455151">"Mengizinkan apl membaca dari berbagai berkas log sistem. Izin ini memungkinkan apl menemukan informasi umum tentang hal-hal yang Anda lakukan dengan tablet, kemungkinan termasuk informasi pribadi."</string>
-    <string name="permdesc_readLogs" product="default" msgid="2063438140241560443">"Mengizinkan apl membaca dari berbagai berkas log sistem. Izin ini memungkinkan apl menemukan informasi umum tentang hal-hal yang Anda lakukan di ponsel, kemungkinan termasuk informasi pribadi."</string>
+    <string name="permdesc_readLogs" product="tablet" msgid="82061313293455151">"Mengizinkan apl membaca dari berbagai file log sistem. Izin ini memungkinkan apl menemukan informasi umum tentang hal-hal yang Anda lakukan dengan tablet, kemungkinan termasuk informasi pribadi."</string>
+    <string name="permdesc_readLogs" product="default" msgid="2063438140241560443">"Mengizinkan apl membaca dari berbagai file log sistem. Izin ini memungkinkan apl menemukan informasi umum tentang hal-hal yang Anda lakukan di ponsel, kemungkinan termasuk informasi pribadi."</string>
     <string name="permlab_anyCodecForPlayback" msgid="715805555823881818">"menggunakan media pengawasandi apa pun untuk pemutaran"</string>
     <string name="permdesc_anyCodecForPlayback" msgid="8283912488433189010">"Mengizinkan apl menggunakan pengawasandi media apa pun yang terpasang guna mengawasandikan media untuk diputar."</string>
     <string name="permlab_diagnostic" msgid="8076743953908000342">"baca/tulis ke sumber daya yang dimiliki oleh diag"</string>
-    <string name="permdesc_diagnostic" msgid="6608295692002452283">"Mengizinkan apl membaca dan menulis ke sumber daya apa pun yang dimiliki oleh grup diag; misalnya, berkas dalam /dev. Izin ini berpotensi mempengaruhi kestabilan dan keamanan sistem. Sebaiknya ini HANYA digunakan untuk diagnostik khusus perangkat keras oleh pabrikan atau operator."</string>
+    <string name="permdesc_diagnostic" msgid="6608295692002452283">"Mengizinkan apl membaca dan menulis ke sumber daya apa pun yang dimiliki oleh grup diag; misalnya, file dalam /dev. Izin ini berpotensi mempengaruhi kestabilan dan keamanan sistem. Sebaiknya ini HANYA digunakan untuk diagnostik khusus perangkat keras oleh pabrikan atau operator."</string>
     <string name="permlab_changeComponentState" msgid="6335576775711095931">"mengaktifkan atau menonaktifkan komponen apl"</string>
     <string name="permdesc_changeComponentState" product="tablet" msgid="8887435740982237294">"Mengizinkan apl mengubah apakah komponen apl lain diaktifkan atau tidak. Apl berbahaya dapat menggunakan ini untuk menonaktifkan kemampuan tablet yang penting. Izin ini harus digunakan dengan hati-hati karena dapat menjadikan komponen apl tidak dapat digunakan, tidak konsisten, atau tidak stabil."</string>
     <string name="permdesc_changeComponentState" product="default" msgid="1827232484416505615">"Mengizinkan apl mengubah apakah komponen apl lain diaktifkan atau tidak. Apl berbahaya dapat menggunakan izin ini untuk menonaktifkan kemampuan ponsel yang penting. Izin ini harus digunakan dengan hati-hati, karena mungkin saja menjadikan komponen apl tidak dapat digunakan, tidak konsisten, atau tidak stabil."</string>
@@ -317,10 +317,10 @@
     <string name="permdesc_grantRevokePermissions" msgid="4088642654085850662">"Memungkinkan aplikasi memberikan atau mencabut izin khusus untuk aplikasi tersebut atau aplikasi lainnya. Aplikasi berbahaya dapat menggunakannya untuk mengakses fitur yang tidak Anda beri izin."</string>
     <string name="permlab_setPreferredApplications" msgid="8463181628695396391">"menyetel apl yang disukai"</string>
     <string name="permdesc_setPreferredApplications" msgid="4973986762241783712">"Mengizinkan apl memodifikasi apl pilihan Anda. Apl berbahaya dapat diam-diam mengubah apl yang berjalan, menipu apl yang ada untuk mengumpulkan data pribadi dari Anda."</string>
-    <string name="permlab_writeSettings" msgid="1365523497395143704">"ubah setelan sistem global"</string>
-    <string name="permdesc_writeSettings" msgid="7775723441558907181">"Mengizinkan apl memodifikasi data setelan sistem. Apl berbahaya dapat merusak konfigurasi sistem anda."</string>
-    <string name="permlab_writeSecureSettings" msgid="204676251876718288">"ubah setelan sistem aman"</string>
-    <string name="permdesc_writeSecureSettings" msgid="8159535613020137391">"Mengizinkan apl memodifikasi data setelan aman sistem. Tidak untuk digunakan oleh apl normal."</string>
+    <string name="permlab_writeSettings" msgid="1365523497395143704">"ubah pengaturan sistem global"</string>
+    <string name="permdesc_writeSettings" msgid="7775723441558907181">"Mengizinkan apl memodifikasi data pengaturan sistem. Apl berbahaya dapat merusak konfigurasi sistem anda."</string>
+    <string name="permlab_writeSecureSettings" msgid="204676251876718288">"ubah pengaturan sistem aman"</string>
+    <string name="permdesc_writeSecureSettings" msgid="8159535613020137391">"Mengizinkan apl memodifikasi data pengaturan aman sistem. Tidak untuk digunakan oleh apl normal."</string>
     <string name="permlab_writeGservices" msgid="2149426664226152185">"ubah peta layanan Google"</string>
     <string name="permdesc_writeGservices" msgid="1287309437638380229">"Mengizinkan apl memodifikasi peta layanan Google. Tidak untuk digunakan oleh apl normal."</string>
     <string name="permlab_receiveBootCompleted" msgid="7776779842866993377">"mulai secara otomatis pada saat boot"</string>
@@ -364,8 +364,8 @@
     <string name="permdesc_accessSurfaceFlinger" msgid="1041619516733293551">"Mengizinkan apl menggunakan fitur tingkat rendah SurfaceFlinger."</string>
     <string name="permlab_readFrameBuffer" msgid="6690504248178498136">"baca buffer frame"</string>
     <string name="permdesc_readFrameBuffer" msgid="4937405521809454680">"Mengizinkan apl membaca konten penyangga frame."</string>
-    <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"ubah setelan audio Anda"</string>
-    <string name="permdesc_modifyAudioSettings" msgid="7343951185408396919">"Mengizinkan apl memodifikasi setelan audio global, misalnya volume dan perutean."</string>
+    <string name="permlab_modifyAudioSettings" msgid="6095859937069146086">"ubah pengaturan audio Anda"</string>
+    <string name="permdesc_modifyAudioSettings" msgid="7343951185408396919">"Mengizinkan apl memodifikasi pengaturan audio global, misalnya volume dan perutean."</string>
     <string name="permlab_recordAudio" msgid="3876049771427466323">"rekam audio"</string>
     <string name="permdesc_recordAudio" msgid="2387462233976248635">"Mengizinkan apl mengakses jalur rekaman audio."</string>
     <string name="permlab_camera" msgid="3616391919559751192">"ambil gambar dan video"</string>
@@ -379,7 +379,7 @@
     <string name="permdesc_reboot" product="tablet" msgid="8172056180063700741">"Mengizinkan apl memaksa tablet melakukan reboot."</string>
     <string name="permdesc_reboot" product="default" msgid="5326008124289989969">"Mengizinkan apl memaksa ponsel melakukan reboot."</string>
     <string name="permlab_mount_unmount_filesystems" msgid="1761023272170956541">"pasang dan lepas filesystem"</string>
-    <string name="permdesc_mount_unmount_filesystems" msgid="1829290701658992347">"Mengizinkan apl memasang dan melepas sistem berkas untuk penyimpanan yang dapat dicopot."</string>
+    <string name="permdesc_mount_unmount_filesystems" msgid="1829290701658992347">"Mengizinkan apl memasang dan melepas sistem file untuk penyimpanan yang dapat dicopot."</string>
     <string name="permlab_mount_format_filesystems" msgid="5523285143576718981">"format penyimpanan eksternal"</string>
     <string name="permdesc_mount_format_filesystems" msgid="8784268246779198627">"Mengizinkan apl memformat penyimpanan yang dapat dicopot."</string>
     <string name="permlab_asec_access" msgid="3411338632002193846">"dapatkan informasi pada penyimpanan internal"</string>
@@ -434,8 +434,8 @@
     <string name="permdesc_setWallpaper" msgid="7373447920977624745">"Mengizinkan apl menyetel wallpaper sistem."</string>
     <string name="permlab_setWallpaperHints" msgid="3600721069353106851">"atur petunjuk ukuran wallpaper"</string>
     <string name="permdesc_setWallpaperHints" msgid="8235784384223730091">"Mengizinkan apl menyetel petunjuk ukuran wallpaper sistem."</string>
-    <string name="permlab_masterClear" msgid="2315750423139697397">"setel ulang sistem ke setelan bawaan pabrik"</string>
-    <string name="permdesc_masterClear" msgid="3665380492633910226">"Mengizinkan apl menyetel ulang sistem ke setelan pabrik sepenuhnya, menghapus semua data, konfigurasi, dan apl yang terpasang."</string>
+    <string name="permlab_masterClear" msgid="2315750423139697397">"setel ulang sistem ke pengaturan bawaan pabrik"</string>
+    <string name="permdesc_masterClear" msgid="3665380492633910226">"Mengizinkan apl menyetel ulang sistem ke pengaturan pabrik sepenuhnya, menghapus semua data, konfigurasi, dan apl yang terpasang."</string>
     <string name="permlab_setTime" msgid="2021614829591775646">"atur waktu"</string>
     <string name="permdesc_setTime" product="tablet" msgid="1896341438151152881">"Mengizinkan apl mengubah waktu pada jam tablet."</string>
     <string name="permdesc_setTime" product="default" msgid="1855702730738020">"Mengizinkan apl mengubah waktu pada jam ponsel."</string>
@@ -457,14 +457,14 @@
     <string name="permdesc_accessNetworkState" msgid="479772796952547198">"Mengizinkan apl melihat keadaan semua jaringan."</string>
     <string name="permlab_createNetworkSockets" msgid="9121633680349549585">"akses internet penuh"</string>
     <string name="permdesc_createNetworkSockets" msgid="5963922297444265950">"Mengizinkan apl membuat soket jaringan."</string>
-    <string name="permlab_writeApnSettings" msgid="505660159675751896">"mengubah/mencegat lalu lintas dan setelan jaringan"</string>
-    <string name="permdesc_writeApnSettings" msgid="5333798886412714193">"Mengizinkan apl mengubah setelan jaringan dan mencegat serta memeriksa semua lalu lintas jaringan, misalnya mengubah proxy dan port APN apa saja. Apl berbahaya dapat memantau, mengalihkan, atau mengubah paket jaringan tanpa sepengetahuan Anda."</string>
+    <string name="permlab_writeApnSettings" msgid="505660159675751896">"mengubah/mencegat lalu lintas dan pengaturan jaringan"</string>
+    <string name="permdesc_writeApnSettings" msgid="5333798886412714193">"Mengizinkan apl mengubah pengaturan jaringan dan mencegat serta memeriksa semua lalu lintas jaringan, misalnya mengubah proxy dan port APN apa saja. Apl berbahaya dapat memantau, mengalihkan, atau mengubah paket jaringan tanpa sepengetahuan Anda."</string>
     <string name="permlab_changeNetworkState" msgid="958884291454327309">"ubah konektivitas jaringan"</string>
     <string name="permdesc_changeNetworkState" msgid="6789123912476416214">"Mengizinkan apl mengubah keadaan konektivitas jaringan."</string>
     <string name="permlab_changeTetherState" msgid="5952584964373017960">"mengubah konektivitas yang tertambat"</string>
     <string name="permdesc_changeTetherState" msgid="1524441344412319780">"Mengizinkan apl mengubah status konektivitas jaringan yang tertambat."</string>
-    <string name="permlab_changeBackgroundDataSetting" msgid="1400666012671648741">"mengubah setelan penggunaan data latar belakang"</string>
-    <string name="permdesc_changeBackgroundDataSetting" msgid="5347729578468744379">"Mengizinkan apl mengubah setelan penggunaan data latar belakang."</string>
+    <string name="permlab_changeBackgroundDataSetting" msgid="1400666012671648741">"mengubah pengaturan penggunaan data latar belakang"</string>
+    <string name="permdesc_changeBackgroundDataSetting" msgid="5347729578468744379">"Mengizinkan apl mengubah pengaturan penggunaan data latar belakang."</string>
     <string name="permlab_accessWifiState" msgid="8100926650211034400">"lihat kondisi Wi-Fi"</string>
     <string name="permdesc_accessWifiState" msgid="7770452658226256831">"Mengizinkan apl melihat informasi tentang keadaan Wi-Fi."</string>
     <string name="permlab_changeWifiState" msgid="7280632711057112137">"ubah status Wi-Fi"</string>
@@ -485,10 +485,10 @@
     <string name="permdesc_nfc" msgid="7120611819401789907">"Mengizinkan apl berkomunikasi dengan tag, kartu, dan alat pembaca Komunikasi Nirkabel Jarak Dekat (NFC)."</string>
     <string name="permlab_disableKeyguard" msgid="4977406164311535092">"nonaktifkan kunci tombol"</string>
     <string name="permdesc_disableKeyguard" msgid="6231611286892232626">"Mengizinkan apl menonaktifkan kunci tombol dan segala keamanan sandi yang terkait. Contoh nyata dari hal ini adalah ponsel menonaktifkan kunci tombol saat menerima panggilan telepon masuk, kemudian mengaktifkan kembali kunci tombol ketika panggilan selesai."</string>
-    <string name="permlab_readSyncSettings" msgid="6201810008230503052">"baca setelan sinkron"</string>
-    <string name="permdesc_readSyncSettings" msgid="5464056785274229278">"Mengizinkan apl membaca setelan sinkronisasi, misalnya apakah sinkronisasi untuk apl Orang diaktifkan atau tidak."</string>
-    <string name="permlab_writeSyncSettings" msgid="6297138566442486462">"tuliskan setelan sinkronisasi"</string>
-    <string name="permdesc_writeSyncSettings" msgid="1466056564502117130">"Mengizinkan apl memodifikasi setelan sinkronisasi, seperti apakah sinkronisasi untuk apl Orang diaktifkan atau tidak."</string>
+    <string name="permlab_readSyncSettings" msgid="6201810008230503052">"baca pengaturan sinkron"</string>
+    <string name="permdesc_readSyncSettings" msgid="5464056785274229278">"Mengizinkan apl membaca pengaturan sinkronisasi, misalnya apakah sinkronisasi untuk apl Orang diaktifkan atau tidak."</string>
+    <string name="permlab_writeSyncSettings" msgid="6297138566442486462">"tuliskan pengaturan sinkronisasi"</string>
+    <string name="permdesc_writeSyncSettings" msgid="1466056564502117130">"Mengizinkan apl memodifikasi pengaturan sinkronisasi, seperti apakah sinkronisasi untuk apl Orang diaktifkan atau tidak."</string>
     <string name="permlab_readSyncStats" msgid="7396577451360202448">"statistika baca sinkron"</string>
     <string name="permdesc_readSyncStats" msgid="3801971839939951678">"Mengizinkan apl membaca statistik sinkronisasi; mis., riwayat sinkronisasi yang telah terjadi."</string>
     <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"baca umpan langganan"</string>
@@ -505,8 +505,8 @@
     <string name="permdesc_sdcardWrite" product="default" msgid="4337417790936632090">"Memungkinkan apl menulis ke kartu SD."</string>
     <string name="permlab_mediaStorageWrite" product="default" msgid="6859839199706879015">"ubah/hapus konten penyimpanan media internal"</string>
     <string name="permdesc_mediaStorageWrite" product="default" msgid="8189160597698529185">"Mengizinkan apl memodifikasi konten penyimpanan media internal."</string>
-    <string name="permlab_cache_filesystem" msgid="5656487264819669824">"akses sistem berkas tembolok."</string>
-    <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Mengizinkan apl membaca dan menulis pada sistem berkas tembolok."</string>
+    <string name="permlab_cache_filesystem" msgid="5656487264819669824">"akses sistem file tembolok."</string>
+    <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Mengizinkan apl membaca dan menulis pada sistem file tembolok."</string>
     <string name="permlab_use_sip" msgid="5986952362795870502">"lakukan//terima panggilan internet"</string>
     <string name="permdesc_use_sip" msgid="4717632000062674294">"Mengizinkan apl menggunakan layanan SIP untuk melakukan/menerima panggilan internet."</string>
     <string name="permlab_readNetworkUsageHistory" msgid="7862593283611493232">"baca riwayat penggunaan jaringan"</string>
@@ -671,7 +671,7 @@
     <string name="faceunlock_multiple_failures" msgid="754137583022792429">"Percobaan Face Unlock melebihi batas maksimum"</string>
     <string name="lockscreen_plugged_in" msgid="8057762828355572315">"Mengisi daya, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_charged" msgid="4938930459620989972">"Terisi."</string>
-    <string name="lockscreen_battery_short" msgid="3617549178603354656">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
+    <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"Hubungkan pengisi daya."</string>
     <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"Tidak ada kartu SIM."</string>
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Tidak ada kartu SIM dalam tablet."</string>
@@ -695,10 +695,10 @@
     <string name="lockscreen_too_many_failed_pin_attempts_dialog_message" msgid="6216672706545696955">"Anda telah <xliff:g id="NUMBER_0">%d</xliff:g> kali salah mengetik PIN. "\n\n"Coba lagi dalam <xliff:g id="NUMBER_1">%d</xliff:g> detik."</string>
     <string name="lockscreen_failed_attempts_almost_glogin" product="tablet" msgid="9191611984625460820">"Anda telah <xliff:g id="NUMBER_0">%d</xliff:g> kali salah menggambar pola pembuka kunci. Setelah <xliff:g id="NUMBER_1">%d</xliff:g> lagi upaya gagal, Anda akan diminta membuka kunci tablet menggunakan info masuk Google."\n\n"Coba lagi dalam <xliff:g id="NUMBER_2">%d</xliff:g> detik."</string>
     <string name="lockscreen_failed_attempts_almost_glogin" product="default" msgid="2590227559763762751">"Anda telah <xliff:g id="NUMBER_0">%d</xliff:g> kali salah menggambar pola pembuka kunci. Setelah <xliff:g id="NUMBER_1">%d</xliff:g> lagi upaya gagal, Anda akan diminta membuka kunci ponsel menggunakan info masuk Google."\n\n"Coba lagi dalam <xliff:g id="NUMBER_2">%d</xliff:g> detik."</string>
-    <string name="lockscreen_failed_attempts_almost_at_wipe" product="tablet" msgid="6128106399745755604">"Anda telah gagal mencoba membuka gembok tablet sebanyak <xliff:g id="NUMBER_0">%d</xliff:g> kali. Setelah <xliff:g id="NUMBER_1">%d</xliff:g> upaya gagal lagi, tablet akan disetel ulang ke setelan bawaan pabrik dan semua data pengguna hilang."</string>
-    <string name="lockscreen_failed_attempts_almost_at_wipe" product="default" msgid="8603565142156826565">"Anda telah gagal mencoba membuka gembok ponsel sebanyak <xliff:g id="NUMBER_0">%d</xliff:g> kali. Setelah <xliff:g id="NUMBER_1">%d</xliff:g> upaya gagal lagi, ponsel akan disetel ulang ke setelan bawaan pabrik dan semua data pengguna hilang."</string>
-    <string name="lockscreen_failed_attempts_now_wiping" product="tablet" msgid="280873516493934365">"Anda telah gagal mencoba membuka gembok tablet sebanyak <xliff:g id="NUMBER">%d</xliff:g> kali. Kini tablet akan disetel ulang ke setelan bawaan pabrik."</string>
-    <string name="lockscreen_failed_attempts_now_wiping" product="default" msgid="3025504721764922246">"Anda telah gagal mencoba membuka gembok ponsel sebanyak <xliff:g id="NUMBER">%d</xliff:g> kali. Kini ponsel akan disetel ulang ke setelan bawaan pabrik."</string>
+    <string name="lockscreen_failed_attempts_almost_at_wipe" product="tablet" msgid="6128106399745755604">"Anda telah gagal mencoba membuka gembok tablet sebanyak <xliff:g id="NUMBER_0">%d</xliff:g> kali. Setelah <xliff:g id="NUMBER_1">%d</xliff:g> upaya gagal lagi, tablet akan disetel ulang ke pengaturan bawaan pabrik dan semua data pengguna hilang."</string>
+    <string name="lockscreen_failed_attempts_almost_at_wipe" product="default" msgid="8603565142156826565">"Anda telah gagal mencoba membuka gembok ponsel sebanyak <xliff:g id="NUMBER_0">%d</xliff:g> kali. Setelah <xliff:g id="NUMBER_1">%d</xliff:g> upaya gagal lagi, ponsel akan disetel ulang ke pengaturan bawaan pabrik dan semua data pengguna hilang."</string>
+    <string name="lockscreen_failed_attempts_now_wiping" product="tablet" msgid="280873516493934365">"Anda telah gagal mencoba membuka gembok tablet sebanyak <xliff:g id="NUMBER">%d</xliff:g> kali. Kini tablet akan disetel ulang ke pengaturan bawaan pabrik."</string>
+    <string name="lockscreen_failed_attempts_now_wiping" product="default" msgid="3025504721764922246">"Anda telah gagal mencoba membuka gembok ponsel sebanyak <xliff:g id="NUMBER">%d</xliff:g> kali. Kini ponsel akan disetel ulang ke pengaturan bawaan pabrik."</string>
     <string name="lockscreen_too_many_failed_attempts_countdown" msgid="6251480343394389665">"Coba lagi dalam <xliff:g id="NUMBER">%d</xliff:g> detik."</string>
     <string name="lockscreen_forgot_pattern_button_text" msgid="2626999449610695930">"Lupa pola?"</string>
     <string name="lockscreen_glogin_forgot_pattern" msgid="2588521501166032747">"Pembuka kunci akun"</string>
@@ -720,8 +720,8 @@
     <string name="password_keyboard_label_symbol_key" msgid="992280756256536042">"?123"</string>
     <string name="password_keyboard_label_alpha_key" msgid="8001096175167485649">"ABC"</string>
     <string name="password_keyboard_label_alt_key" msgid="1284820942620288678">"ALT"</string>
-    <string name="hour_ampm" msgid="4329881288269772723">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string>
-    <string name="hour_cap_ampm" msgid="1829009197680861107">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string>
+    <string name="hour_ampm" msgid="4584338083529355982">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string>
+    <string name="hour_cap_ampm" msgid="2083465992940444366">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string>
     <string name="factorytest_failed" msgid="5410270329114212041">"Uji pabrik gagal"</string>
     <string name="factorytest_not_system" msgid="4435201656767276723">"Tindakan FACTORY_TEST hanya didukung untuk paket yang terpasang pada /system/app."</string>
     <string name="factorytest_no_action" msgid="872991874799998561">"Tidak ada paket yang memberikan tindakan FACTORY_TEST."</string>
@@ -733,7 +733,7 @@
     <string name="double_tap_toast" msgid="4595046515400268881">"Kiat: Ketuk dua kali untuk memperbesar dan memperkecil."</string>
     <string name="autofill_this_form" msgid="4616758841157816676">"Isiotomatis"</string>
     <string name="setup_autofill" msgid="7103495070180590814">"Siapkan Pengisian Otomatis"</string>
-    <string name="autofill_address_name_separator" msgid="2504700673286691795">" "</string>
+    <string name="autofill_address_name_separator" msgid="6350145154779706772">"  "</string>
     <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string>
     <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string>
     <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
@@ -749,17 +749,17 @@
     <string name="autofill_parish" msgid="8202206105468820057">"Kampung"</string>
     <string name="autofill_area" msgid="3547409050889952423">"Area"</string>
     <string name="autofill_emirate" msgid="2893880978835698818">"Emirat"</string>
-    <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"baca riwayat dan bookmark Peramban"</string>
-    <string name="permdesc_readHistoryBookmarks" msgid="4577476392604595921">"Mengizinkan apl membaca semua URL yang telah dikunjungi Peramban dan semua bookmark Peramban."</string>
-    <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"tuliskan riwayat dan bookmark Peramban"</string>
-    <string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="1757103804824209530">"Mengizinkan apl memodifikasi riwayat Peramban atau bookmark yang tersimpan di tablet. Apl berbahaya dapat menggunakan izin ini untuk menghapus atau memodifikasi data Peramban Anda."</string>
-    <string name="permdesc_writeHistoryBookmarks" product="default" msgid="6693764355720719197">"Mengizinkan apl memodifikasi riwayat Peramban atau bookmark yang tersimpan di ponsel Anda. Apl berbahaya dapat menggunakannya untuk menghapus atau memodifikasi data Peramban Anda."</string>
+    <string name="permlab_readHistoryBookmarks" msgid="1284843728203412135">"baca riwayat dan bookmark Browser"</string>
+    <string name="permdesc_readHistoryBookmarks" msgid="4577476392604595921">"Mengizinkan apl membaca semua URL yang telah dikunjungi Browser dan semua bookmark Browser."</string>
+    <string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"tuliskan riwayat dan bookmark Browser"</string>
+    <string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="1757103804824209530">"Mengizinkan apl memodifikasi riwayat Browser atau bookmark yang tersimpan di tablet. Apl berbahaya dapat menggunakan izin ini untuk menghapus atau memodifikasi data Browser Anda."</string>
+    <string name="permdesc_writeHistoryBookmarks" product="default" msgid="6693764355720719197">"Mengizinkan apl memodifikasi riwayat Browser atau bookmark yang tersimpan di ponsel Anda. Apl berbahaya dapat menggunakannya untuk menghapus atau memodifikasi data Browser Anda."</string>
     <string name="permlab_setAlarm" msgid="5924401328803615165">"setel alarm di jam alarm"</string>
     <string name="permdesc_setAlarm" msgid="316392039157473848">"Mengizinkan apl menyetel alarm di apl jam alarm yang terpasang. Beberapa apl jam alarm mungkin tidak menerapkan fitur ini."</string>
     <string name="permlab_addVoicemail" msgid="5525660026090959044">"tambahkan kotak pesan"</string>
     <string name="permdesc_addVoicemail" msgid="6604508651428252437">"Mengizinkan apl menambahkan pesan ke kotak masuk untuk pesan suara Anda."</string>
-    <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"memodifikasi izin geolokasi Peramban"</string>
-    <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"Mengizinkan apl memodifikasi izin geolokasi Peramban. Apl berbahaya dapat menggunakan izin ini untuk memungkinkan pengiriman informasi lokasi ke sembarang situs web."</string>
+    <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"memodifikasi izin geolokasi Browser"</string>
+    <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"Mengizinkan apl memodifikasi izin geolokasi Browser. Apl berbahaya dapat menggunakan izin ini untuk memungkinkan pengiriman informasi lokasi ke sembarang situs web."</string>
     <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"verifikasi paket"</string>
     <string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"Mengizinkan apl memverifikasi bahwa suatu paket dapat dipasang."</string>
     <string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"mengikat ke pemverifikasi paket"</string>
@@ -768,7 +768,9 @@
     <string name="permdesc_serialPort" msgid="2991639985224598193">"Memungkinkan pemegangnya mengakses port serial menggunakan API SerialManager."</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"mengakses penyedia konten dari luar"</string>
     <string name="permdesc_accessContentProvidersExternally" msgid="4544346486697853685">"Memungkinkan pemegang mengakses penyedia konten dari cangkang. Tidak pernah diperlukan untuk apl normal."</string>
-    <string name="save_password_message" msgid="767344687139195790">"Apakah Anda ingin peramban menyimpan sandi ini?"</string>
+    <string name="permlab_updateLock" msgid="3527558366616680889">"menghindari pembaruan perangkat otomatis"</string>
+    <string name="permdesc_updateLock" msgid="1655625832166778492">"Memungkinkan pemegang untuk menawarkan informasi ke sistem mengenai kapan waktu yang baik bagi pemulaian ulang non-interaktif untuk meningkatkan versi perangkat."</string>
+    <string name="save_password_message" msgid="767344687139195790">"Apakah Anda ingin browser menyimpan sandi ini?"</string>
     <string name="save_password_notnow" msgid="6389675316706699758">"Tidak sekarang"</string>
     <string name="save_password_remember" msgid="6491879678996749466">"Ingat"</string>
     <string name="save_password_never" msgid="8274330296785855105">"Jangan"</string>
@@ -908,7 +910,7 @@
     <string name="capital_off" msgid="6815870386972805832">"MATI"</string>
     <string name="whichApplication" msgid="4533185947064773386">"Tindakan lengkap menggunakan"</string>
     <string name="alwaysUse" msgid="4583018368000610438">"Gunakan secara bawaan untuk tindakan ini."</string>
-    <string name="clearDefaultHintMsg" msgid="3252584689512077257">"Menghapus bawaan di Setelan sistem &gt; Apl &gt; Terunduh."</string>
+    <string name="clearDefaultHintMsg" msgid="3252584689512077257">"Menghapus bawaan di Pengaturan sistem &gt; Apl &gt; Terunduh."</string>
     <string name="chooseActivity" msgid="7486876147751803333">"Pilih tindakan"</string>
     <string name="chooseUsbActivity" msgid="6894748416073583509">"Pilih apl untuk perangkat USB"</string>
     <string name="noApplications" msgid="2991814273936504689">"Tidak ada apl yang dapat melakukan tindakan ini."</string>
@@ -929,7 +931,7 @@
     <string name="launch_warning_original" msgid="188102023021668683">"<xliff:g id="APP_NAME">%1$s</xliff:g> telah diluncurkan aslinya."</string>
     <string name="screen_compat_mode_scale" msgid="3202955667675944499">"Skala"</string>
     <string name="screen_compat_mode_show" msgid="4013878876486655892">"Selalu tampilkan"</string>
-    <string name="screen_compat_mode_hint" msgid="1064524084543304459">"Aktifkan kembali dialog ini di Setelan sistem &gt; Apl &gt; Terunduh."</string>
+    <string name="screen_compat_mode_hint" msgid="1064524084543304459">"Aktifkan kembali dialog ini di Pengaturan sistem &gt; Apl &gt; Terunduh."</string>
     <string name="smv_application" msgid="3307209192155442829">"Apl <xliff:g id="APPLICATION">%1$s</xliff:g> (proses <xliff:g id="PROCESS">%2$s</xliff:g>) telah melanggar kebijakan StrictMode yang diberlakukannya sendiri."</string>
     <string name="smv_process" msgid="5120397012047462446">"Proses <xliff:g id="PROCESS">%1$s</xliff:g> telah melanggar kebijakan StrictMode yang diberlakukan secara otomatis."</string>
     <string name="android_upgrading_title" msgid="1584192285441405746">"Android sedang meningkatkan versi..."</string>
@@ -981,7 +983,7 @@
     <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"Memulai Wi-Fi Langsung. Opsi ini akan mematikan hotspot/klien Wi-Fi."</string>
     <string name="wifi_p2p_failed_message" msgid="3763669677935623084">"Tidak dapat memulai Wi-Fi Langsung."</string>
     <string name="wifi_p2p_enabled_notification_title" msgid="2068321881673734886">"Wi-Fi Langsung aktif"</string>
-    <string name="wifi_p2p_enabled_notification_message" msgid="1638949953993894335">"Sentuh untuk setelan"</string>
+    <string name="wifi_p2p_enabled_notification_message" msgid="1638949953993894335">"Sentuh untuk pengaturan"</string>
     <string name="accept" msgid="1645267259272829559">"Terima"</string>
     <string name="decline" msgid="2112225451706137894">"Tolak"</string>
     <string name="wifi_p2p_invitation_sent_title" msgid="1318975185112070734">"Undangan terkirim"</string>
@@ -1012,13 +1014,13 @@
     <string name="perms_show_all" msgid="2671791163933091180"><b>"Tampilkan semua"</b></string>
     <string name="usb_storage_activity_title" msgid="4465055157209648641">"Penyimpanan massal USB"</string>
     <string name="usb_storage_title" msgid="5901459041398751495">"USB terhubung"</string>
-    <string name="usb_storage_message" product="nosdcard" msgid="3308538094316477839">"Anda telah tersambung ke komputer melalui USB. Sentuh tombol di bawah jika Anda ingin menyalin berkas antara komputer dan penyimpanan USB Android Anda."</string>
-    <string name="usb_storage_message" product="default" msgid="805351000446037811">"Anda telah tersambung ke komputer melalui USB. Sentuh tombol di bawah jika Anda ingin menyalin berkas antara komputer dan kartu SD Android Anda."</string>
+    <string name="usb_storage_message" product="nosdcard" msgid="3308538094316477839">"Anda telah tersambung ke komputer melalui USB. Sentuh tombol di bawah jika Anda ingin menyalin file antara komputer dan penyimpanan USB Android Anda."</string>
+    <string name="usb_storage_message" product="default" msgid="805351000446037811">"Anda telah tersambung ke komputer melalui USB. Sentuh tombol di bawah jika Anda ingin menyalin file antara komputer dan kartu SD Android Anda."</string>
     <string name="usb_storage_button_mount" msgid="1052259930369508235">"Hidupkan penyimpanan USB"</string>
     <string name="usb_storage_error_message" product="nosdcard" msgid="3017045217365540658">"Terjadi masalah saat menggunakan penyimpanan USB Anda untuk penyimpanan massal USB."</string>
     <string name="usb_storage_error_message" product="default" msgid="2876018512716970313">"Terjadi masalah saat menggunakan kartu SD Anda untuk penyimpanan massal USB."</string>
     <string name="usb_storage_notification_title" msgid="8175892554757216525">"USB terhubung"</string>
-    <string name="usb_storage_notification_message" msgid="939822783828183763">"Sentuh untuk menyalin berkas ke/dari komputer Anda."</string>
+    <string name="usb_storage_notification_message" msgid="939822783828183763">"Sentuh untuk menyalin file ke/dari komputer Anda."</string>
     <string name="usb_storage_stop_notification_title" msgid="2336058396663516017">"Matikan penyimpanan USB"</string>
     <string name="usb_storage_stop_notification_message" msgid="1656852098555623822">"Sentuh untuk mematikan penyimpanan USB."</string>
     <string name="usb_storage_stop_title" msgid="660129851708775853">"Penyimpanan USB sedang digunakan"</string>
@@ -1037,7 +1039,7 @@
     <string name="usb_notification_message" msgid="2290859399983720271">"Sentuh untuk opsi USB lainnya."</string>
     <string name="extmedia_format_title" product="nosdcard" msgid="9020092196061007262">"Format penyimpanan USB?"</string>
     <string name="extmedia_format_title" product="default" msgid="3648415921526526069">"Format kartu SD?"</string>
-    <string name="extmedia_format_message" product="nosdcard" msgid="3934016853425761078">"Semua berkas yang tersimpan dalam penyimpanan USB Anda akan dihapus. Tindakan ini tidak dapat diurungkan!"</string>
+    <string name="extmedia_format_message" product="nosdcard" msgid="3934016853425761078">"Semua file yang tersimpan dalam penyimpanan USB Anda akan dihapus. Tindakan ini tidak dapat diurungkan!"</string>
     <string name="extmedia_format_message" product="default" msgid="14131895027543830">"Semua data di kartu Anda akan hilang."</string>
     <string name="extmedia_format_button_format" msgid="4131064560127478695">"Format"</string>
     <string name="adb_active_notification_title" msgid="6729044778949189918">"Debugging USB terhubung"</string>
@@ -1053,7 +1055,7 @@
     <string name="ext_media_nofs_notification_title" product="nosdcard" msgid="7788040745686229307">"Penyimpanan USB kosong"</string>
     <string name="ext_media_nofs_notification_title" product="default" msgid="780477838241212997">"Kartu SD kosong"</string>
     <string name="ext_media_nofs_notification_message" product="nosdcard" msgid="7840121067427269500">"Penyimpanan USB kosong atau sistem berkasnya tidak didukung."</string>
-    <string name="ext_media_nofs_notification_message" product="default" msgid="8641065641786923604">"Kartu SD kosong atau memiliki sistem berkas yang tidak didukung."</string>
+    <string name="ext_media_nofs_notification_message" product="default" msgid="8641065641786923604">"Kartu SD kosong atau memiliki sistem file yang tidak didukung."</string>
     <string name="ext_media_unmountable_notification_title" product="nosdcard" msgid="2090046769532713563">"Penyimpanan USB rusak"</string>
     <string name="ext_media_unmountable_notification_title" product="default" msgid="6410723906019100189">"Kartu SD rusak"</string>
     <string name="ext_media_unmountable_notification_message" product="nosdcard" msgid="1795917578395333280">"Penyimpanan USB rusak. Coba diformat ulang."</string>
@@ -1102,8 +1104,8 @@
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN diaktifkan oleh <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Sentuh untuk mengelola jaringan."</string>
     <string name="vpn_text_long" msgid="6407351006249174473">"Tersambung ke <xliff:g id="SESSION">%s</xliff:g>. Sentuh untuk mengelola jaringan."</string>
-    <string name="upload_file" msgid="2897957172366730416">"Pilih berkas"</string>
-    <string name="no_file_chosen" msgid="6363648562170759465">"Tidak ada berkas yang dipilih"</string>
+    <string name="upload_file" msgid="2897957172366730416">"Pilih file"</string>
+    <string name="no_file_chosen" msgid="6363648562170759465">"Tidak ada file yang dipilih"</string>
     <string name="reset" msgid="2448168080964209908">"Setel ulang"</string>
     <string name="submit" msgid="1602335572089911941">"Kirim"</string>
     <string name="car_mode_disable_notification_title" msgid="3164768212003864316">"Mode mobil diaktifkan"</string>
@@ -1241,6 +1243,6 @@
     <string name="status_bar_device_locked" msgid="3092703448690669768">"Perangkat tergembok."</string>
     <string name="list_delimeter" msgid="3975117572185494152">", "</string>
     <string name="sending" msgid="3245653681008218030">"Mengirim..."</string>
-    <string name="launchBrowserDefault" msgid="2057951947297614725">"Luncurkan Peramban?"</string>
+    <string name="launchBrowserDefault" msgid="2057951947297614725">"Luncurkan Browser?"</string>
     <string name="SetupCallDefault" msgid="5834948469253758575">"Terima panggilan?"</string>
 </resources>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index 21855eb6..96c6709 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -26,7 +26,7 @@
     <string name="gigabyteShort" msgid="3259882455212193214">"GB"</string>
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
-    <string name="fileSizeSuffix" msgid="7670819340156489359">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
     <string name="untitled" msgid="4638956954852782576">"&lt;Senza nome&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -671,7 +671,7 @@
     <string name="faceunlock_multiple_failures" msgid="754137583022792429">"Numero massimo di tentativi di Sblocco col sorriso superato"</string>
     <string name="lockscreen_plugged_in" msgid="8057762828355572315">"In carica (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string>
     <string name="lockscreen_charged" msgid="4938930459620989972">"Carico."</string>
-    <string name="lockscreen_battery_short" msgid="3617549178603354656">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
+    <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"Collegare il caricabatterie."</string>
     <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"Nessuna SIM presente."</string>
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Nessuna scheda SIM presente nel tablet."</string>
@@ -720,8 +720,8 @@
     <string name="password_keyboard_label_symbol_key" msgid="992280756256536042">"?123"</string>
     <string name="password_keyboard_label_alpha_key" msgid="8001096175167485649">"ABC"</string>
     <string name="password_keyboard_label_alt_key" msgid="1284820942620288678">"ALT"</string>
-    <string name="hour_ampm" msgid="4329881288269772723">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string>
-    <string name="hour_cap_ampm" msgid="1829009197680861107">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string>
+    <string name="hour_ampm" msgid="4584338083529355982">"<xliff:g id="HOUR">%-l</xliff:g> <xliff:g id="AMPM">%P</xliff:g>"</string>
+    <string name="hour_cap_ampm" msgid="2083465992940444366">"<xliff:g id="HOUR">%-l</xliff:g> <xliff:g id="AMPM">%p</xliff:g>"</string>
     <string name="factorytest_failed" msgid="5410270329114212041">"Test di fabbrica non riuscito"</string>
     <string name="factorytest_not_system" msgid="4435201656767276723">"L\'azione FACTORY_TEST è supportata soltanto per i pacchetti installati in /system/app."</string>
     <string name="factorytest_no_action" msgid="872991874799998561">"Nessun pacchetto trovato che fornisca l\'azione FACTORY_TEST."</string>
@@ -733,7 +733,7 @@
     <string name="double_tap_toast" msgid="4595046515400268881">"Suggerimento. Tocca due volte per aumentare e diminuire lo zoom."</string>
     <string name="autofill_this_form" msgid="4616758841157816676">"Compilazione autom."</string>
     <string name="setup_autofill" msgid="7103495070180590814">"Compilaz. autom."</string>
-    <string name="autofill_address_name_separator" msgid="2504700673286691795">" "</string>
+    <string name="autofill_address_name_separator" msgid="6350145154779706772">" "</string>
     <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string>
     <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string>
     <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
@@ -768,6 +768,8 @@
     <string name="permdesc_serialPort" msgid="2991639985224598193">"Permette al proprietario di accedere alle porte seriali utilizzando l\'API SerialManager."</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"accesso a fornitori di contenuti esterni"</string>
     <string name="permdesc_accessContentProvidersExternally" msgid="4544346486697853685">"Consente al proprietario di accedere ai fornitori di contenuti dalla shell. Non dovrebbe mai essere necessario per le normali applicazioni."</string>
+    <string name="permlab_updateLock" msgid="3527558366616680889">"scoraggiamento aggiorn. automatici disp."</string>
+    <string name="permdesc_updateLock" msgid="1655625832166778492">"Consente al titolare di dare al sistema informazioni relative agli orari opportuni per il riavvio non interattivo al fine di eseguire l\'upgrade del dispositivo."</string>
     <string name="save_password_message" msgid="767344687139195790">"Memorizzare la password nel browser?"</string>
     <string name="save_password_notnow" msgid="6389675316706699758">"Non ora"</string>
     <string name="save_password_remember" msgid="6491879678996749466">"Memorizza"</string>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index b009ea1..485e0b0 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -26,7 +26,7 @@
     <string name="gigabyteShort" msgid="3259882455212193214">"GB‏‏"</string>
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
-    <string name="fileSizeSuffix" msgid="7670819340156489359">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
     <string name="untitled" msgid="4638956954852782576">"&gt;ללא כותרת&lt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"..."</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -671,7 +671,7 @@
     <string name="faceunlock_multiple_failures" msgid="754137583022792429">"חרגת ממספר הניסיונות המרבי של זיהוי פרצוף"</string>
     <string name="lockscreen_plugged_in" msgid="8057762828355572315">"טוען (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string>
     <string name="lockscreen_charged" msgid="4938930459620989972">"נטען."</string>
-    <string name="lockscreen_battery_short" msgid="3617549178603354656">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
+    <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"חבר את המטען."</string>
     <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"אין כרטיס SIM."</string>
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"אין כרטיס SIM בטבלט."</string>
@@ -720,8 +720,8 @@
     <string name="password_keyboard_label_symbol_key" msgid="992280756256536042">"?123"</string>
     <string name="password_keyboard_label_alpha_key" msgid="8001096175167485649">"אבג"</string>
     <string name="password_keyboard_label_alt_key" msgid="1284820942620288678">"ALT"</string>
-    <string name="hour_ampm" msgid="4329881288269772723">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string>
-    <string name="hour_cap_ampm" msgid="1829009197680861107">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string>
+    <string name="hour_ampm" msgid="4584338083529355982">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string>
+    <string name="hour_cap_ampm" msgid="2083465992940444366">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string>
     <string name="factorytest_failed" msgid="5410270329114212041">"בדיקת היצרן נכשלה"</string>
     <string name="factorytest_not_system" msgid="4435201656767276723">"הפעולה FACTORY_TEST נתמכת רק עבור חבילות שהותקנו ב-‎/system/app."</string>
     <string name="factorytest_no_action" msgid="872991874799998561">"לא נמצאה חבילה המספקת את הפעולה FACTORY_TEST."</string>
@@ -733,7 +733,7 @@
     <string name="double_tap_toast" msgid="4595046515400268881">"טיפ: הקש פעמיים כדי להגדיל ולהקטין."</string>
     <string name="autofill_this_form" msgid="4616758841157816676">"מילוי אוטומטי"</string>
     <string name="setup_autofill" msgid="7103495070180590814">"הגדר מילוי אוטומטי"</string>
-    <string name="autofill_address_name_separator" msgid="2504700673286691795">" "</string>
+    <string name="autofill_address_name_separator" msgid="6350145154779706772">" "</string>
     <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string>
     <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string>
     <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
@@ -768,6 +768,8 @@
     <string name="permdesc_serialPort" msgid="2991639985224598193">"מאפשר לבעלים לגשת ליציאות טוריות באמצעות ממשק ה- API של SerialManager."</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"גישה לספקי תוכן באופן חיצוני"</string>
     <string name="permdesc_accessContentProvidersExternally" msgid="4544346486697853685">"מאפשר לבעלים לגשת לספקי תוכן מהמעטפת. לעולם לא אמור להיות צורך עבור יישומים רגילים."</string>
+    <string name="permlab_updateLock" msgid="3527558366616680889">"דחה עדכוני מכשיר אוטומטיים"</string>
+    <string name="permdesc_updateLock" msgid="1655625832166778492">"מאפשר לבעלים להציע מידע למערכת לגבי זמן מתאים לאתחול מחדש לא אינטראקטיבי לשם שדרוג המכשיר."</string>
     <string name="save_password_message" msgid="767344687139195790">"האם ברצונך שהדפדפן יזכור סיסמה זו?"</string>
     <string name="save_password_notnow" msgid="6389675316706699758">"לא כעת"</string>
     <string name="save_password_remember" msgid="6491879678996749466">"זכור"</string>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index 9898734..bc9840d 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -26,7 +26,7 @@
     <string name="gigabyteShort" msgid="3259882455212193214">"GB"</string>
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
-    <string name="fileSizeSuffix" msgid="7670819340156489359">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
     <string name="untitled" msgid="4638956954852782576">"&lt;新規&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"..."</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -671,7 +671,7 @@
     <string name="faceunlock_multiple_failures" msgid="754137583022792429">"フェイスアンロックの最大試行回数を超えました"</string>
     <string name="lockscreen_plugged_in" msgid="8057762828355572315">"充電しています: <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_charged" msgid="4938930459620989972">"充電完了"</string>
-    <string name="lockscreen_battery_short" msgid="3617549178603354656">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
+    <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"充電してください"</string>
     <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"SIMカードが挿入されていません"</string>
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"タブレット内にSIMカードがありません。"</string>
@@ -720,8 +720,8 @@
     <string name="password_keyboard_label_symbol_key" msgid="992280756256536042">"?123"</string>
     <string name="password_keyboard_label_alpha_key" msgid="8001096175167485649">"ABC"</string>
     <string name="password_keyboard_label_alt_key" msgid="1284820942620288678">"ALT"</string>
-    <string name="hour_ampm" msgid="4329881288269772723">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string>
-    <string name="hour_cap_ampm" msgid="1829009197680861107">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string>
+    <string name="hour_ampm" msgid="4584338083529355982">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string>
+    <string name="hour_cap_ampm" msgid="2083465992940444366">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string>
     <string name="factorytest_failed" msgid="5410270329114212041">"出荷時試験が失敗"</string>
     <string name="factorytest_not_system" msgid="4435201656767276723">"FACTORY_TEST操作は、/system/appにインストールされたパッケージのみが対象です。"</string>
     <string name="factorytest_no_action" msgid="872991874799998561">"FACTORY_TEST操作を行うパッケージは見つかりませんでした。"</string>
@@ -733,7 +733,7 @@
     <string name="double_tap_toast" msgid="4595046515400268881">"ヒント: ダブルタップで拡大/縮小できます。"</string>
     <string name="autofill_this_form" msgid="4616758841157816676">"自動入力"</string>
     <string name="setup_autofill" msgid="7103495070180590814">"自動入力を設定"</string>
-    <string name="autofill_address_name_separator" msgid="2504700673286691795">" "</string>
+    <string name="autofill_address_name_separator" msgid="6350145154779706772">" "</string>
     <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$3$2$1"</string>
     <string name="autofill_address_summary_separator" msgid="7483307893170324129">"、 "</string>
     <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
@@ -768,6 +768,8 @@
     <string name="permdesc_serialPort" msgid="2991639985224598193">"SerialManager APIを使用してシリアルポートにアクセスすることを所有者に許可します。"</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"コンテンツプロバイダへの外部アクセス"</string>
     <string name="permdesc_accessContentProvidersExternally" msgid="4544346486697853685">"シェルからコンテンツプロバイダにアクセスすることを権利所有者に許可します。通常のアプリでは必要ありません。"</string>
+    <string name="permlab_updateLock" msgid="3527558366616680889">"端末の自動更新の抑制"</string>
+    <string name="permdesc_updateLock" msgid="1655625832166778492">"非対話型の再起動により端末をアップグレードするのに適したタイミングについて、システムに情報を提供することを権利所有者に許可します。"</string>
     <string name="save_password_message" msgid="767344687139195790">"このパスワードをブラウザで保存しますか?"</string>
     <string name="save_password_notnow" msgid="6389675316706699758">"今は保存しない"</string>
     <string name="save_password_remember" msgid="6491879678996749466">"保存"</string>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index 5eea0ba..c9801a3 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -26,7 +26,7 @@
     <string name="gigabyteShort" msgid="3259882455212193214">"GB"</string>
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
-    <string name="fileSizeSuffix" msgid="7670819340156489359">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
     <string name="untitled" msgid="4638956954852782576">"&lt;제목 없음&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -671,7 +671,7 @@
     <string name="faceunlock_multiple_failures" msgid="754137583022792429">"얼굴 인식 잠금해제 최대 시도 횟수를 초과했습니다."</string>
     <string name="lockscreen_plugged_in" msgid="8057762828355572315">"충전 중(<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string>
     <string name="lockscreen_charged" msgid="4938930459620989972">"충전되었습니다."</string>
-    <string name="lockscreen_battery_short" msgid="3617549178603354656">"<xliff:g id="NUMBER">%d</xliff:g> <xliff:g id="PERCENT">%%</xliff:g>"</string>
+    <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"충전기를 연결하세요."</string>
     <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"SIM 카드가 없습니다."</string>
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"태블릿에 SIM 카드가 없습니다."</string>
@@ -720,8 +720,8 @@
     <string name="password_keyboard_label_symbol_key" msgid="992280756256536042">"?123"</string>
     <string name="password_keyboard_label_alpha_key" msgid="8001096175167485649">"ABC"</string>
     <string name="password_keyboard_label_alt_key" msgid="1284820942620288678">"ALT"</string>
-    <string name="hour_ampm" msgid="4329881288269772723">"<xliff:g id="AMPM">%P</xliff:g> <xliff:g id="HOUR">%-l</xliff:g>:00"</string>
-    <string name="hour_cap_ampm" msgid="1829009197680861107">"<xliff:g id="AMPM">%p</xliff:g> <xliff:g id="HOUR">%-l</xliff:g>:00"</string>
+    <string name="hour_ampm" msgid="4584338083529355982">"<xliff:g id="AMPM">%P</xliff:g> <xliff:g id="HOUR">%-l</xliff:g>시"</string>
+    <string name="hour_cap_ampm" msgid="2083465992940444366">"<xliff:g id="AMPM">%p</xliff:g> <xliff:g id="HOUR">%-l</xliff:g>시"</string>
     <string name="factorytest_failed" msgid="5410270329114212041">"출고 테스트 불합격"</string>
     <string name="factorytest_not_system" msgid="4435201656767276723">"FACTORY_TEST 작업은 /system/app 디렉토리에 설치된 패키지에 대해서만 지원됩니다."</string>
     <string name="factorytest_no_action" msgid="872991874799998561">"FACTORY_TEST 작업을 제공하는 패키지가 없습니다."</string>
@@ -733,7 +733,7 @@
     <string name="double_tap_toast" msgid="4595046515400268881">"도움말: 확대/축소하려면 두 번 탭합니다."</string>
     <string name="autofill_this_form" msgid="4616758841157816676">"자동완성"</string>
     <string name="setup_autofill" msgid="7103495070180590814">"자동완성 설정..."</string>
-    <string name="autofill_address_name_separator" msgid="2504700673286691795">" "</string>
+    <string name="autofill_address_name_separator" msgid="6350145154779706772">" "</string>
     <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$3$2$1"</string>
     <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string>
     <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
@@ -768,6 +768,8 @@
     <string name="permdesc_serialPort" msgid="2991639985224598193">"SerialManager API를 사용하여 권한을 가진 프로그램이 직렬 포트에 액세스할 수 있도록 합니다."</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"외부에서 콘텐츠 제공자에 액세스"</string>
     <string name="permdesc_accessContentProvidersExternally" msgid="4544346486697853685">"권한을 가진 프로그램이 셸에서 콘텐츠 제공자에 액세스하도록 허용합니다. 일반 앱에서는 필요하지 않습니다."</string>
+    <string name="permlab_updateLock" msgid="3527558366616680889">"지금은 자동 기기 업데이트를 권장하지 않음"</string>
+    <string name="permdesc_updateLock" msgid="1655625832166778492">"기기를 자동으로 다시 부팅하여 업그레이드해도 괜찮은 시간에 대한 정보를 사용자가 시스템에 제공할 수 있도록 허용합니다."</string>
     <string name="save_password_message" msgid="767344687139195790">"브라우저에 이 비밀번호를 저장하시겠습니까?"</string>
     <string name="save_password_notnow" msgid="6389675316706699758">"나중에"</string>
     <string name="save_password_remember" msgid="6491879678996749466">"저장"</string>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index 7ea172f..4424ad5 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -26,7 +26,7 @@
     <string name="gigabyteShort" msgid="3259882455212193214">"GB"</string>
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
-    <string name="fileSizeSuffix" msgid="7670819340156489359">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
     <string name="untitled" msgid="4638956954852782576">"&lt;Be pavadinimo&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -671,7 +671,7 @@
     <string name="faceunlock_multiple_failures" msgid="754137583022792429">"Viršijote maksimalų atrakinimo pagal veidą bandymų skaičių"</string>
     <string name="lockscreen_plugged_in" msgid="8057762828355572315">"Įkraunama, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_charged" msgid="4938930459620989972">"Įkrauta."</string>
-    <string name="lockscreen_battery_short" msgid="3617549178603354656">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
+    <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g> <xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"Prijunkite kroviklį."</string>
     <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"Nėra SIM kortelės."</string>
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Planšetiniame kompiuteryje nėra SIM kortelės."</string>
@@ -720,8 +720,8 @@
     <string name="password_keyboard_label_symbol_key" msgid="992280756256536042">"?123"</string>
     <string name="password_keyboard_label_alpha_key" msgid="8001096175167485649">"ABC"</string>
     <string name="password_keyboard_label_alt_key" msgid="1284820942620288678">"ALT"</string>
-    <string name="hour_ampm" msgid="4329881288269772723">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string>
-    <string name="hour_cap_ampm" msgid="1829009197680861107">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string>
+    <string name="hour_ampm" msgid="4584338083529355982">"<xliff:g id="HOUR">%-l</xliff:g> <xliff:g id="AMPM">%P</xliff:g>"</string>
+    <string name="hour_cap_ampm" msgid="2083465992940444366">"<xliff:g id="HOUR">%-l</xliff:g> <xliff:g id="AMPM">%p</xliff:g>"</string>
     <string name="factorytest_failed" msgid="5410270329114212041">"Gamyklos bandymas nepavyko"</string>
     <string name="factorytest_not_system" msgid="4435201656767276723">"Veiksmas FACTORY_TEST palaikomas tik paketuose, įdiegtuose /system/app."</string>
     <string name="factorytest_no_action" msgid="872991874799998561">"Nerasta paketo, kuris teiktų FACTORY_TEST veiksmą."</string>
@@ -733,7 +733,7 @@
     <string name="double_tap_toast" msgid="4595046515400268881">"Patarimas: palieskite dukart, kad padidintumėte ar sumažintumėte mastelį."</string>
     <string name="autofill_this_form" msgid="4616758841157816676">"Automatinis pildymas"</string>
     <string name="setup_autofill" msgid="7103495070180590814">"Nust. aut. pild."</string>
-    <string name="autofill_address_name_separator" msgid="2504700673286691795">" "</string>
+    <string name="autofill_address_name_separator" msgid="6350145154779706772">" "</string>
     <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string>
     <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string>
     <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
@@ -768,6 +768,8 @@
     <string name="permdesc_serialPort" msgid="2991639985224598193">"Leidžiama savininkui pasiekti nuosekliuosius prievadus naudojant „SerialManager“ API."</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"pasiekti turinio teikėjus iš išorės"</string>
     <string name="permdesc_accessContentProvidersExternally" msgid="4544346486697853685">"Leidžiama savininkui pasiekti turinio teikėjus naudojant apvalkalą. To niekada neturėtų prireikti naudojant įprastas programas."</string>
+    <string name="permlab_updateLock" msgid="3527558366616680889">"Atsisakyti autom. įrenginio atnaujinimų"</string>
+    <string name="permdesc_updateLock" msgid="1655625832166778492">"Leidžia savininkui pateikti pasiūlymą sistemai dėl tinkamo laiko iš naujo neinteraktyviai įkelti programą, kad būtų naujovinamas įrenginys."</string>
     <string name="save_password_message" msgid="767344687139195790">"Ar norite, kad naršyklė atsimintų šį slaptažodį?"</string>
     <string name="save_password_notnow" msgid="6389675316706699758">"Ne dabar"</string>
     <string name="save_password_remember" msgid="6491879678996749466">"Atsiminti"</string>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index 1581341..89baaaa 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -26,7 +26,7 @@
     <string name="gigabyteShort" msgid="3259882455212193214">"GB"</string>
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
-    <string name="fileSizeSuffix" msgid="7670819340156489359">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
     <string name="untitled" msgid="4638956954852782576">"&lt;Bez nosaukuma&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -671,7 +671,7 @@
     <string name="faceunlock_multiple_failures" msgid="754137583022792429">"Ir pārsniegts maksimālais Autorizācijas pēc sejas mēģinājumu skaits."</string>
     <string name="lockscreen_plugged_in" msgid="8057762828355572315">"Notiek uzlāde (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string>
     <string name="lockscreen_charged" msgid="4938930459620989972">"Uzlādēts."</string>
-    <string name="lockscreen_battery_short" msgid="3617549178603354656">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
+    <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"Pievienojiet uzlādes ierīci."</string>
     <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"Nav SIM kartes."</string>
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Planšetdatorā nav SIM kartes."</string>
@@ -720,8 +720,8 @@
     <string name="password_keyboard_label_symbol_key" msgid="992280756256536042">"?123"</string>
     <string name="password_keyboard_label_alpha_key" msgid="8001096175167485649">"ABC"</string>
     <string name="password_keyboard_label_alt_key" msgid="1284820942620288678">"ALT"</string>
-    <string name="hour_ampm" msgid="4329881288269772723">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string>
-    <string name="hour_cap_ampm" msgid="1829009197680861107">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string>
+    <string name="hour_ampm" msgid="4584338083529355982">"<xliff:g id="HOUR">%-l</xliff:g> (<xliff:g id="AMPM">%P</xliff:g>)"</string>
+    <string name="hour_cap_ampm" msgid="2083465992940444366">"<xliff:g id="HOUR">%-l</xliff:g> (<xliff:g id="AMPM">%p</xliff:g>)"</string>
     <string name="factorytest_failed" msgid="5410270329114212041">"Rūpnīcas pārbaude neizdevās"</string>
     <string name="factorytest_not_system" msgid="4435201656767276723">"Darbība FACTORY_TEST tiek atbalstīta tikai pakotnēm, kas ir instalētas šeit: /system/app."</string>
     <string name="factorytest_no_action" msgid="872991874799998561">"Netika atrasts neviena pakotne, kas nodrošina darbību FACTORY_TEST."</string>
@@ -733,7 +733,7 @@
     <string name="double_tap_toast" msgid="4595046515400268881">"Padoms. Divreiz pieskarieties, lai tuvinātu un tālinātu."</string>
     <string name="autofill_this_form" msgid="4616758841157816676">"Automātiskā aizpilde"</string>
     <string name="setup_autofill" msgid="7103495070180590814">"Iest. aut. aizp."</string>
-    <string name="autofill_address_name_separator" msgid="2504700673286691795">" "</string>
+    <string name="autofill_address_name_separator" msgid="6350145154779706772">" "</string>
     <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string>
     <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string>
     <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
@@ -768,6 +768,8 @@
     <string name="permdesc_serialPort" msgid="2991639985224598193">"Ļauj īpašniekam piekļūt seriālajiem portiem, izmantojot SerialManager API."</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"ārēji piekļūt satura nodrošinātājiem"</string>
     <string name="permdesc_accessContentProvidersExternally" msgid="4544346486697853685">"Ļauj īpašniekam no čaulas piekļūt satura nodrošinātājiem. Nekad nav nepieciešama parastām lietotnēm."</string>
+    <string name="permlab_updateLock" msgid="3527558366616680889">"neatļaut automāt. ierīces atjauninājumus"</string>
+    <string name="permdesc_updateLock" msgid="1655625832166778492">"Ļauj īpašniekam piedāvāt sistēmai vēlamo laiku, kad veikt neinteraktīvu atsāknēšanu, lai jauninātu ierīci."</string>
     <string name="save_password_message" msgid="767344687139195790">"Vai vēlaties, lai pārlūkprogrammā tiktu saglabāta šī parole?"</string>
     <string name="save_password_notnow" msgid="6389675316706699758">"Ne tagad"</string>
     <string name="save_password_remember" msgid="6491879678996749466">"Atcerēties"</string>
diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml
index d3c4885..5bb95af 100644
--- a/core/res/res/values-ms/strings.xml
+++ b/core/res/res/values-ms/strings.xml
@@ -26,7 +26,7 @@
     <string name="gigabyteShort" msgid="3259882455212193214">"GB"</string>
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
-    <string name="fileSizeSuffix" msgid="7670819340156489359">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
     <string name="untitled" msgid="4638956954852782576">"&lt;Tidak bertajuk&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"..."</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -313,10 +313,8 @@
     <string name="permlab_changeComponentState" msgid="6335576775711095931">"dayakan atau lumpuhkan komponen apl"</string>
     <string name="permdesc_changeComponentState" product="tablet" msgid="8887435740982237294">"Membenarkan apl untuk menukar sama ada komponen apl lain didayakan atau tidak. Apl hasad boleh menggunakannya untuk melumpuhkan keupayaan telefon yang penting. Berhati-hati semasa menggunakan kebenaran ini, kerana hal ini boleh menjadikan komponen apl berada dalam keadaan tidak boleh digunakan, tidak konsisten, atau tidak stabil."</string>
     <string name="permdesc_changeComponentState" product="default" msgid="1827232484416505615">"Membenarkan apl untuk menukar sama ada komponen apl lain didayakan atau tidak. Apl hasad boleh menggunakannya untuk melumpuhkan keupayaan telefon yang penting. Berhati-hati semasa menggunakan kebenaran ini, kerana hal ini boleh menjadikan komponen apl berada dalam keadaan tidak boleh digunakan, tidak konsisten, atau tidak stabil."</string>
-    <!-- no translation found for permlab_grantRevokePermissions (4627315351093508795) -->
-    <skip />
-    <!-- no translation found for permdesc_grantRevokePermissions (4088642654085850662) -->
-    <skip />
+    <string name="permlab_grantRevokePermissions" msgid="4627315351093508795">"berikan atau batalkan kebenaran"</string>
+    <string name="permdesc_grantRevokePermissions" msgid="4088642654085850662">"Membenarkan aplikasi memberikan atau membatalkan kebenaran khusus untuk aplikasi itu sendiri atau aplikasi lain. Aplikasi berniat jahat boleh menggunakan perkara ini untuk mengakses ciri yang belum anda berikan padanya."</string>
     <string name="permlab_setPreferredApplications" msgid="8463181628695396391">"tetapkan keutamaan apl"</string>
     <string name="permdesc_setPreferredApplications" msgid="4973986762241783712">"Membenarkan apl untuk mengubah suai apl pilihan anda. Apl hasad secara diam-diam boleh menukar apl yang dijalankan, menipu apl anda yang sedia ada untuk mengumpul data peribadi daripada anda."</string>
     <string name="permlab_writeSettings" msgid="1365523497395143704">"mengubah suai tetapan sistem global"</string>
@@ -673,7 +671,7 @@
     <string name="faceunlock_multiple_failures" msgid="754137583022792429">"Telah melepasi had cubaan Buka Kunci Wajah"</string>
     <string name="lockscreen_plugged_in" msgid="8057762828355572315">"Mengecas, (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string>
     <string name="lockscreen_charged" msgid="4938930459620989972">"Sudah dicas."</string>
-    <string name="lockscreen_battery_short" msgid="3617549178603354656">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
+    <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"Sambungkan pengecas anda."</string>
     <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"Tiada kad SIM."</string>
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Tiada kad SIM dalam tablet."</string>
@@ -722,8 +720,8 @@
     <string name="password_keyboard_label_symbol_key" msgid="992280756256536042">"?123"</string>
     <string name="password_keyboard_label_alpha_key" msgid="8001096175167485649">"ABC"</string>
     <string name="password_keyboard_label_alt_key" msgid="1284820942620288678">"ALT"</string>
-    <string name="hour_ampm" msgid="4329881288269772723">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string>
-    <string name="hour_cap_ampm" msgid="1829009197680861107">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string>
+    <string name="hour_ampm" msgid="4584338083529355982">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string>
+    <string name="hour_cap_ampm" msgid="2083465992940444366">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string>
     <string name="factorytest_failed" msgid="5410270329114212041">"Ujian kilang gagal"</string>
     <string name="factorytest_not_system" msgid="4435201656767276723">"Tindakan FACTORY_TEST hanya disokong untuk pakej yang dipasangkan dalam /system/app."</string>
     <string name="factorytest_no_action" msgid="872991874799998561">"Tiada pakej yang menyediakan tindakan FACTORY_TEST ditemui."</string>
@@ -735,7 +733,7 @@
     <string name="double_tap_toast" msgid="4595046515400268881">"Petua: Ketik dua kali untuk mengezum masuk dan keluar."</string>
     <string name="autofill_this_form" msgid="4616758841157816676">"Auto isi"</string>
     <string name="setup_autofill" msgid="7103495070180590814">"Sediakan Autoisi"</string>
-    <string name="autofill_address_name_separator" msgid="2504700673286691795">" "</string>
+    <string name="autofill_address_name_separator" msgid="6350145154779706772">" "</string>
     <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string>
     <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string>
     <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
@@ -770,6 +768,8 @@
     <string name="permdesc_serialPort" msgid="2991639985224598193">"Membenarkan pemegang mengakses port bersiri menggunakan API SerialManager."</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"akses pembekal kandungan secara luaran"</string>
     <string name="permdesc_accessContentProvidersExternally" msgid="4544346486697853685">"Membolehkan pemegang mengakses pembekal kandungan dari luar. Tidak akan sekali-kali diperlukan untuk apl biasa."</string>
+    <string name="permlab_updateLock" msgid="3527558366616680889">"tidak menggalakkan kemas kini peranti automatik"</string>
+    <string name="permdesc_updateLock" msgid="1655625832166778492">"Membenarkan pemegang untuk menawarkan maklumat kepada sistem tentang bila akan menjadi masa yang baik untuk but semula bukan interaktif untuk menaik taraf peranti."</string>
     <string name="save_password_message" msgid="767344687139195790">"Adakah anda mahu penyemak imbas mengingati kata laluan ini?"</string>
     <string name="save_password_notnow" msgid="6389675316706699758">"Bukan sekarang"</string>
     <string name="save_password_remember" msgid="6491879678996749466">"Ingat"</string>
@@ -1008,8 +1008,7 @@
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Tetapkan tarikh"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Tetapkan"</string>
     <string name="default_permission_group" msgid="2690160991405646128">"Lalai"</string>
-    <!-- no translation found for perms_new_perm_prefix (8257740710754301407) -->
-    <skip />
+    <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ffffa3a3">"BAHARU: "</font></string>
     <string name="no_permissions" msgid="7283357728219338112">"Tiada kebenaran diperlukan"</string>
     <string name="perms_hide" msgid="7283915391320676226"><b>"Sembunyikan"</b></string>
     <string name="perms_show_all" msgid="2671791163933091180"><b>"Tunjukkan semua"</b></string>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index ee58558..6a9f846 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -26,7 +26,7 @@
     <string name="gigabyteShort" msgid="3259882455212193214">"GB"</string>
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
-    <string name="fileSizeSuffix" msgid="7670819340156489359">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
     <string name="untitled" msgid="4638956954852782576">"&lt;Uten navn&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -314,7 +314,7 @@
     <string name="permdesc_changeComponentState" product="tablet" msgid="8887435740982237294">"Lar appen endre hvorvidt en komponent i en annen app er aktivert eller ikke. Ondsinnede apper kan bruke dette til å deaktivere viktige nettbrettfunksjoner. Denne tillatelsen må brukes med forsiktighet, ettersom det er mulig å få appkomponenter inn i en ubrukelig, inkonsistent eller ustabil tilstand."</string>
     <string name="permdesc_changeComponentState" product="default" msgid="1827232484416505615">"Lar appen endre hvorvidt en komponent i en annen app er aktivert eller ikke. Ondsinnede apper kan bruke dette til å deaktivere viktige telefonfunksjoner. Denne tillatelsen må brukes med forsiktighet, ettersom det er mulig å få appkomponenter inn i en ubrukelig, inkonsistent eller ustabil tilstand."</string>
     <string name="permlab_grantRevokePermissions" msgid="4627315351093508795">"gi eller trekke tilbake tillatelser"</string>
-    <string name="permdesc_grantRevokePermissions" msgid="4088642654085850662">"Lar et program gi eller trekke tilbake spesielle tillatelser for eget bruk eller for andre programmer. Skadelige programmer kan bruke dette for å få tilgang til funksjoner de ikke skal ha tilgang til."</string>
+    <string name="permdesc_grantRevokePermissions" msgid="4088642654085850662">"Lar programmer gi eller trekke tilbake spesielle tillatelser for eget bruk eller for andre programmer. Skadelige programmer kan bruke dette for å få tilgang til funksjoner de ikke skal ha tilgang til."</string>
     <string name="permlab_setPreferredApplications" msgid="8463181628695396391">"angi foretrukne apper"</string>
     <string name="permdesc_setPreferredApplications" msgid="4973986762241783712">"Lar appen endre de foretrukne appene dine. Ondsinnede apper kan ubemerket endre apper som kjøres, og forfalske eksisterende apper til å samle private data fra deg."</string>
     <string name="permlab_writeSettings" msgid="1365523497395143704">"endre globale systeminnstillinger"</string>
@@ -671,7 +671,7 @@
     <string name="faceunlock_multiple_failures" msgid="754137583022792429">"Du har overskredet grensen for opplåsingsforsøk med Ansiktslås"</string>
     <string name="lockscreen_plugged_in" msgid="8057762828355572315">"Lader, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_charged" msgid="4938930459620989972">"Fullt ladet"</string>
-    <string name="lockscreen_battery_short" msgid="3617549178603354656">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
+    <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"Koble til en batterilader."</string>
     <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"Mangler SIM-kort."</string>
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Nettbrettet mangler SIM-kort."</string>
@@ -720,8 +720,8 @@
     <string name="password_keyboard_label_symbol_key" msgid="992280756256536042">"?123"</string>
     <string name="password_keyboard_label_alpha_key" msgid="8001096175167485649">"ABC"</string>
     <string name="password_keyboard_label_alt_key" msgid="1284820942620288678">"ALT"</string>
-    <string name="hour_ampm" msgid="4329881288269772723">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string>
-    <string name="hour_cap_ampm" msgid="1829009197680861107">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string>
+    <string name="hour_ampm" msgid="4584338083529355982">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string>
+    <string name="hour_cap_ampm" msgid="2083465992940444366">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string>
     <string name="factorytest_failed" msgid="5410270329114212041">"Fabrikktesten feilet"</string>
     <string name="factorytest_not_system" msgid="4435201656767276723">"The FACTORY_TEST action is only supported for packages installed in /system/app."</string>
     <string name="factorytest_no_action" msgid="872991874799998561">"No package was found that provides the FACTORY_TEST action."</string>
@@ -733,7 +733,7 @@
     <string name="double_tap_toast" msgid="4595046515400268881">"Tips: Dobbelttrykk for å zoome inn og ut."</string>
     <string name="autofill_this_form" msgid="4616758841157816676">"Autofyll"</string>
     <string name="setup_autofill" msgid="7103495070180590814">"Konfig. autofyll"</string>
-    <string name="autofill_address_name_separator" msgid="2504700673286691795">" "</string>
+    <string name="autofill_address_name_separator" msgid="6350145154779706772">" "</string>
     <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string>
     <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string>
     <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
@@ -768,6 +768,8 @@
     <string name="permdesc_serialPort" msgid="2991639985224598193">"Gir innehaveren tilgang til serielle porter ved hjelp av SerialManager API."</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"gå til innholdsleverandører eksternt"</string>
     <string name="permdesc_accessContentProvidersExternally" msgid="4544346486697853685">"Lar innehaveren gå til innholdsleverandører fra kommandovinduet. Skal aldri være nødvendig for vanlige apper."</string>
+    <string name="permlab_updateLock" msgid="3527558366616680889">"unngå automatiske enhetsoppdateringer"</string>
+    <string name="permdesc_updateLock" msgid="1655625832166778492">"Lar innehaveren informere systemet om gunstige tidspunkter for ikke-interaktiv omstart for oppgradering av enheten."</string>
     <string name="save_password_message" msgid="767344687139195790">"Ønsker du at nettleseren skal huske dette passordet?"</string>
     <string name="save_password_notnow" msgid="6389675316706699758">"Ikke nå"</string>
     <string name="save_password_remember" msgid="6491879678996749466">"Husk"</string>
@@ -1006,7 +1008,7 @@
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Angi dato"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Lagre"</string>
     <string name="default_permission_group" msgid="2690160991405646128">"Standard"</string>
-    <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ffffa3a3">"NY: "</font></string>
+    <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ffffa3a3">"NYTT: "</font></string>
     <string name="no_permissions" msgid="7283357728219338112">"Trenger ingen rettigheter"</string>
     <string name="perms_hide" msgid="7283915391320676226"><b>"Skjul"</b></string>
     <string name="perms_show_all" msgid="2671791163933091180"><b>"Vis alle"</b></string>
@@ -1077,7 +1079,7 @@
     <string name="permdesc_copyProtectedData" msgid="4390697124288317831">"Lar appen påkalle standard meldingsbeholdertjeneste for kopiering av innhold. Ikke beregnet på vanlige apper."</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="4070433208160063538">"Trykk to ganger for zoomkontroll"</string>
     <string name="gadget_host_error_inflating" msgid="4882004314906466162">"Kunne ikke legge til modulen."</string>
-    <string name="ime_action_go" msgid="8320845651737369027">"Gå"</string>
+    <string name="ime_action_go" msgid="8320845651737369027">"Utfør"</string>
     <string name="ime_action_search" msgid="658110271822807811">"Søk"</string>
     <string name="ime_action_send" msgid="2316166556349314424">"Send"</string>
     <string name="ime_action_next" msgid="3138843904009813834">"Neste"</string>
@@ -1086,7 +1088,7 @@
     <string name="ime_action_default" msgid="2840921885558045721">"Utfør"</string>
     <string name="dial_number_using" msgid="5789176425167573586">"Ring nummeret"\n"<xliff:g id="NUMBER">%s</xliff:g>"</string>
     <string name="create_contact_using" msgid="4947405226788104538">"Lag kontakt"\n"med nummeret <xliff:g id="NUMBER">%s</xliff:g>"</string>
-    <string name="grant_credentials_permission_message_header" msgid="2106103817937859662">"Én eller flere av de følgende appene ber om tillatelse til å få tilgang til kontoen din fra nå av."</string>
+    <string name="grant_credentials_permission_message_header" msgid="2106103817937859662">"Følgende app(er) ber om tilgang til kontoen din fra nå av."</string>
     <string name="grant_credentials_permission_message_footer" msgid="3125211343379376561">"Vil du tillate dette?"</string>
     <string name="grant_permissions_header_text" msgid="6874497408201826708">"Tilgangsforespørsel"</string>
     <string name="allow" msgid="7225948811296386551">"Tillat"</string>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 584a7d1..6876c63 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -26,7 +26,7 @@
     <string name="gigabyteShort" msgid="3259882455212193214">"GB"</string>
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
-    <string name="fileSizeSuffix" msgid="7670819340156489359">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
     <string name="untitled" msgid="4638956954852782576">"&lt;Zonder titel&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -314,7 +314,7 @@
     <string name="permdesc_changeComponentState" product="tablet" msgid="8887435740982237294">"Hiermee kan de app wijzigen of een component van een andere app wel of niet is ingeschakeld. Schadelijke apps kunnen dit gebruiken om belangrijke tabletfuncties uit te schakelen. U moet voorzichtig omgaan met deze rechten, aangezien het mogelijk is dat onderdelen van apps onbruikbaar, inconsistent of instabiel worden."</string>
     <string name="permdesc_changeComponentState" product="default" msgid="1827232484416505615">"Hiermee kan de app wijzigen of een component van een andere app wel of niet is ingeschakeld. Schadelijke apps kunnen dit gebruiken om belangrijke telefoonfuncties uit te schakelen. U moet voorzichtig omgaan met deze rechten, aangezien het mogelijk is dat onderdelen van apps onbruikbaar, inconsistent of instabiel worden."</string>
     <string name="permlab_grantRevokePermissions" msgid="4627315351093508795">"rechten verlenen of intrekken"</string>
-    <string name="permdesc_grantRevokePermissions" msgid="4088642654085850662">"Toestaan dat een app specifieke rechten aan zichzelf of andere apps verleent of intrekt. Schadelijke apps kunnen dit gebruiken om toegang te krijgen tot functies waartoe u de apps geen toegang heeft gegeven."</string>
+    <string name="permdesc_grantRevokePermissions" msgid="4088642654085850662">"Toestaan dat een app specifieke rechten aan zichzelf of andere apps verleent of deze intrekt. Schadelijke apps kunnen dit gebruiken om toegang te krijgen tot functies waartoe u de apps geen toegang heeft gegeven."</string>
     <string name="permlab_setPreferredApplications" msgid="8463181628695396391">"voorkeursapps instellen"</string>
     <string name="permdesc_setPreferredApplications" msgid="4973986762241783712">"Hiermee kan de app uw voorkeursapps aanpassen. Schadelijke apps kunnen de apps die worden uitgevoerd zonder uw medeweten wijzigen om uw bestaande apps te imiteren en privégegevens van u te verzamelen."</string>
     <string name="permlab_writeSettings" msgid="1365523497395143704">"algemene systeeminstellingen wijzigen"</string>
@@ -671,7 +671,7 @@
     <string name="faceunlock_multiple_failures" msgid="754137583022792429">"Maximaal aantal pogingen voor Face Unlock overschreden"</string>
     <string name="lockscreen_plugged_in" msgid="8057762828355572315">"Opladen, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_charged" msgid="4938930459620989972">"Opgeladen."</string>
-    <string name="lockscreen_battery_short" msgid="3617549178603354656">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
+    <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"Sluit de oplader aan."</string>
     <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"Geen SIM-kaart."</string>
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Geen SIM-kaart in tablet."</string>
@@ -720,8 +720,8 @@
     <string name="password_keyboard_label_symbol_key" msgid="992280756256536042">"?123"</string>
     <string name="password_keyboard_label_alpha_key" msgid="8001096175167485649">"ABC"</string>
     <string name="password_keyboard_label_alt_key" msgid="1284820942620288678">"Alt"</string>
-    <string name="hour_ampm" msgid="4329881288269772723">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string>
-    <string name="hour_cap_ampm" msgid="1829009197680861107">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string>
+    <string name="hour_ampm" msgid="4584338083529355982">"<xliff:g id="HOUR">%-l</xliff:g> <xliff:g id="AMPM">%P</xliff:g>"</string>
+    <string name="hour_cap_ampm" msgid="2083465992940444366">"<xliff:g id="HOUR">%-l</xliff:g> <xliff:g id="AMPM">%p</xliff:g>"</string>
     <string name="factorytest_failed" msgid="5410270329114212041">"Fabriekstest mislukt"</string>
     <string name="factorytest_not_system" msgid="4435201656767276723">"De actie FACTORY_TEST wordt alleen ondersteund voor pakketten die zijn geïnstalleerd in /system/app."</string>
     <string name="factorytest_no_action" msgid="872991874799998561">"Er is geen pakket gevonden dat de actie FACTORY_TEST levert."</string>
@@ -733,7 +733,7 @@
     <string name="double_tap_toast" msgid="4595046515400268881">"Tip: dubbeltik om in en uit te zoomen."</string>
     <string name="autofill_this_form" msgid="4616758841157816676">"Autom. aanvullen"</string>
     <string name="setup_autofill" msgid="7103495070180590814">"Autom. aanvullen instellen"</string>
-    <string name="autofill_address_name_separator" msgid="2504700673286691795">" "</string>
+    <string name="autofill_address_name_separator" msgid="6350145154779706772">" "</string>
     <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string>
     <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string>
     <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
@@ -768,6 +768,8 @@
     <string name="permdesc_serialPort" msgid="2991639985224598193">"De houder toestaan toegang tot seriële poorten te krijgen met de SerialManager API."</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"externe toegang tot inhoudsproviders"</string>
     <string name="permdesc_accessContentProvidersExternally" msgid="4544346486697853685">"Hiermee kan de houder toegang krijgen tot inhoudsproviders via de shell. Nooit vereist voor normale apps."</string>
+    <string name="permlab_updateLock" msgid="3527558366616680889">"automatische apparaatupdates afwijzen"</string>
+    <string name="permdesc_updateLock" msgid="1655625832166778492">"Toestaan dat de houder informatie aan het systeem levert over welk moment een goed tijdstip is voor een niet-interactieve reboot om het apparaat bij te werken."</string>
     <string name="save_password_message" msgid="767344687139195790">"Wilt u dat de browser dit wachtwoord onthoudt?"</string>
     <string name="save_password_notnow" msgid="6389675316706699758">"Niet nu"</string>
     <string name="save_password_remember" msgid="6491879678996749466">"Onthouden"</string>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index 4d0e0fa..286c32c 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -26,7 +26,7 @@
     <string name="gigabyteShort" msgid="3259882455212193214">"GB"</string>
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
-    <string name="fileSizeSuffix" msgid="7670819340156489359">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
     <string name="untitled" msgid="4638956954852782576">"&lt;Bez nazwy&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -314,7 +314,7 @@
     <string name="permdesc_changeComponentState" product="tablet" msgid="8887435740982237294">"Pozwala aplikacji na włączenie lub wyłączenie składnika innej aplikacji. Złośliwe aplikacje mogą wykorzystać to uprawnienie do wyłączenia ważnych funkcji tabletu. W przypadku tego uprawnienia należy zachować ostrożność, ponieważ istnieje możliwość wprowadzenia składników aplikacji w stan nieużywalności, niespójności lub niestabilności."</string>
     <string name="permdesc_changeComponentState" product="default" msgid="1827232484416505615">"Pozwala aplikacji na włączenie lub wyłączenie składnika innej aplikacji. Złośliwe aplikacje mogą wykorzystać to uprawnienie do wyłączenia ważnych funkcji telefonu. W przypadku tego uprawnienia należy zachować ostrożność, ponieważ istnieje możliwość wprowadzenia składników aplikacji w stan nieużywalności, niespójności lub niestabilności."</string>
     <string name="permlab_grantRevokePermissions" msgid="4627315351093508795">"przyznaj lub cofnij uprawnienia"</string>
-    <string name="permdesc_grantRevokePermissions" msgid="4088642654085850662">"Pozwala aplikacji na przyznanie lub cofnięcie określonych uprawnień do niej lub do innych aplikacji. Złośliwe aplikacje mogą to wykorzystać, by uzyskać dostęp do nieprzyznanych im funkcji."</string>
+    <string name="permdesc_grantRevokePermissions" msgid="4088642654085850662">"Pozwala aplikacji na przyznanie lub cofnięcie określonych uprawnień do niej lub do innych aplikacji. Złośliwe aplikacje mogą to wykorzystać, by uzyskać dostęp do nieuprawnionych funkcji."</string>
     <string name="permlab_setPreferredApplications" msgid="8463181628695396391">"ustawianie preferowanych aplikacji"</string>
     <string name="permdesc_setPreferredApplications" msgid="4973986762241783712">"Pozwala aplikacji na zmianę Twoich preferowanych aplikacji. Złośliwe aplikacje mogą dyskretnie zmienić uruchamiane aplikacje, podszywając się pod dotychczasowe aplikacje w celu zebrania od Ciebie prywatnych danych."</string>
     <string name="permlab_writeSettings" msgid="1365523497395143704">"modyfikowanie ogólnych ustawień systemu"</string>
@@ -499,7 +499,7 @@
     <string name="permdesc_readDictionary" msgid="8977815988329283705">"Pozwala aplikacji na odczytywanie wszelkich prywatnych słów, nazw i wyrażeń zapisanych w słowniku użytkownika."</string>
     <string name="permlab_writeDictionary" msgid="2296383164914812772">"zapisywanie w słowniku zdefiniowanym przez użytkownika"</string>
     <string name="permdesc_writeDictionary" msgid="8185385716255065291">"Pozwala aplikacji na zapisywanie nowych słów do słownika użytkownika."</string>
-    <string name="permlab_sdcardWrite" product="nosdcard" msgid="85430876310764752">"modyfik./usuwan. z nośnika USB"</string>
+    <string name="permlab_sdcardWrite" product="nosdcard" msgid="85430876310764752">"Modyfikowanie/usuwanie z nośnika USB"</string>
     <string name="permlab_sdcardWrite" product="default" msgid="8079403759001777291">"modyfikowanie/usuwanie zawartości karty SD"</string>
     <string name="permdesc_sdcardWrite" product="nosdcard" msgid="6175406299445710888">"Pozwala aplikacji na zapis w pamięci USB."</string>
     <string name="permdesc_sdcardWrite" product="default" msgid="4337417790936632090">"Pozwala aplikacji na zapis na karcie SD."</string>
@@ -671,7 +671,7 @@
     <string name="faceunlock_multiple_failures" msgid="754137583022792429">"Przekroczono maksymalną liczbę prób odblokowania Face Unlock."</string>
     <string name="lockscreen_plugged_in" msgid="8057762828355572315">"Ładowanie (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string>
     <string name="lockscreen_charged" msgid="4938930459620989972">"Naładowany."</string>
-    <string name="lockscreen_battery_short" msgid="3617549178603354656">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
+    <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"Podłącz ładowarkę."</string>
     <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"Brak karty SIM."</string>
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Brak karty SIM w tablecie."</string>
@@ -720,8 +720,8 @@
     <string name="password_keyboard_label_symbol_key" msgid="992280756256536042">"?123"</string>
     <string name="password_keyboard_label_alpha_key" msgid="8001096175167485649">"ABC"</string>
     <string name="password_keyboard_label_alt_key" msgid="1284820942620288678">"ALT"</string>
-    <string name="hour_ampm" msgid="4329881288269772723">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string>
-    <string name="hour_cap_ampm" msgid="1829009197680861107">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string>
+    <string name="hour_ampm" msgid="4584338083529355982">"<xliff:g id="HOUR">%-l</xliff:g> <xliff:g id="AMPM">%P</xliff:g>"</string>
+    <string name="hour_cap_ampm" msgid="2083465992940444366">"<xliff:g id="HOUR">%-l</xliff:g> <xliff:g id="AMPM">%p</xliff:g>"</string>
     <string name="factorytest_failed" msgid="5410270329114212041">"Nieudany test fabryczny"</string>
     <string name="factorytest_not_system" msgid="4435201656767276723">"Czynność FACTORY_TEST jest obsługiwana tylko dla pakietów zainstalowanych w katalogu /system/app."</string>
     <string name="factorytest_no_action" msgid="872991874799998561">"Nie znaleziono żadnego pakietu, który zapewnia działanie FACTORY_TEST."</string>
@@ -733,7 +733,7 @@
     <string name="double_tap_toast" msgid="4595046515400268881">"Wskazówka: dotknij dwukrotnie, aby powiększyć lub pomniejszyć."</string>
     <string name="autofill_this_form" msgid="4616758841157816676">"Autouzupełnianie"</string>
     <string name="setup_autofill" msgid="7103495070180590814">"Ustaw autouzupełnianie"</string>
-    <string name="autofill_address_name_separator" msgid="2504700673286691795">" "</string>
+    <string name="autofill_address_name_separator" msgid="6350145154779706772">" "</string>
     <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string>
     <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string>
     <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
@@ -768,6 +768,8 @@
     <string name="permdesc_serialPort" msgid="2991639985224598193">"Umożliwia posiadaczowi dostęp do portów szeregowych przy użyciu interfejsu API narzędzia SerialManager."</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"Dostęp do dostawców treści z zewnątrz"</string>
     <string name="permdesc_accessContentProvidersExternally" msgid="4544346486697853685">"Pozwala na dostęp do dostawców treści z powłoki. To uprawnienie nie powinno być potrzebne zwykłym aplikacjom."</string>
+    <string name="permlab_updateLock" msgid="3527558366616680889">"odradź automatyczne aktualizacje urządzenia"</string>
+    <string name="permdesc_updateLock" msgid="1655625832166778492">"Umożliwia posiadaczowi poinformowanie systemu, kiedy będzie dobry moment na nieinteraktywne uruchomienie ponowne wymagane do uaktualnienia urządzenia."</string>
     <string name="save_password_message" msgid="767344687139195790">"Czy chcesz, aby zapamiętać to hasło w przeglądarce?"</string>
     <string name="save_password_notnow" msgid="6389675316706699758">"Nie teraz"</string>
     <string name="save_password_remember" msgid="6491879678996749466">"Zapamiętaj"</string>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index 9f1e053..7f031fd 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -26,7 +26,7 @@
     <string name="gigabyteShort" msgid="3259882455212193214">"GB"</string>
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
-    <string name="fileSizeSuffix" msgid="7670819340156489359">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
     <string name="untitled" msgid="4638956954852782576">"&lt;Sem nome&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -671,7 +671,7 @@
     <string name="faceunlock_multiple_failures" msgid="754137583022792429">"Excedido o n.º máximo de tentativas de Desbloqueio Através do Rosto"</string>
     <string name="lockscreen_plugged_in" msgid="8057762828355572315">"A carregar, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_charged" msgid="4938930459620989972">"Carregado."</string>
-    <string name="lockscreen_battery_short" msgid="3617549178603354656">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
+    <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"Ligue o carregador."</string>
     <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"Nenhum cartão SIM."</string>
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Nenhum cartão SIM no tablet."</string>
@@ -720,8 +720,8 @@
     <string name="password_keyboard_label_symbol_key" msgid="992280756256536042">"?123"</string>
     <string name="password_keyboard_label_alpha_key" msgid="8001096175167485649">"ABC"</string>
     <string name="password_keyboard_label_alt_key" msgid="1284820942620288678">"ALT"</string>
-    <string name="hour_ampm" msgid="4329881288269772723">"<xliff:g id="HOUR">%-l</xliff:g> <xliff:g id="AMPM">%P</xliff:g>"</string>
-    <string name="hour_cap_ampm" msgid="1829009197680861107">"<xliff:g id="HOUR">%-l</xliff:g> <xliff:g id="AMPM">%p</xliff:g>"</string>
+    <string name="hour_ampm" msgid="4584338083529355982">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string>
+    <string name="hour_cap_ampm" msgid="2083465992940444366">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string>
     <string name="factorytest_failed" msgid="5410270329114212041">"O teste de fábrica falhou"</string>
     <string name="factorytest_not_system" msgid="4435201656767276723">"A acção FACTORY_TEST apenas é suportada para pacotes instalados em /system/app."</string>
     <string name="factorytest_no_action" msgid="872991874799998561">"Não foi localizado qualquer pacote que forneça a acção FACTORY_TEST."</string>
@@ -733,7 +733,7 @@
     <string name="double_tap_toast" msgid="4595046515400268881">"Sugestão: toque duas vezes para aumentar ou diminuir o zoom."</string>
     <string name="autofill_this_form" msgid="4616758841157816676">"Preenchimento Automático"</string>
     <string name="setup_autofill" msgid="7103495070180590814">"Configurar Preenchimento Automático"</string>
-    <string name="autofill_address_name_separator" msgid="2504700673286691795">" "</string>
+    <string name="autofill_address_name_separator" msgid="6350145154779706772">" "</string>
     <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string>
     <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string>
     <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
@@ -768,6 +768,8 @@
     <string name="permdesc_serialPort" msgid="2991639985224598193">"Permite ao titular aceder a portas de série através da API SerialManager."</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"aceder a fornecedores de conteúdos externamente"</string>
     <string name="permdesc_accessContentProvidersExternally" msgid="4544346486697853685">"Permite ao titular aceder a fornecedores de conteúdos a partir da shell. Nunca deverá ser necessário para aplicações normais."</string>
+    <string name="permlab_updateLock" msgid="3527558366616680889">"desaconselhar atualizações automáticas do aparelho"</string>
+    <string name="permdesc_updateLock" msgid="1655625832166778492">"Permite ao titular disponibilizar informações ao sistema acerca do melhor momento para efetuar um reinício não interativo para atualização do aparelho."</string>
     <string name="save_password_message" msgid="767344687139195790">"Quer que o browser memorize esta palavra-passe?"</string>
     <string name="save_password_notnow" msgid="6389675316706699758">"Agora não"</string>
     <string name="save_password_remember" msgid="6491879678996749466">"Lembrar"</string>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index 4826ddf..fbfe88f 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -26,7 +26,7 @@
     <string name="gigabyteShort" msgid="3259882455212193214">"GB"</string>
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
-    <string name="fileSizeSuffix" msgid="7670819340156489359">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
     <string name="untitled" msgid="4638956954852782576">"&lt;Sem título&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">".."</string>
@@ -671,7 +671,7 @@
     <string name="faceunlock_multiple_failures" msgid="754137583022792429">"O número máximo de tentativas de Desbloqueio por reconhecimento facial foi excedido"</string>
     <string name="lockscreen_plugged_in" msgid="8057762828355572315">"Carregando, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_charged" msgid="4938930459620989972">"Carregado."</string>
-    <string name="lockscreen_battery_short" msgid="3617549178603354656">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
+    <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"Conecte o seu carregador."</string>
     <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"Sem cartão SIM."</string>
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Não há um cartão SIM no tablet."</string>
@@ -720,8 +720,8 @@
     <string name="password_keyboard_label_symbol_key" msgid="992280756256536042">"?123"</string>
     <string name="password_keyboard_label_alpha_key" msgid="8001096175167485649">"ABC"</string>
     <string name="password_keyboard_label_alt_key" msgid="1284820942620288678">"ALT"</string>
-    <string name="hour_ampm" msgid="4329881288269772723">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string>
-    <string name="hour_cap_ampm" msgid="1829009197680861107">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string>
+    <string name="hour_ampm" msgid="4584338083529355982">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string>
+    <string name="hour_cap_ampm" msgid="2083465992940444366">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string>
     <string name="factorytest_failed" msgid="5410270329114212041">"Falha no teste de fábrica"</string>
     <string name="factorytest_not_system" msgid="4435201656767276723">"A ação FACTORY_TEST é suportada apenas para pacotes instalados em /system/app."</string>
     <string name="factorytest_no_action" msgid="872991874799998561">"Nenhum pacote que forneça a ação FACTORY_TEST foi encontrado."</string>
@@ -733,7 +733,7 @@
     <string name="double_tap_toast" msgid="4595046515400268881">"Dica: toque duas vezes para aumentar e diminuir o zoom."</string>
     <string name="autofill_this_form" msgid="4616758841157816676">"Preench. aut."</string>
     <string name="setup_autofill" msgid="7103495070180590814">"Conf. preench. aut."</string>
-    <string name="autofill_address_name_separator" msgid="2504700673286691795">" "</string>
+    <string name="autofill_address_name_separator" msgid="6350145154779706772">" "</string>
     <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string>
     <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string>
     <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
@@ -768,6 +768,8 @@
     <string name="permdesc_serialPort" msgid="2991639985224598193">"Permite que o detentor tenha acesso a portas seriais usando a API SerialManager."</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"acessar fornec. de conteúdo externamente"</string>
     <string name="permdesc_accessContentProvidersExternally" msgid="4544346486697853685">"Permite que o proprietário tenha acesso a fornecedores de conteúdo a partir da camada. Nunca deve ser necessário para aplicativos normais."</string>
+    <string name="permlab_updateLock" msgid="3527558366616680889">"impedir atualiz. autom. do dispositivo"</string>
+    <string name="permdesc_updateLock" msgid="1655625832166778492">"Permite que o proprietário forneça informações ao sistema sobre quando seria um bom momento para uma reinicialização não interativa para atualizar o dispositivo."</string>
     <string name="save_password_message" msgid="767344687139195790">"Deseja que o navegador lembre desta senha?"</string>
     <string name="save_password_notnow" msgid="6389675316706699758">"Agora não"</string>
     <string name="save_password_remember" msgid="6491879678996749466">"Lembrar"</string>
diff --git a/core/res/res/values-rm/strings.xml b/core/res/res/values-rm/strings.xml
index c7579de..ff76f74 100644
--- a/core/res/res/values-rm/strings.xml
+++ b/core/res/res/values-rm/strings.xml
@@ -26,7 +26,8 @@
     <string name="gigabyteShort" msgid="3259882455212193214">"GB"</string>
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
-    <string name="fileSizeSuffix" msgid="7670819340156489359">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <!-- no translation found for fileSizeSuffix (9164292791500531949) -->
+    <skip />
     <!-- no translation found for untitled (4638956954852782576) -->
     <skip />
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
@@ -1000,7 +1001,8 @@
     <!-- no translation found for lockscreen_plugged_in (8057762828355572315) -->
     <skip />
     <string name="lockscreen_charged" msgid="4938930459620989972">"Chargià"</string>
-    <string name="lockscreen_battery_short" msgid="3617549178603354656">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
+    <!-- no translation found for lockscreen_battery_short (4477264849386850266) -->
+    <skip />
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"Connectai Voss chargiader."</string>
     <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"Nagina carta SIM."</string>
     <!-- no translation found for lockscreen_missing_sim_message (151659196095791474) -->
@@ -1077,8 +1079,10 @@
     <string name="password_keyboard_label_symbol_key" msgid="992280756256536042">"?123"</string>
     <string name="password_keyboard_label_alpha_key" msgid="8001096175167485649">"ABC"</string>
     <string name="password_keyboard_label_alt_key" msgid="1284820942620288678">"ALT"</string>
-    <string name="hour_ampm" msgid="4329881288269772723">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string>
-    <string name="hour_cap_ampm" msgid="1829009197680861107">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string>
+    <!-- no translation found for hour_ampm (4584338083529355982) -->
+    <skip />
+    <!-- no translation found for hour_cap_ampm (2083465992940444366) -->
+    <skip />
     <string name="factorytest_failed" msgid="5410270329114212041">"Il test da fabrica n\'è betg reussì"</string>
     <string name="factorytest_not_system" msgid="4435201656767276723">"L\'acziun FACTORY_TEST vegn mo sustegnida per pachets installads en /system/app."</string>
     <string name="factorytest_no_action" msgid="872991874799998561">"Betg chattà in pachet che porscha l\'acziun FACTORY_TEST."</string>
@@ -1095,7 +1099,7 @@
     <skip />
     <!-- no translation found for setup_autofill (7103495070180590814) -->
     <skip />
-    <!-- no translation found for autofill_address_name_separator (2504700673286691795) -->
+    <!-- no translation found for autofill_address_name_separator (6350145154779706772) -->
     <skip />
     <!-- no translation found for autofill_address_summary_name_format (3268041054899214945) -->
     <skip />
@@ -1163,6 +1167,10 @@
     <skip />
     <!-- no translation found for permdesc_accessContentProvidersExternally (4544346486697853685) -->
     <skip />
+    <!-- no translation found for permlab_updateLock (3527558366616680889) -->
+    <skip />
+    <!-- no translation found for permdesc_updateLock (1655625832166778492) -->
+    <skip />
     <string name="save_password_message" msgid="767344687139195790">"Vulais Vus ch\'il navigatur memorisescha quest pled-clav?"</string>
     <string name="save_password_notnow" msgid="6389675316706699758">"Betg ussa"</string>
     <string name="save_password_remember" msgid="6491879678996749466">"Memorisar"</string>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index 0890cc0..cac586e 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -26,7 +26,7 @@
     <string name="gigabyteShort" msgid="3259882455212193214">"GO"</string>
     <string name="terabyteShort" msgid="231613018159186962">"TO"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PO"</string>
-    <string name="fileSizeSuffix" msgid="7670819340156489359">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
     <string name="untitled" msgid="4638956954852782576">"&lt;Fără titlu&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -313,10 +313,8 @@
     <string name="permlab_changeComponentState" msgid="6335576775711095931">"activare sau dezactivare a componentelor aplicaţiei"</string>
     <string name="permdesc_changeComponentState" product="tablet" msgid="8887435740982237294">"Permite aplicaţiei să modifice starea activată sau dezactivată a unei componente a altei aplicaţii. Aplicaţiile rău intenţionate pot să utilizeze această permisiune pentru a dezactiva funcţii importante ale tabletei. Este necesar să utilizaţi cu atenţie această permisiune, deoarece este posibil să aduceţi componentele aplicaţiei într-o stare inutilizabilă, inconsecventă sau instabilă."</string>
     <string name="permdesc_changeComponentState" product="default" msgid="1827232484416505615">"Permite aplicaţiei să modifice starea activată sau dezactivată a unei componente a altei aplicaţii. Aplicaţiile rău intenţionate pot să utilizeze această permisiune pentru a dezactiva funcţii importante ale telefonului. Este necesar să utilizaţi cu atenţie această permisiune, deoarece este posibil să aduceţi componentele aplicaţiei într-o stare inutilizabilă, inconsecventă sau instabilă."</string>
-    <!-- no translation found for permlab_grantRevokePermissions (4627315351093508795) -->
-    <skip />
-    <!-- no translation found for permdesc_grantRevokePermissions (4088642654085850662) -->
-    <skip />
+    <string name="permlab_grantRevokePermissions" msgid="4627315351093508795">"acordaţi sau revocaţi permisiuni"</string>
+    <string name="permdesc_grantRevokePermissions" msgid="4088642654085850662">"Permite unei aplicaţii să acorde sau să revoce permisiuni specifice acelei aplicaţii sau altor aplicaţii. Aplicaţiile rău intenţionate pot utiliza această permisiune pentru a accesa funcţii pe care nu le-aţi permis."</string>
     <string name="permlab_setPreferredApplications" msgid="8463181628695396391">"setare aplicaţii preferate"</string>
     <string name="permdesc_setPreferredApplications" msgid="4973986762241783712">"Permite aplicaţiei să modifice aplicaţiile dvs. preferate. Aplicaţiile rău intenţionate pot să modifice fără a vă înştiinţa aplicaţiile care rulează, păcălind aplicaţiile existente să colecteze date private de la dvs."</string>
     <string name="permlab_writeSettings" msgid="1365523497395143704">"modificare setări sistem globale"</string>
@@ -673,7 +671,7 @@
     <string name="faceunlock_multiple_failures" msgid="754137583022792429">"S-a depăşit numărul maxim de încercări pentru Deblocare facială"</string>
     <string name="lockscreen_plugged_in" msgid="8057762828355572315">"Se încarcă, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_charged" msgid="4938930459620989972">"Încărcată."</string>
-    <string name="lockscreen_battery_short" msgid="3617549178603354656">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
+    <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g> <xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"Conectaţi încărcătorul."</string>
     <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"Niciun card SIM."</string>
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Nu există card SIM în computerul tablet PC."</string>
@@ -722,8 +720,8 @@
     <string name="password_keyboard_label_symbol_key" msgid="992280756256536042">"?123"</string>
     <string name="password_keyboard_label_alpha_key" msgid="8001096175167485649">"ABC"</string>
     <string name="password_keyboard_label_alt_key" msgid="1284820942620288678">"ALT"</string>
-    <string name="hour_ampm" msgid="4329881288269772723">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string>
-    <string name="hour_cap_ampm" msgid="1829009197680861107">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string>
+    <string name="hour_ampm" msgid="4584338083529355982">"<xliff:g id="HOUR">%-l</xliff:g> <xliff:g id="AMPM">%P</xliff:g>"</string>
+    <string name="hour_cap_ampm" msgid="2083465992940444366">"<xliff:g id="HOUR">%-l</xliff:g> <xliff:g id="AMPM">%p</xliff:g>"</string>
     <string name="factorytest_failed" msgid="5410270329114212041">"Testarea de fabrică nu a reuşit"</string>
     <string name="factorytest_not_system" msgid="4435201656767276723">"Acţiunea FACTORY_TEST este acceptată doar pentru pachetele instalate în /system/app."</string>
     <string name="factorytest_no_action" msgid="872991874799998561">"Nu s-a găsit niciun pachet care să ofere acţiunea FACTORY_TEST."</string>
@@ -735,7 +733,7 @@
     <string name="double_tap_toast" msgid="4595046515400268881">"Sfat: măriţi şi micşoraţi prin dublă atingere."</string>
     <string name="autofill_this_form" msgid="4616758841157816676">"Automat"</string>
     <string name="setup_autofill" msgid="7103495070180590814">"Conf.Compl.auto."</string>
-    <string name="autofill_address_name_separator" msgid="2504700673286691795">" "</string>
+    <string name="autofill_address_name_separator" msgid="6350145154779706772">" "</string>
     <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string>
     <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string>
     <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
@@ -770,6 +768,8 @@
     <string name="permdesc_serialPort" msgid="2991639985224598193">"Permite posesorului accesul la porturile serial utilizând API-ul SerialManager."</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"accesaţi furniz. de conţin. din exterior"</string>
     <string name="permdesc_accessContentProvidersExternally" msgid="4544346486697853685">"Permite deţinătorului să acceseze furnizorii de conţinut din interfaţă. Nu ar trebui să fie necesară pentru aplicaţiile normale."</string>
+    <string name="permlab_updateLock" msgid="3527558366616680889">"descuraj. actual. autom. ale dispozitiv."</string>
+    <string name="permdesc_updateLock" msgid="1655625832166778492">"Permite proprietarului să ofere sistemului informaţii cu privire la momentul oportun pentru o repornire noninteractivă în scopul trecerii dispozitivului la o versiune superioară."</string>
     <string name="save_password_message" msgid="767344687139195790">"Doriţi ca browserul să reţină această parolă?"</string>
     <string name="save_password_notnow" msgid="6389675316706699758">"Nu acum"</string>
     <string name="save_password_remember" msgid="6491879678996749466">"Reţineţi"</string>
@@ -1008,8 +1008,7 @@
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Setaţi data"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Setaţi"</string>
     <string name="default_permission_group" msgid="2690160991405646128">"Prestabilit"</string>
-    <!-- no translation found for perms_new_perm_prefix (8257740710754301407) -->
-    <skip />
+    <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ffffa3a3">"NOU: "</font></string>
     <string name="no_permissions" msgid="7283357728219338112">"Nu se solicită nicio permisiune"</string>
     <string name="perms_hide" msgid="7283915391320676226"><b>"Ascundeţi"</b></string>
     <string name="perms_show_all" msgid="2671791163933091180"><b>"Afişaţi-le pe toate"</b></string>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index 662a54e..3a554d6 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -26,7 +26,7 @@
     <string name="gigabyteShort" msgid="3259882455212193214">"ГБ"</string>
     <string name="terabyteShort" msgid="231613018159186962">"TБ"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"ПБ"</string>
-    <string name="fileSizeSuffix" msgid="7670819340156489359">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
     <string name="untitled" msgid="4638956954852782576">"&lt;Без названия&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"..."</string>
@@ -671,7 +671,7 @@
     <string name="faceunlock_multiple_failures" msgid="754137583022792429">"Все попытки войти с помощью Фейсконтроля использованы"</string>
     <string name="lockscreen_plugged_in" msgid="8057762828355572315">"Идет зарядка (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string>
     <string name="lockscreen_charged" msgid="4938930459620989972">"Батарея заряжена"</string>
-    <string name="lockscreen_battery_short" msgid="3617549178603354656">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
+    <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"Подключите зарядное устройство."</string>
     <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"Нет SIM-карты"</string>
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"SIM-карта не установлена."</string>
@@ -720,8 +720,8 @@
     <string name="password_keyboard_label_symbol_key" msgid="992280756256536042">"?123"</string>
     <string name="password_keyboard_label_alpha_key" msgid="8001096175167485649">"АБВ"</string>
     <string name="password_keyboard_label_alt_key" msgid="1284820942620288678">"ALT"</string>
-    <string name="hour_ampm" msgid="4329881288269772723">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string>
-    <string name="hour_cap_ampm" msgid="1829009197680861107">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string>
+    <string name="hour_ampm" msgid="4584338083529355982">"<xliff:g id="HOUR">%-l</xliff:g> <xliff:g id="AMPM">%P</xliff:g>"</string>
+    <string name="hour_cap_ampm" msgid="2083465992940444366">"<xliff:g id="HOUR">%-l</xliff:g> <xliff:g id="AMPM">%p</xliff:g>"</string>
     <string name="factorytest_failed" msgid="5410270329114212041">"Не удалось провести стандартный тест"</string>
     <string name="factorytest_not_system" msgid="4435201656767276723">"Действие FACTORY_TEST поддерживается только для пакетов, установленных в /system/app."</string>
     <string name="factorytest_no_action" msgid="872991874799998561">"Пакет, обеспечивающий действие FACTORY_TEST, не найден."</string>
@@ -733,7 +733,7 @@
     <string name="double_tap_toast" msgid="4595046515400268881">"Совет: нажмите дважды, чтобы увеличить и уменьшить масштаб."</string>
     <string name="autofill_this_form" msgid="4616758841157816676">"Автозаполнение"</string>
     <string name="setup_autofill" msgid="7103495070180590814">"Настроить автозаполнение"</string>
-    <string name="autofill_address_name_separator" msgid="2504700673286691795">" "</string>
+    <string name="autofill_address_name_separator" msgid="6350145154779706772">" "</string>
     <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string>
     <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string>
     <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
@@ -768,6 +768,8 @@
     <string name="permdesc_serialPort" msgid="2991639985224598193">"Открыть владельцу доступ к последовательным портам с помощью SerialManager API."</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"доступ к контенту без приложения"</string>
     <string name="permdesc_accessContentProvidersExternally" msgid="4544346486697853685">"Владелец сможет получить доступ к контенту без использования приложения. Это разрешение не применяется в обычных приложениях."</string>
+    <string name="permlab_updateLock" msgid="3527558366616680889">"предотвращать авт. обновления устройства"</string>
+    <string name="permdesc_updateLock" msgid="1655625832166778492">"Позволяет владельцу сообщить системе о подходящем моменте для неинтерактивной перезагрузки в ходе обновления устройства."</string>
     <string name="save_password_message" msgid="767344687139195790">"Вы хотите, чтобы браузер запомнил этот пароль?"</string>
     <string name="save_password_notnow" msgid="6389675316706699758">"Не сейчас"</string>
     <string name="save_password_remember" msgid="6491879678996749466">"Запомнить"</string>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index 98b829f..daa321d 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -26,7 +26,7 @@
     <string name="gigabyteShort" msgid="3259882455212193214">"GB"</string>
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
-    <string name="fileSizeSuffix" msgid="7670819340156489359">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
     <string name="untitled" msgid="4638956954852782576">"&lt;Bez mena&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -671,7 +671,7 @@
     <string name="faceunlock_multiple_failures" msgid="754137583022792429">"Prekročili ste maximálny povolený počet pokusov o odomknutie tvárou"</string>
     <string name="lockscreen_plugged_in" msgid="8057762828355572315">"Prebieha nabíjanie, <xliff:g id="NUMBER">%d</xliff:g> <xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_charged" msgid="4938930459620989972">"Nabité."</string>
-    <string name="lockscreen_battery_short" msgid="3617549178603354656">"<xliff:g id="NUMBER">%d</xliff:g> <xliff:g id="PERCENT">%%</xliff:g>"</string>
+    <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g> <xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"Pripojte nabíjačku."</string>
     <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"Nie je vložená karta SIM."</string>
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"V tablete nie je žiadna karta SIM."</string>
@@ -720,8 +720,8 @@
     <string name="password_keyboard_label_symbol_key" msgid="992280756256536042">"?123"</string>
     <string name="password_keyboard_label_alpha_key" msgid="8001096175167485649">"ABC"</string>
     <string name="password_keyboard_label_alt_key" msgid="1284820942620288678">"ALT"</string>
-    <string name="hour_ampm" msgid="4329881288269772723">"<xliff:g id="HOUR">%-l</xliff:g> <xliff:g id="AMPM">%P</xliff:g>"</string>
-    <string name="hour_cap_ampm" msgid="1829009197680861107">"<xliff:g id="HOUR">%-l</xliff:g> <xliff:g id="AMPM">%p</xliff:g>"</string>
+    <string name="hour_ampm" msgid="4584338083529355982">"<xliff:g id="HOUR">%-l</xliff:g> <xliff:g id="AMPM">%P</xliff:g>"</string>
+    <string name="hour_cap_ampm" msgid="2083465992940444366">"<xliff:g id="HOUR">%-l</xliff:g> <xliff:g id="AMPM">%p</xliff:g>"</string>
     <string name="factorytest_failed" msgid="5410270329114212041">"Továrenský test zlyhal"</string>
     <string name="factorytest_not_system" msgid="4435201656767276723">"Test FACTORY_TEST je možné uskutočniť iba pri balíčkoch nainštalovaných v priečinku /system/app."</string>
     <string name="factorytest_no_action" msgid="872991874799998561">"Nebol nájdený žiadny balíček umožňujúci test FACTORY_TEST."</string>
@@ -733,7 +733,7 @@
     <string name="double_tap_toast" msgid="4595046515400268881">"Tip: Dvojitým klepnutím môžete zobrazenie priblížiť alebo oddialiť."</string>
     <string name="autofill_this_form" msgid="4616758841157816676">"Aut.dop."</string>
     <string name="setup_autofill" msgid="7103495070180590814">"Nast. Aut. dop."</string>
-    <string name="autofill_address_name_separator" msgid="2504700673286691795">" "</string>
+    <string name="autofill_address_name_separator" msgid="6350145154779706772">" "</string>
     <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string>
     <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string>
     <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
@@ -766,10 +766,10 @@
     <string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"Umožňuje držiteľovi podávať žiadosti o overenie balíkov. Bežné aplikácie by toto nastavenie nemali nikdy potrebovať."</string>
     <string name="permlab_serialPort" msgid="546083327654631076">"prístup k sériovým portom"</string>
     <string name="permdesc_serialPort" msgid="2991639985224598193">"Držiteľa oprávňuje na prístup k sériovým portom pomocou rozhrania API SerialManager."</string>
-    <!-- no translation found for permlab_accessContentProvidersExternally (5077774297943409285) -->
-    <skip />
-    <!-- no translation found for permdesc_accessContentProvidersExternally (4544346486697853685) -->
-    <skip />
+    <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"externý prístup k poskytovateľom obsahu"</string>
+    <string name="permdesc_accessContentProvidersExternally" msgid="4544346486697853685">"Povoľuje držiteľovi pristupovať k poskytovateľom obsahu z príkazového riadka. Normálne aplikácie by túto možnosť nikdy nemali potrebovať."</string>
+    <string name="permlab_updateLock" msgid="3527558366616680889">"zakázať automatické aktualizácie zariad."</string>
+    <string name="permdesc_updateLock" msgid="1655625832166778492">"Umožňuje držiteľovi poskytnúť systému informácie o vhodnom čase na automatický reštart zariadenia kvôli inovovaniu."</string>
     <string name="save_password_message" msgid="767344687139195790">"Chcete, aby si prehliadač zapamätal toto heslo?"</string>
     <string name="save_password_notnow" msgid="6389675316706699758">"Teraz nie"</string>
     <string name="save_password_remember" msgid="6491879678996749466">"Zapamätať"</string>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index 9d99013..20ad59b 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -26,7 +26,7 @@
     <string name="gigabyteShort" msgid="3259882455212193214">"GB"</string>
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
-    <string name="fileSizeSuffix" msgid="7670819340156489359">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
     <string name="untitled" msgid="4638956954852782576">"&lt;Brez naslova&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -314,7 +314,7 @@
     <string name="permdesc_changeComponentState" product="tablet" msgid="8887435740982237294">"Programu omogoča, da spremeni, ali je komponenta drugega programa omogočena ali ne. Zlonamerni programi lahko to uporabijo za onemogočanje pomembnih zmožnosti tabličnega računalnika. Pri dodeljevanju dovoljenja je treba biti previden, saj lahko komponente programa nastavite tako, da jih ni mogoče uporabiti, da niso dosledne ali da niso stabilne."</string>
     <string name="permdesc_changeComponentState" product="default" msgid="1827232484416505615">"Programu omogoča, da spremeni, ali je komponenta drugega programa omogočena ali ne. Zlonamerni programi lahko to uporabijo za onemogočanje pomembnih zmožnosti telefona. Pri dodeljevanju dovoljenja je treba biti previden, saj lahko komponente programa nastavite tako, da jih ni mogoče uporabiti, da niso dosledne ali da niso stabilne."</string>
     <string name="permlab_grantRevokePermissions" msgid="4627315351093508795">"dodeljevanje ali preklic dovoljenj"</string>
-    <string name="permdesc_grantRevokePermissions" msgid="4088642654085850662">"Programu omogoča dodeljevanje ali preklic posebnih dovoljenj zanj ali za druge programe. Zlonamerni programi lahko to uporabijo za dostop do funkcij, za katere jim niste dodelili pravic."</string>
+    <string name="permdesc_grantRevokePermissions" msgid="4088642654085850662">"Aplikaciji omogoča dodeljevanje ali preklic posebnih dovoljenj zanjo ali za druge aplikacije. Zlonamerne aplikacije lahko to uporabijo za dostop do funkcij, za katere jim niste dodelili pravic."</string>
     <string name="permlab_setPreferredApplications" msgid="8463181628695396391">"nastavitev prednostnih programov"</string>
     <string name="permdesc_setPreferredApplications" msgid="4973986762241783712">"Programu omogoča spreminjanje priljubljenih programov. Zlonamerni programi lahko s tem neopazno spremenijo programe, ki se izvajajo, tako da se izdajajo za obstoječe programe in zbirajo osebne podatke."</string>
     <string name="permlab_writeSettings" msgid="1365523497395143704">"spreminjanje splošnih nastavitev sistema"</string>
@@ -671,7 +671,7 @@
     <string name="faceunlock_multiple_failures" msgid="754137583022792429">"Presegli ste dovoljeno število poskusov odklepanja z obrazom"</string>
     <string name="lockscreen_plugged_in" msgid="8057762828355572315">"Polnjenje (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string>
     <string name="lockscreen_charged" msgid="4938930459620989972">"Napolnjeno."</string>
-    <string name="lockscreen_battery_short" msgid="3617549178603354656">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
+    <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"Priključite napajalnik."</string>
     <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"Ni kartice SIM."</string>
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"V tabličnem računalniku ni kartice SIM."</string>
@@ -720,8 +720,8 @@
     <string name="password_keyboard_label_symbol_key" msgid="992280756256536042">"?123"</string>
     <string name="password_keyboard_label_alpha_key" msgid="8001096175167485649">"ABC"</string>
     <string name="password_keyboard_label_alt_key" msgid="1284820942620288678">"ALT"</string>
-    <string name="hour_ampm" msgid="4329881288269772723">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string>
-    <string name="hour_cap_ampm" msgid="1829009197680861107">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string>
+    <string name="hour_ampm" msgid="4584338083529355982">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string>
+    <string name="hour_cap_ampm" msgid="2083465992940444366">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string>
     <string name="factorytest_failed" msgid="5410270329114212041">"Tovarniški preskus ni uspel"</string>
     <string name="factorytest_not_system" msgid="4435201656767276723">"Dejanje FACTORY_TEST je podprto le za pakete, nameščene v razdelku /system/app."</string>
     <string name="factorytest_no_action" msgid="872991874799998561">"Ni bilo najdenega paketa, ki omogoča dejanje FACTORY_TEST."</string>
@@ -733,7 +733,7 @@
     <string name="double_tap_toast" msgid="4595046515400268881">"Nasvet: Tapnite dvakrat, če želite povečati ali pomanjšati."</string>
     <string name="autofill_this_form" msgid="4616758841157816676">"Samoizp."</string>
     <string name="setup_autofill" msgid="7103495070180590814">"Nastavi samoizp."</string>
-    <string name="autofill_address_name_separator" msgid="2504700673286691795">" "</string>
+    <string name="autofill_address_name_separator" msgid="6350145154779706772">" "</string>
     <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string>
     <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string>
     <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
@@ -768,6 +768,8 @@
     <string name="permdesc_serialPort" msgid="2991639985224598193">"Imetniku omogoča, da z API-jem za SerialManager dostopa do serijskih vrat."</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"zunanji dostop do ponudnikov vsebine"</string>
     <string name="permdesc_accessContentProvidersExternally" msgid="4544346486697853685">"Omogoča imetniku, da dostopa do ponudnikov vsebine iz lupine. Nikoli naj ne bi bilo potrebno za običajne programe"</string>
+    <string name="permlab_updateLock" msgid="3527558366616680889">"odvrnitev samodejnih posodobitev naprave"</string>
+    <string name="permdesc_updateLock" msgid="1655625832166778492">"Dovoli, da lastnik sistemu ponudi informacije o tem, kdaj je primeren čas za neinteraktiven vnovični zagon, s katerim nadgradi napravo."</string>
     <string name="save_password_message" msgid="767344687139195790">"Ali želite, da si brskalnik zapomni to geslo?"</string>
     <string name="save_password_notnow" msgid="6389675316706699758">"Ne zdaj"</string>
     <string name="save_password_remember" msgid="6491879678996749466">"Zapomni si"</string>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index a9e7b9b..9fb8abf 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -26,7 +26,7 @@
     <string name="gigabyteShort" msgid="3259882455212193214">"GB"</string>
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
-    <string name="fileSizeSuffix" msgid="7670819340156489359">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
     <string name="untitled" msgid="4638956954852782576">"&lt;Без наслова&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -671,7 +671,7 @@
     <string name="faceunlock_multiple_failures" msgid="754137583022792429">"Премашен је највећи дозвољени број покушаја Откључавања лицем"</string>
     <string name="lockscreen_plugged_in" msgid="8057762828355572315">"Пуњење, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_charged" msgid="4938930459620989972">"Батерија је напуњена."</string>
-    <string name="lockscreen_battery_short" msgid="3617549178603354656">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
+    <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"Повежите пуњач."</string>
     <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"Нема SIM картице."</string>
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"У таблету нема SIM картице."</string>
@@ -720,8 +720,8 @@
     <string name="password_keyboard_label_symbol_key" msgid="992280756256536042">"?123"</string>
     <string name="password_keyboard_label_alpha_key" msgid="8001096175167485649">"ABC"</string>
     <string name="password_keyboard_label_alt_key" msgid="1284820942620288678">"ALT"</string>
-    <string name="hour_ampm" msgid="4329881288269772723">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string>
-    <string name="hour_cap_ampm" msgid="1829009197680861107">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string>
+    <string name="hour_ampm" msgid="4584338083529355982">"<xliff:g id="HOUR">%-l</xliff:g> <xliff:g id="AMPM">%P</xliff:g>"</string>
+    <string name="hour_cap_ampm" msgid="2083465992940444366">"<xliff:g id="HOUR">%-l</xliff:g> <xliff:g id="AMPM">%p</xliff:g>"</string>
     <string name="factorytest_failed" msgid="5410270329114212041">"Фабричко тестирање није успело"</string>
     <string name="factorytest_not_system" msgid="4435201656767276723">"Радња FACTORY_TEST је подржана само за пакете инсталиране у директоријуму /system/app."</string>
     <string name="factorytest_no_action" msgid="872991874799998561">"Није пронађен ниједан пакет који обезбеђује радњу FACTORY_TEST."</string>
@@ -733,7 +733,7 @@
     <string name="double_tap_toast" msgid="4595046515400268881">"Савет: Додирните двапут да бисте увећали и умањили приказ."</string>
     <string name="autofill_this_form" msgid="4616758841157816676">"Аутом. поп."</string>
     <string name="setup_autofill" msgid="7103495070180590814">"Подеш. аут. поп."</string>
-    <string name="autofill_address_name_separator" msgid="2504700673286691795">" "</string>
+    <string name="autofill_address_name_separator" msgid="6350145154779706772">" "</string>
     <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string>
     <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string>
     <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
@@ -768,6 +768,8 @@
     <string name="permdesc_serialPort" msgid="2991639985224598193">"Омогућава власнику да приступи серијским портовима помоћу SerialManager API-ја."</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"приступ добављачима садржаја споља"</string>
     <string name="permdesc_accessContentProvidersExternally" msgid="4544346486697853685">"Дозвољава власнику да приступа добављачима садржаја из интерфејса. Никада не би требало да буде потребно за обичне апликације."</string>
+    <string name="permlab_updateLock" msgid="3527558366616680889">"одговарање од аутом. ажурирања уређаја"</string>
+    <string name="permdesc_updateLock" msgid="1655625832166778492">"Дозвољава носиоцу да систему понуди информације о томе када је погодно време да неинтерактивно поновно покретање надогради уређај."</string>
     <string name="save_password_message" msgid="767344687139195790">"Желите ли да прегледач запамти ову лозинку?"</string>
     <string name="save_password_notnow" msgid="6389675316706699758">"Не сада"</string>
     <string name="save_password_remember" msgid="6491879678996749466">"Запамти"</string>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index f780ca4..2c4189b 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -26,7 +26,7 @@
     <string name="gigabyteShort" msgid="3259882455212193214">"GB"</string>
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
-    <string name="fileSizeSuffix" msgid="7670819340156489359">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
     <string name="untitled" msgid="4638956954852782576">"&lt;Okänd&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">".."</string>
@@ -313,10 +313,8 @@
     <string name="permlab_changeComponentState" msgid="6335576775711095931">"aktivera eller inaktivera appkomponenter"</string>
     <string name="permdesc_changeComponentState" product="tablet" msgid="8887435740982237294">"Tillåter att appen ändrar inställningen för om en komponent i en annan app ska aktiveras eller inte. Skadliga appar kan använda detta för att inaktivera viktiga funktioner i pekdatorn. Var försiktig med behörigheten, eftersom appkomponenter kan bli oanvändbara, inkonsekventa eller instabila."</string>
     <string name="permdesc_changeComponentState" product="default" msgid="1827232484416505615">"Tillåter att appen ändrar inställningen för om en komponent i en annan app ska aktiveras eller inte. Skadliga appar kan använda detta för att inaktivera viktiga funktioner i pekdatorn. Var försiktig med behörigheten, eftersom programkomponenter kan bli oanvändbara, inkonsekventa eller instabila."</string>
-    <!-- no translation found for permlab_grantRevokePermissions (4627315351093508795) -->
-    <skip />
-    <!-- no translation found for permdesc_grantRevokePermissions (4088642654085850662) -->
-    <skip />
+    <string name="permlab_grantRevokePermissions" msgid="4627315351093508795">"bevilja eller återkalla behörighet"</string>
+    <string name="permdesc_grantRevokePermissions" msgid="4088642654085850662">"Tillåter att en app beviljar eller återkallar specifik behörighet, för sig själv eller andra appar. Skadlig programvara kan utnyttja detta för att få åtkomst till funktioner som du inte har beviljat behörighet till."</string>
     <string name="permlab_setPreferredApplications" msgid="8463181628695396391">"ange önskade appar"</string>
     <string name="permdesc_setPreferredApplications" msgid="4973986762241783712">"Tillåter att appen ändrar dina önskade appar. Skadliga appar kan utan förvarning ändra de appar som körs och kapa dina befintliga appar så att de börjar samla privata uppgifter från dig."</string>
     <string name="permlab_writeSettings" msgid="1365523497395143704">"ändra globala systeminställningar"</string>
@@ -673,7 +671,7 @@
     <string name="faceunlock_multiple_failures" msgid="754137583022792429">"Du har försökt låsa upp med Ansiktslås för många gånger"</string>
     <string name="lockscreen_plugged_in" msgid="8057762828355572315">"Laddar (<xliff:g id="PERCENT">%%</xliff:g> <xliff:g id="NUMBER">%d</xliff:g>)"</string>
     <string name="lockscreen_charged" msgid="4938930459620989972">"Laddad."</string>
-    <string name="lockscreen_battery_short" msgid="3617549178603354656">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
+    <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g> <xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"Anslut din laddare."</string>
     <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"Inget SIM-kort."</string>
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Inget SIM-kort i pekdatorn."</string>
@@ -722,8 +720,8 @@
     <string name="password_keyboard_label_symbol_key" msgid="992280756256536042">"?123"</string>
     <string name="password_keyboard_label_alpha_key" msgid="8001096175167485649">"ABC"</string>
     <string name="password_keyboard_label_alt_key" msgid="1284820942620288678">"ALT"</string>
-    <string name="hour_ampm" msgid="4329881288269772723">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string>
-    <string name="hour_cap_ampm" msgid="1829009197680861107">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string>
+    <string name="hour_ampm" msgid="4584338083529355982">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string>
+    <string name="hour_cap_ampm" msgid="2083465992940444366">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string>
     <string name="factorytest_failed" msgid="5410270329114212041">"Det gick fel vid fabrikstestet"</string>
     <string name="factorytest_not_system" msgid="4435201656767276723">"Åtgärden FACTORY_TEST stöds endast för paket som har installerats i /system/app."</string>
     <string name="factorytest_no_action" msgid="872991874799998561">"Vi hittade inget paket som erbjuder åtgärden FACTORY_TEST."</string>
@@ -735,7 +733,8 @@
     <string name="double_tap_toast" msgid="4595046515400268881">"Tips! Dubbelknacka om du vill zooma in eller ut."</string>
     <string name="autofill_this_form" msgid="4616758841157816676">"Autofyll"</string>
     <string name="setup_autofill" msgid="7103495070180590814">"Ange Autofyll"</string>
-    <string name="autofill_address_name_separator" msgid="2504700673286691795">" "</string>
+    <!-- no translation found for autofill_address_name_separator (6350145154779706772) -->
+    <skip />
     <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string>
     <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string>
     <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
@@ -770,6 +769,8 @@
     <string name="permdesc_serialPort" msgid="2991639985224598193">"Innebär att innehavaren får åtkomst till serieportar med programmeringsgränssnittet för SerialManager."</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"komma åt innehållsleverantörer externt"</string>
     <string name="permdesc_accessContentProvidersExternally" msgid="4544346486697853685">"Innehavaren kan få åtkomst till innehållsleverantörer från skalet. Ska inte behövas för vanliga appar."</string>
+    <string name="permlab_updateLock" msgid="3527558366616680889">"hindra automatiska enhetsuppdateringar"</string>
+    <string name="permdesc_updateLock" msgid="1655625832166778492">"Innehavaren kan informera systemet när det är lämpligt att göra en omstart utan interaktivitet för att uppgradera enheten."</string>
     <string name="save_password_message" msgid="767344687139195790">"Vill du att webbläsaren ska komma ihåg lösenordet?"</string>
     <string name="save_password_notnow" msgid="6389675316706699758">"Inte nu"</string>
     <string name="save_password_remember" msgid="6491879678996749466">"Kom ihåg"</string>
@@ -1008,8 +1009,7 @@
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Ange datum"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Ställ in"</string>
     <string name="default_permission_group" msgid="2690160991405646128">"Standardinställning"</string>
-    <!-- no translation found for perms_new_perm_prefix (8257740710754301407) -->
-    <skip />
+    <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ffffa3a3">"NY: "</font></string>
     <string name="no_permissions" msgid="7283357728219338112">"Inga behörigheter krävs"</string>
     <string name="perms_hide" msgid="7283915391320676226"><b>"Dölj"</b></string>
     <string name="perms_show_all" msgid="2671791163933091180"><b>"Visa alla"</b></string>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index c9e4692..286e6d6 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -26,7 +26,7 @@
     <string name="gigabyteShort" msgid="3259882455212193214">"GB"</string>
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
-    <string name="fileSizeSuffix" msgid="7670819340156489359">"Kishika nafasi<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
     <string name="untitled" msgid="4638956954852782576">"&lt;Haina jina&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -313,10 +313,8 @@
     <string name="permlab_changeComponentState" msgid="6335576775711095931">"wezesha au lemeza vijenzi vya programu"</string>
     <string name="permdesc_changeComponentState" product="tablet" msgid="8887435740982237294">"Inaruhusu programu kubadilisha kama kijenzi cha programu nyingine kimewezeshwa au la. Programu hasidi zinaweza kutumia hii kulemeza uwezo muhimu wa kompyuta kibao. Lazina uangalifu utumike kwa ruhusa hii, kwani kuna uwezekano kupata vijenzi vya programu katika hali isiyotumika, isiyowiana, au hali isiyo thabiti."</string>
     <string name="permdesc_changeComponentState" product="default" msgid="1827232484416505615">"Inaruhusu programu kubadilisha kama kijenzi cha programu nyingine kimewezeshwa au la. Programu hasidi zinaweza kutumia hii kulemeza mambo muhimu ambayo simu inaweza kufanya. Lazima uangalifu utumike kwa ruhusa hii, kwani kuna uwezekano kufanya vijenzi vya programu kuwa katika hali ya kutotumika, kutokuwa na uwiano, au kutokuwa thabiti."</string>
-    <!-- no translation found for permlab_grantRevokePermissions (4627315351093508795) -->
-    <skip />
-    <!-- no translation found for permdesc_grantRevokePermissions (4088642654085850662) -->
-    <skip />
+    <string name="permlab_grantRevokePermissions" msgid="4627315351093508795">"toa au batilisha idhini"</string>
+    <string name="permdesc_grantRevokePermissions" msgid="4088642654085850662">"Inaruhusu programu kutoa au kukataa idhini maalum ya programu hii au zingine. Programu hasidi zinaweza kutumia hii ili kufikia vipengee ambavyo hujaziruhusu."</string>
     <string name="permlab_setPreferredApplications" msgid="8463181628695396391">"kuweka programu zinazopendelewa"</string>
     <string name="permdesc_setPreferredApplications" msgid="4973986762241783712">"Inaruhusu programu kurekebisha programu unazopendelea. Programu hasidi zinaweza, polepole, kubadilisha programu zinazoendeshwa, na kuzifanya programu ulizo nazo kukusanya data ya kibinafsi kutoka kwako."</string>
     <string name="permlab_writeSettings" msgid="1365523497395143704">"rekebisha mipangilio ya mfumo jumla"</string>
@@ -673,7 +671,7 @@
     <string name="faceunlock_multiple_failures" msgid="754137583022792429">"Majaribio ya Juu ya Kufungua Uso yamezidishwa"</string>
     <string name="lockscreen_plugged_in" msgid="8057762828355572315">"Inachaji <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_charged" msgid="4938930459620989972">"Imechajiwa."</string>
-    <string name="lockscreen_battery_short" msgid="3617549178603354656">"Kishika nafasi<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
+    <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"Unganisha chaja yako"</string>
     <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"Hakuna SIM kadi."</string>
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Hakuna SIM kadi katika kompyuta ndogo."</string>
@@ -722,8 +720,8 @@
     <string name="password_keyboard_label_symbol_key" msgid="992280756256536042">"?123"</string>
     <string name="password_keyboard_label_alpha_key" msgid="8001096175167485649">"ABC"</string>
     <string name="password_keyboard_label_alt_key" msgid="1284820942620288678">"ALT"</string>
-    <string name="hour_ampm" msgid="4329881288269772723">"Kishika nafasi<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string>
-    <string name="hour_cap_ampm" msgid="1829009197680861107">"Kishika nafasi<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string>
+    <string name="hour_ampm" msgid="4584338083529355982">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string>
+    <string name="hour_cap_ampm" msgid="2083465992940444366">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string>
     <string name="factorytest_failed" msgid="5410270329114212041">"Jaribio la kiwanda limeshindikana"</string>
     <string name="factorytest_not_system" msgid="4435201656767276723">"Tendo la JARIBIO_LA KIWANDA  linahimiliwa tu kwa furushi zilizosakinishwa katika /system/app."</string>
     <string name="factorytest_no_action" msgid="872991874799998561">"Hakuna furushi lililopatikana ambalo linatoa tendo la JARIBIO_LA KIWANDA."</string>
@@ -735,7 +733,7 @@
     <string name="double_tap_toast" msgid="4595046515400268881">"Kidokezo: Gonga mara mbili ili kukuza ndani na nje."</string>
     <string name="autofill_this_form" msgid="4616758841157816676">"Mjazo-otomatiki"</string>
     <string name="setup_autofill" msgid="7103495070180590814">"Sanidi Mjazo-otomati"</string>
-    <string name="autofill_address_name_separator" msgid="2504700673286691795">" Kishika nafasi "</string>
+    <string name="autofill_address_name_separator" msgid="6350145154779706772">" "</string>
     <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string>
     <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string>
     <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
@@ -770,6 +768,8 @@
     <string name="permdesc_serialPort" msgid="2991639985224598193">"Inaruhusu mmiliki kufikia vituo tambulishi kwa kutumia KisimamiziTambulishi cha API."</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"fikia watoa huduma nje"</string>
     <string name="permdesc_accessContentProvidersExternally" msgid="4544346486697853685">"Inaruhusu mmiliki kufikia watoa huduma  kutoka kwa onyesho. Haifai kuhitajika kamwe kwa programu za kawaida."</string>
+    <string name="permlab_updateLock" msgid="3527558366616680889">"katisha tamaa usasishaji kifaa kiotomatiki"</string>
+    <string name="permdesc_updateLock" msgid="1655625832166778492">"Inaruhusu mmiliki kutoa maelezo kwa mfumo kuhusu ni lini itakuwa wakati mzuri wa uwashaji upya usiotagusana ili kuboresha kifaa."</string>
     <string name="save_password_message" msgid="767344687139195790">"Unataka kuvinjari ili ukumbuke nenosiri hili?"</string>
     <string name="save_password_notnow" msgid="6389675316706699758">"Si Sasa"</string>
     <string name="save_password_remember" msgid="6491879678996749466">"Kumbuka"</string>
@@ -1008,8 +1008,7 @@
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Weka tarehe"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Weka"</string>
     <string name="default_permission_group" msgid="2690160991405646128">"Chaguo-msingi"</string>
-    <!-- no translation found for perms_new_perm_prefix (8257740710754301407) -->
-    <skip />
+    <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ffffa3a3">" MPYA: "</font></string>
     <string name="no_permissions" msgid="7283357728219338112">"Hakuna vibali vinavyohitajika"</string>
     <string name="perms_hide" msgid="7283915391320676226"><b>"Ficha"</b></string>
     <string name="perms_show_all" msgid="2671791163933091180"><b>"Onyesha zote"</b></string>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index a787a2a..a9a196c 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -26,7 +26,7 @@
     <string name="gigabyteShort" msgid="3259882455212193214">"GB"</string>
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
-    <string name="fileSizeSuffix" msgid="7670819340156489359">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
     <string name="untitled" msgid="4638956954852782576">"&lt;ไม่มีชื่อ&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -671,7 +671,7 @@
     <string name="faceunlock_multiple_failures" msgid="754137583022792429">"มีความพยายามที่จะใช้ Face Unlock เกินขีดจำกัด"</string>
     <string name="lockscreen_plugged_in" msgid="8057762828355572315">"กำลังชาร์จ, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_charged" msgid="4938930459620989972">"ชาร์จแล้ว"</string>
-    <string name="lockscreen_battery_short" msgid="3617549178603354656">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
+    <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"เสียบที่ชาร์จของคุณ"</string>
     <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"ไม่มีซิมการ์ด"</string>
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"ไม่มีซิมการ์ดในแท็บเล็ต"</string>
@@ -720,8 +720,8 @@
     <string name="password_keyboard_label_symbol_key" msgid="992280756256536042">"?123"</string>
     <string name="password_keyboard_label_alpha_key" msgid="8001096175167485649">"ABC"</string>
     <string name="password_keyboard_label_alt_key" msgid="1284820942620288678">"ALT"</string>
-    <string name="hour_ampm" msgid="4329881288269772723">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string>
-    <string name="hour_cap_ampm" msgid="1829009197680861107">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string>
+    <string name="hour_ampm" msgid="4584338083529355982">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string>
+    <string name="hour_cap_ampm" msgid="2083465992940444366">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string>
     <string name="factorytest_failed" msgid="5410270329114212041">"การทดสอบจากโรงงานล้มเหลว"</string>
     <string name="factorytest_not_system" msgid="4435201656767276723">"การทำงาน FACTORY_TEST ได้รับการสนับสนุนเฉพาะสำหรับแพ็คเก็จที่ติดตั้งใน /system/app เท่านั้น"</string>
     <string name="factorytest_no_action" msgid="872991874799998561">"ไม่พบแพคเกจที่มีการทำงาน FACTORY_TEST"</string>
@@ -733,7 +733,7 @@
     <string name="double_tap_toast" msgid="4595046515400268881">"เคล็ดลับ: แตะสองครั้งเพื่อขยายและย่อ"</string>
     <string name="autofill_this_form" msgid="4616758841157816676">"ป้อนอัตโนมัติ"</string>
     <string name="setup_autofill" msgid="7103495070180590814">"ค่าป้อนอัตโนมัติ"</string>
-    <string name="autofill_address_name_separator" msgid="2504700673286691795">" "</string>
+    <string name="autofill_address_name_separator" msgid="6350145154779706772">" "</string>
     <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string>
     <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string>
     <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
@@ -768,6 +768,8 @@
     <string name="permdesc_serialPort" msgid="2991639985224598193">"อนุญาตให้ผู้ถือสามารถเข้าถึงพอร์ตอนุกรมโดยใช้ SerialManager API"</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"เข้าถึงผู้ให้บริการเนื้อหาจากภายนอก"</string>
     <string name="permdesc_accessContentProvidersExternally" msgid="4544346486697853685">"ช่วยให้เจ้าของสามารถเข้าถึงผู้ให้บริการเนื้อหาจากหน้าจอรับคำสั่งเชลล์ แอปพลิเคชันทั่วไปไม่จำเป็นต้องใช้"</string>
+    <string name="permlab_updateLock" msgid="3527558366616680889">"ป้องกันการอัปเดตอุปกรณ์อัตโนมัติ"</string>
+    <string name="permdesc_updateLock" msgid="1655625832166778492">"ช่วยให้เจ้าของแจ้งข้อมูลเกี่ยวกับเวลาที่เหมาะสมในการรีบูตแบบไม่โต้ตอบเพื่ออัปเกรดอุปกรณ์ไปยังระบบได้"</string>
     <string name="save_password_message" msgid="767344687139195790">"คุณต้องการให้เบราว์เซอร์จำรหัสผ่านนี้หรือไม่"</string>
     <string name="save_password_notnow" msgid="6389675316706699758">"ยังไม่ใช้งานขณะนี้"</string>
     <string name="save_password_remember" msgid="6491879678996749466">"จำไว้"</string>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index 99731af..2672083 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -26,7 +26,7 @@
     <string name="gigabyteShort" msgid="3259882455212193214">"GB"</string>
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
-    <string name="fileSizeSuffix" msgid="7670819340156489359">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
     <string name="untitled" msgid="4638956954852782576">"&lt;Walang pamagat&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -671,7 +671,7 @@
     <string name="faceunlock_multiple_failures" msgid="754137583022792429">"Nalagpasan na ang maximum na mga pagtatangka sa Face Unlock"</string>
     <string name="lockscreen_plugged_in" msgid="8057762828355572315">"Nagcha-charge, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_charged" msgid="4938930459620989972">"Naka-charge."</string>
-    <string name="lockscreen_battery_short" msgid="3617549178603354656">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
+    <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"Ikonekta ang iyong charger."</string>
     <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"Walang SIM card."</string>
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Walang SIM card sa tablet."</string>
@@ -720,8 +720,8 @@
     <string name="password_keyboard_label_symbol_key" msgid="992280756256536042">"?123"</string>
     <string name="password_keyboard_label_alpha_key" msgid="8001096175167485649">"ABC"</string>
     <string name="password_keyboard_label_alt_key" msgid="1284820942620288678">"ALT"</string>
-    <string name="hour_ampm" msgid="4329881288269772723">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string>
-    <string name="hour_cap_ampm" msgid="1829009197680861107">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string>
+    <string name="hour_ampm" msgid="4584338083529355982">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string>
+    <string name="hour_cap_ampm" msgid="2083465992940444366">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string>
     <string name="factorytest_failed" msgid="5410270329114212041">"Nabigo ang factory na pagsubok"</string>
     <string name="factorytest_not_system" msgid="4435201656767276723">"Suportado lang ang pagkilos na FACTORY_TEST para sa mga package na naka-install sa /system/app."</string>
     <string name="factorytest_no_action" msgid="872991874799998561">"Walang nakitang package na nagbibigay ng pagkilos na FACTORY_TEST."</string>
@@ -733,7 +733,7 @@
     <string name="double_tap_toast" msgid="4595046515400268881">"Tip: Mag-double tap upang mag-zoom in at out."</string>
     <string name="autofill_this_form" msgid="4616758841157816676">"Autofill"</string>
     <string name="setup_autofill" msgid="7103495070180590814">"I-set up ang Autofill."</string>
-    <string name="autofill_address_name_separator" msgid="2504700673286691795">" "</string>
+    <string name="autofill_address_name_separator" msgid="6350145154779706772">" "</string>
     <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string>
     <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string>
     <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
@@ -768,6 +768,8 @@
     <string name="permdesc_serialPort" msgid="2991639985224598193">"Binibigyang-daan ang may-ari na mag-access ng mga serial port gamit ang SerialManager API."</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"panlabas na mag-access ng mga provider ng nilalaman"</string>
     <string name="permdesc_accessContentProvidersExternally" msgid="4544346486697853685">"Binibigyang-daan ang may-ari na ma-access ang mga provider ng nilalaman mula sa shell. Hindi kailanman dapat kailanganin para sa karaniwang apps."</string>
+    <string name="permlab_updateLock" msgid="3527558366616680889">"wag payagan awtomatiko update ng device"</string>
+    <string name="permdesc_updateLock" msgid="1655625832166778492">"Pinapayagan ang may-hawak na mag-alok ng impormasyon sa system tungkol sa kung kailan ang magandang oras para sa hindi interactive na pag-reboot upang i-upgrade ang device."</string>
     <string name="save_password_message" msgid="767344687139195790">"Gusto mo bang tandaan ng browser ang password na ito?"</string>
     <string name="save_password_notnow" msgid="6389675316706699758">"Hindi ngayon"</string>
     <string name="save_password_remember" msgid="6491879678996749466">"Tandaan"</string>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index 730c69f..059ccea 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -26,7 +26,7 @@
     <string name="gigabyteShort" msgid="3259882455212193214">"GB"</string>
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
-    <string name="fileSizeSuffix" msgid="7670819340156489359">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
     <string name="untitled" msgid="4638956954852782576">"&lt;Adsız&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -313,10 +313,8 @@
     <string name="permlab_changeComponentState" msgid="6335576775711095931">"uygulama bileşenlerini etkinleştir veya devre dışı bırak"</string>
     <string name="permdesc_changeComponentState" product="tablet" msgid="8887435740982237294">"Uygulamaya, başka bir uygulamanın bir bileşeninin etkin veya devre dışı olma durumunu değiştirme izni verir. Kötü amaçlı uygulamalar tabletin önemli özelliklerini devre dışı bırakmak için bunu kullanabilir. Uygulama bileşenlerini kullanılamaz, tutarsız ya da kararsız hale getirebileceğinden bu izin ayarlanırken dikkat edilmelidir."</string>
     <string name="permdesc_changeComponentState" product="default" msgid="1827232484416505615">"Uygulamaya, başka bir uygulamanın bir bileşeninin etkin veya devre dışı olma durumunu değiştirme izni verir. Kötü amaçlı uygulamalar telefonun önemli özelliklerini devre dışı bırakmak için bunu kullanabilir. Uygulama bileşenlerini kullanılamaz, tutarsız ya da kararsız getirebileceğinden bu izin ayarlanırken dikkat edilmelidir."</string>
-    <!-- no translation found for permlab_grantRevokePermissions (4627315351093508795) -->
-    <skip />
-    <!-- no translation found for permdesc_grantRevokePermissions (4088642654085850662) -->
-    <skip />
+    <string name="permlab_grantRevokePermissions" msgid="4627315351093508795">"izinleri ver veya kaldır"</string>
+    <string name="permdesc_grantRevokePermissions" msgid="4088642654085850662">"Uygulamaya, kendisi veya başka uygulamalar için belirli izinleri verme ya da kaldırma izni verir. Zararlı uygulamalar bunu, kendilerine izin vermediğiniz özelliklere erişmek için kullanabilir."</string>
     <string name="permlab_setPreferredApplications" msgid="8463181628695396391">"tercih edilen uygulamaları ayarla"</string>
     <string name="permdesc_setPreferredApplications" msgid="4973986762241783712">"Uygulamaya, tercih edilen uygulamalarınızı değiştirme izni verir. Kötü amaçlı uygulamalar çalışmakta olan uygulamaları sessizce değiştirip gizli verilerinizi toplamak için mevcut uygulamalarınızı yanlış yönlendirebilir."</string>
     <string name="permlab_writeSettings" msgid="1365523497395143704">"genel sistem ayarlarını değiştir"</string>
@@ -673,7 +671,7 @@
     <string name="faceunlock_multiple_failures" msgid="754137583022792429">"Yüz Tanıma Kilidi için maksimum deneme sayısı aşıldı"</string>
     <string name="lockscreen_plugged_in" msgid="8057762828355572315">"Şarj oluyor (<xliff:g id="PERCENT">%%</xliff:g><xliff:g id="NUMBER">%d</xliff:g>)"</string>
     <string name="lockscreen_charged" msgid="4938930459620989972">"Şarj oldu."</string>
-    <string name="lockscreen_battery_short" msgid="3617549178603354656">"<xliff:g id="NUMBER">%d</xliff:g> <xliff:g id="PERCENT">%%</xliff:g>"</string>
+    <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="PERCENT">%%</xliff:g><xliff:g id="NUMBER">%d</xliff:g>"</string>
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"Şarj cihazınızı bağlayın."</string>
     <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"SIM kart yok."</string>
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Tablette SIM kart yok."</string>
@@ -722,8 +720,8 @@
     <string name="password_keyboard_label_symbol_key" msgid="992280756256536042">"?123"</string>
     <string name="password_keyboard_label_alpha_key" msgid="8001096175167485649">"ABC"</string>
     <string name="password_keyboard_label_alt_key" msgid="1284820942620288678">"ALT"</string>
-    <string name="hour_ampm" msgid="4329881288269772723">"<xliff:g id="HOUR">%-l</xliff:g> <xliff:g id="AMPM">%P</xliff:g>"</string>
-    <string name="hour_cap_ampm" msgid="1829009197680861107">"<xliff:g id="HOUR">%-l</xliff:g> <xliff:g id="AMPM">%p</xliff:g>"</string>
+    <string name="hour_ampm" msgid="4584338083529355982">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string>
+    <string name="hour_cap_ampm" msgid="2083465992940444366">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string>
     <string name="factorytest_failed" msgid="5410270329114212041">"Fabrika testi yapılamadı"</string>
     <string name="factorytest_not_system" msgid="4435201656767276723">"FACTORY_TEST işlemi yalnızca /system/app dizinine yüklenmiş paketler için desteklenir."</string>
     <string name="factorytest_no_action" msgid="872991874799998561">"FACTORY_TEST işlemini sağlayan hiçbir paket bulunamadı."</string>
@@ -735,7 +733,7 @@
     <string name="double_tap_toast" msgid="4595046515400268881">"İpucu: Yakınlaştırmak ve uzaklaştırmak için iki kez hafifçe vurun."</string>
     <string name="autofill_this_form" msgid="4616758841157816676">"Otomatik Doldur"</string>
     <string name="setup_autofill" msgid="7103495070180590814">"Otomatik doldurma ayarla"</string>
-    <string name="autofill_address_name_separator" msgid="2504700673286691795">" "</string>
+    <string name="autofill_address_name_separator" msgid="6350145154779706772">" "</string>
     <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string>
     <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string>
     <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
@@ -770,6 +768,8 @@
     <string name="permdesc_serialPort" msgid="2991639985224598193">"İzin sahibinin, SerialManager API\'sını kullanarak seri bağlantı noktalarına erişmesine olanak sağlar."</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"içerik sağlayıcılara harici olarak eriş"</string>
     <string name="permdesc_accessContentProvidersExternally" msgid="4544346486697853685">"İzin verilen uygulamaya, Uygulama İş Parçacığının dışından içerik sağlayıcılara erişebilme olanağı verir."</string>
+    <string name="permlab_updateLock" msgid="3527558366616680889">"otomatik cihaz güncellemelerinin yapılmasını engelle"</string>
+    <string name="permdesc_updateLock" msgid="1655625832166778492">"Cihazın yeni sürüme geçirilmesinde kesintisiz  yeniden başlatmanın ne zaman uygun olacağı bilgisinin sisteme teklif edilmesine izin verir."</string>
     <string name="save_password_message" msgid="767344687139195790">"Tarayıcının bu şifreyi anımsamasını istiyor musunuz?"</string>
     <string name="save_password_notnow" msgid="6389675316706699758">"Şimdi değil"</string>
     <string name="save_password_remember" msgid="6491879678996749466">"Anımsa"</string>
@@ -1008,8 +1008,7 @@
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Tarihi ayarla"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Ayarla"</string>
     <string name="default_permission_group" msgid="2690160991405646128">"Varsayılan"</string>
-    <!-- no translation found for perms_new_perm_prefix (8257740710754301407) -->
-    <skip />
+    <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ffffa3a3">"YENİ: "</font></string>
     <string name="no_permissions" msgid="7283357728219338112">"İzin gerektirmez"</string>
     <string name="perms_hide" msgid="7283915391320676226"><b>"Gizle"</b></string>
     <string name="perms_show_all" msgid="2671791163933091180"><b>"Tümünü göster"</b></string>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index 4d3c8537..42929ec 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -26,7 +26,7 @@
     <string name="gigabyteShort" msgid="3259882455212193214">"Гб"</string>
     <string name="terabyteShort" msgid="231613018159186962">"Тб"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"Пб"</string>
-    <string name="fileSizeSuffix" msgid="7670819340156489359">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
     <string name="untitled" msgid="4638956954852782576">"&lt;Без назви&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">".."</string>
@@ -671,7 +671,7 @@
     <string name="faceunlock_multiple_failures" msgid="754137583022792429">"Перевищено максимальну кількість спроб розблокування за допомогою функції \"Фейсконтроль\""</string>
     <string name="lockscreen_plugged_in" msgid="8057762828355572315">"Заряджається, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_charged" msgid="4938930459620989972">"Заряджено."</string>
-    <string name="lockscreen_battery_short" msgid="3617549178603354656">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
+    <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"Підкл. заряд. пристрій."</string>
     <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"Нема SIM-карти."</string>
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"У пристр. нема SIM-карти."</string>
@@ -720,8 +720,8 @@
     <string name="password_keyboard_label_symbol_key" msgid="992280756256536042">"?123"</string>
     <string name="password_keyboard_label_alpha_key" msgid="8001096175167485649">"ABC"</string>
     <string name="password_keyboard_label_alt_key" msgid="1284820942620288678">"ALT"</string>
-    <string name="hour_ampm" msgid="4329881288269772723">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string>
-    <string name="hour_cap_ampm" msgid="1829009197680861107">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string>
+    <string name="hour_ampm" msgid="4584338083529355982">"<xliff:g id="HOUR">%-l</xliff:g> <xliff:g id="AMPM">%P</xliff:g>"</string>
+    <string name="hour_cap_ampm" msgid="2083465992940444366">"<xliff:g id="HOUR">%-l</xliff:g> <xliff:g id="AMPM">%p</xliff:g>"</string>
     <string name="factorytest_failed" msgid="5410270329114212041">"Помилка завод. тесту"</string>
     <string name="factorytest_not_system" msgid="4435201656767276723">"Дія FACTORY_TEST підтримується лише для пакетів, установлених у /system/app."</string>
     <string name="factorytest_no_action" msgid="872991874799998561">"Не було знайдено жодного пакета, який надає дію FACTORY_TEST."</string>
@@ -733,7 +733,7 @@
     <string name="double_tap_toast" msgid="4595046515400268881">"Порада: двічі торкніться для збільшення чи зменшення."</string>
     <string name="autofill_this_form" msgid="4616758841157816676">"Автозап."</string>
     <string name="setup_autofill" msgid="7103495070180590814">"Налашт.автозап."</string>
-    <string name="autofill_address_name_separator" msgid="2504700673286691795">" "</string>
+    <string name="autofill_address_name_separator" msgid="6350145154779706772">" "</string>
     <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string>
     <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string>
     <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
@@ -768,6 +768,8 @@
     <string name="permdesc_serialPort" msgid="2991639985224598193">"Дозволяє власнику отримувати доступ до послідовних портів за допомогою API SerialManager."</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"отримув. ззовні доступ до постач. вмісту"</string>
     <string name="permdesc_accessContentProvidersExternally" msgid="4544346486697853685">"Дозволяє власнику отримувати ззовні доступ до постачальників вмісту. Ніколи не застосовується для звичайних програм."</string>
+    <string name="permlab_updateLock" msgid="3527558366616680889">"перешкоджати автом. оновленням пристрою"</string>
+    <string name="permdesc_updateLock" msgid="1655625832166778492">"Дозволяє власникові надавати системі інформацію про найкращий час для оновлення пристрою шляхом неінтерактивного перезавантаження."</string>
     <string name="save_password_message" msgid="767344687139195790">"Хочете, щоб переглядач запам\'ятав цей пароль?"</string>
     <string name="save_password_notnow" msgid="6389675316706699758">"Не зараз"</string>
     <string name="save_password_remember" msgid="6491879678996749466">"Запам\'ятати"</string>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index c9b200d..64469ab 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -26,7 +26,7 @@
     <string name="gigabyteShort" msgid="3259882455212193214">"GB"</string>
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
-    <string name="fileSizeSuffix" msgid="7670819340156489359">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
     <string name="untitled" msgid="4638956954852782576">"&lt;Không có tiêu đề&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -671,7 +671,7 @@
     <string name="faceunlock_multiple_failures" msgid="754137583022792429">"Đã vượt quá số lần Mở khóa bằng khuôn mặt tối đa"</string>
     <string name="lockscreen_plugged_in" msgid="8057762828355572315">"Đang sạc, <xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_charged" msgid="4938930459620989972">"Đã sạc."</string>
-    <string name="lockscreen_battery_short" msgid="3617549178603354656">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
+    <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"Kết nối bộ sạc của bạn."</string>
     <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"Không có thẻ SIM nào."</string>
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Không có thẻ SIM nào trong máy tính bảng."</string>
@@ -720,8 +720,8 @@
     <string name="password_keyboard_label_symbol_key" msgid="992280756256536042">"?123"</string>
     <string name="password_keyboard_label_alpha_key" msgid="8001096175167485649">"ABC"</string>
     <string name="password_keyboard_label_alt_key" msgid="1284820942620288678">"ALT"</string>
-    <string name="hour_ampm" msgid="4329881288269772723">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string>
-    <string name="hour_cap_ampm" msgid="1829009197680861107">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string>
+    <string name="hour_ampm" msgid="4584338083529355982">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string>
+    <string name="hour_cap_ampm" msgid="2083465992940444366">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string>
     <string name="factorytest_failed" msgid="5410270329114212041">"Thử nghiệm ban đầu không thành công"</string>
     <string name="factorytest_not_system" msgid="4435201656767276723">"Tác vụ FACTORY_TEST chỉ được hỗ trợ cho các gói được cài đặt trong /system/app."</string>
     <string name="factorytest_no_action" msgid="872991874799998561">"Không tìm thấy gói cung cấp tác vụ FACTORY_TEST."</string>
@@ -733,7 +733,7 @@
     <string name="double_tap_toast" msgid="4595046515400268881">"Mẹo: Nhấn đúp để phóng to và thu nhỏ."</string>
     <string name="autofill_this_form" msgid="4616758841157816676">"Tự động điền"</string>
     <string name="setup_autofill" msgid="7103495070180590814">"Thiết lập Tự động điền"</string>
-    <string name="autofill_address_name_separator" msgid="2504700673286691795">" "</string>
+    <string name="autofill_address_name_separator" msgid="6350145154779706772">" "</string>
     <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string>
     <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string>
     <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
@@ -768,6 +768,8 @@
     <string name="permdesc_serialPort" msgid="2991639985224598193">"Cho phép chủ sở hữu truy cập cổng nối tiếp sử dụng API SerialManager."</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"truy cập vào nhà cung cấp nội dung từ bên ngoài"</string>
     <string name="permdesc_accessContentProvidersExternally" msgid="4544346486697853685">"Cho phép chủ sở hữu truy cập vào nhà cung cấp nội dung từ bên ngoài. Không bao giờ cần cho ứng dụng thông thường."</string>
+    <string name="permlab_updateLock" msgid="3527558366616680889">"ko khuyến khích cập nhật th.bị tự động"</string>
+    <string name="permdesc_updateLock" msgid="1655625832166778492">"Cho phép chủ sở hữu cung cấp thông tin tới hệ thống về thời điểm thích hợp để khởi động lại không tương tác nhằm nâng cấp thiết bị."</string>
     <string name="save_password_message" msgid="767344687139195790">"Bạn có muốn trình duyệt nhớ mật khẩu này không?"</string>
     <string name="save_password_notnow" msgid="6389675316706699758">"Không phải bây giờ"</string>
     <string name="save_password_remember" msgid="6491879678996749466">"Nhớ"</string>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index c2d59e9..24b726d 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -26,7 +26,7 @@
     <string name="gigabyteShort" msgid="3259882455212193214">"GB"</string>
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
-    <string name="fileSizeSuffix" msgid="7670819340156489359">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
     <string name="untitled" msgid="4638956954852782576">"&lt;未命名&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"..."</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -313,10 +313,8 @@
     <string name="permlab_changeComponentState" msgid="6335576775711095931">"启用或停用应用程序组件"</string>
     <string name="permdesc_changeComponentState" product="tablet" msgid="8887435740982237294">"允许应用程序启用或停用其他应用程序的组件。恶意应用程序可能借此停用重要的平板电脑功能。请务必谨慎使用此权限,因为这可能导致某些应用程序组件处于无法使用、不一致或不稳定的状态。"</string>
     <string name="permdesc_changeComponentState" product="default" msgid="1827232484416505615">"允许应用程序启用或停用其他应用程序的组件。恶意应用程序可能借此停用重要的手机功能。请务必谨慎使用此权限,因为这可能导致某些应用程序组件进入无法使用、不一致或不稳定的状态。"</string>
-    <!-- no translation found for permlab_grantRevokePermissions (4627315351093508795) -->
-    <skip />
-    <!-- no translation found for permdesc_grantRevokePermissions (4088642654085850662) -->
-    <skip />
+    <string name="permlab_grantRevokePermissions" msgid="4627315351093508795">"授予或撤消权限"</string>
+    <string name="permdesc_grantRevokePermissions" msgid="4088642654085850662">"允许应用针对自身或其他应用授予或撤消特定权限。恶意应用可能会借此访问您未授权它们访问的功能。"</string>
     <string name="permlab_setPreferredApplications" msgid="8463181628695396391">"设置首选应用程序"</string>
     <string name="permdesc_setPreferredApplications" msgid="4973986762241783712">"允许应用程序修改您的首选应用程序。恶意应用程序可能会在后台更改运行的应用程序,欺骗您现有的应用程序,以收集您的私人数据。"</string>
     <string name="permlab_writeSettings" msgid="1365523497395143704">"修改全局系统设置"</string>
@@ -673,7 +671,7 @@
     <string name="faceunlock_multiple_failures" msgid="754137583022792429">"已超过“人脸解锁”尝试次数上限"</string>
     <string name="lockscreen_plugged_in" msgid="8057762828355572315">"正在充电,<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_charged" msgid="4938930459620989972">"已充满。"</string>
-    <string name="lockscreen_battery_short" msgid="3617549178603354656">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
+    <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"连接您的充电器。"</string>
     <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"没有 SIM 卡"</string>
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"平板电脑中没有 SIM 卡。"</string>
@@ -722,8 +720,8 @@
     <string name="password_keyboard_label_symbol_key" msgid="992280756256536042">"?123"</string>
     <string name="password_keyboard_label_alpha_key" msgid="8001096175167485649">"ABC"</string>
     <string name="password_keyboard_label_alt_key" msgid="1284820942620288678">"ALT"</string>
-    <string name="hour_ampm" msgid="4329881288269772723">"<xliff:g id="AMPM">%P</xliff:g><xliff:g id="HOUR">%-l</xliff:g>点"</string>
-    <string name="hour_cap_ampm" msgid="1829009197680861107">"<xliff:g id="AMPM">%p</xliff:g><xliff:g id="HOUR">%-l</xliff:g>点"</string>
+    <string name="hour_ampm" msgid="4584338083529355982">"<xliff:g id="AMPM">%P</xliff:g> <xliff:g id="HOUR">%-l</xliff:g>"</string>
+    <string name="hour_cap_ampm" msgid="2083465992940444366">"<xliff:g id="AMPM">%p</xliff:g> <xliff:g id="HOUR">%-l</xliff:g>"</string>
     <string name="factorytest_failed" msgid="5410270329114212041">"出厂测试失败"</string>
     <string name="factorytest_not_system" msgid="4435201656767276723">"只有在 /system/app 中安装的包支持 FACTORY_TEST 操作。"</string>
     <string name="factorytest_no_action" msgid="872991874799998561">"未发现支持 FACTORY_TEST 操作的包。"</string>
@@ -735,7 +733,7 @@
     <string name="double_tap_toast" msgid="4595046515400268881">"提示:点按两次可放大或缩小。"</string>
     <string name="autofill_this_form" msgid="4616758841157816676">"自动填充"</string>
     <string name="setup_autofill" msgid="7103495070180590814">"设置自动填充"</string>
-    <string name="autofill_address_name_separator" msgid="2504700673286691795">" "</string>
+    <string name="autofill_address_name_separator" msgid="6350145154779706772">" "</string>
     <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string>
     <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string>
     <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
@@ -770,6 +768,8 @@
     <string name="permdesc_serialPort" msgid="2991639985224598193">"允许持有人使用 SerialManager API 访问串行端口。"</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"从外部访问内容提供程序"</string>
     <string name="permdesc_accessContentProvidersExternally" msgid="4544346486697853685">"允许持有者通过界面访问内容提供程序。普通应用绝不需要此权限。"</string>
+    <string name="permlab_updateLock" msgid="3527558366616680889">"阻止自动设备更新"</string>
+    <string name="permdesc_updateLock" msgid="1655625832166778492">"允许持有人向系统提供相关信息,以确定什么时候适合执行非交互式重新启动来升级设备。"</string>
     <string name="save_password_message" msgid="767344687139195790">"是否希望浏览器记住此密码?"</string>
     <string name="save_password_notnow" msgid="6389675316706699758">"暂不保存"</string>
     <string name="save_password_remember" msgid="6491879678996749466">"记住"</string>
@@ -1008,8 +1008,7 @@
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"设置日期"</string>
     <string name="date_time_set" msgid="5777075614321087758">"设置"</string>
     <string name="default_permission_group" msgid="2690160991405646128">"默认"</string>
-    <!-- no translation found for perms_new_perm_prefix (8257740710754301407) -->
-    <skip />
+    <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ffffa3a3">"新增:"</font></string>
     <string name="no_permissions" msgid="7283357728219338112">"不需要任何权限"</string>
     <string name="perms_hide" msgid="7283915391320676226"><b>"隐藏"</b></string>
     <string name="perms_show_all" msgid="2671791163933091180"><b>"全部显示"</b></string>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 18d0836..7c8617e 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -26,7 +26,7 @@
     <string name="gigabyteShort" msgid="3259882455212193214">"GB"</string>
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
-    <string name="fileSizeSuffix" msgid="7670819340156489359">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
     <string name="untitled" msgid="4638956954852782576">"&lt;未命名&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"..."</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -313,10 +313,8 @@
     <string name="permlab_changeComponentState" msgid="6335576775711095931">"啟用或停用應用程式元件"</string>
     <string name="permdesc_changeComponentState" product="tablet" msgid="8887435740982237294">"允許應用程式啟用或停用其他應用程式的元件。請注意,惡意應用程式可能利用此功能停用重要的平板電腦功能。這項權限可能導致應用程式元件無法使用、不一致或不穩定,請務必謹慎使用。"</string>
     <string name="permdesc_changeComponentState" product="default" msgid="1827232484416505615">"允許應用程式啟用或停用其他應用程式的元件。請注意,惡意應用程式可能利用此功能停用重要的手機功能。這項權限可能導致應用程式元件無法使用、不一致或不穩定,請務必謹慎使用。"</string>
-    <!-- no translation found for permlab_grantRevokePermissions (4627315351093508795) -->
-    <skip />
-    <!-- no translation found for permdesc_grantRevokePermissions (4088642654085850662) -->
-    <skip />
+    <string name="permlab_grantRevokePermissions" msgid="4627315351093508795">"授予或撤銷權限"</string>
+    <string name="permdesc_grantRevokePermissions" msgid="4088642654085850662">"允許應用程式授予或撤銷本身或其他應用程式的特定權限。注意,惡意應用程式可能藉此存取您未授予權限的功能。"</string>
     <string name="permlab_setPreferredApplications" msgid="8463181628695396391">"設定偏好的應用程式"</string>
     <string name="permdesc_setPreferredApplications" msgid="4973986762241783712">"允許應用程式修改您偏好的應用程式。請注意,惡意應用程式可能利用此功能擅自竄改執行的應用程式,並冒充現有的程式收集您的私人資料。"</string>
     <string name="permlab_writeSettings" msgid="1365523497395143704">"編輯全域系統設定"</string>
@@ -673,7 +671,7 @@
     <string name="faceunlock_multiple_failures" msgid="754137583022792429">"已超過人臉解鎖嘗試次數上限"</string>
     <string name="lockscreen_plugged_in" msgid="8057762828355572315">"充電中 (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string>
     <string name="lockscreen_charged" msgid="4938930459620989972">"充電完成。"</string>
-    <string name="lockscreen_battery_short" msgid="3617549178603354656">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
+    <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"請連接充電器。"</string>
     <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"沒有 SIM  卡。"</string>
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"平板電腦中沒有 SIM 卡。"</string>
@@ -722,8 +720,8 @@
     <string name="password_keyboard_label_symbol_key" msgid="992280756256536042">"?123"</string>
     <string name="password_keyboard_label_alpha_key" msgid="8001096175167485649">"ABC"</string>
     <string name="password_keyboard_label_alt_key" msgid="1284820942620288678">"ALT"</string>
-    <string name="hour_ampm" msgid="4329881288269772723">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string>
-    <string name="hour_cap_ampm" msgid="1829009197680861107">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string>
+    <string name="hour_ampm" msgid="4584338083529355982">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string>
+    <string name="hour_cap_ampm" msgid="2083465992940444366">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string>
     <string name="factorytest_failed" msgid="5410270329114212041">"出廠測試失敗"</string>
     <string name="factorytest_not_system" msgid="4435201656767276723">"只有安裝在 /system/app 裡的程式才能支援 FACTORY_TEST 操作。"</string>
     <string name="factorytest_no_action" msgid="872991874799998561">"找不到提供 FACTORY_TEST 的程式。"</string>
@@ -735,7 +733,8 @@
     <string name="double_tap_toast" msgid="4595046515400268881">"提示:輕按兩下即可縮放。"</string>
     <string name="autofill_this_form" msgid="4616758841157816676">"自動填入功能"</string>
     <string name="setup_autofill" msgid="7103495070180590814">"設定自動填入功能"</string>
-    <string name="autofill_address_name_separator" msgid="2504700673286691795">" "</string>
+    <!-- no translation found for autofill_address_name_separator (6350145154779706772) -->
+    <skip />
     <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string>
     <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string>
     <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
@@ -770,6 +769,8 @@
     <string name="permdesc_serialPort" msgid="2991639985224598193">"允許應用程式使用 SerialManager API 存取序列埠。"</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"從外部存取內容供應端"</string>
     <string name="permdesc_accessContentProvidersExternally" msgid="4544346486697853685">"允許應用程式透過文字指令介面存取內容供應端 (一般應用程式不需這項權限)。"</string>
+    <string name="permlab_updateLock" msgid="3527558366616680889">"不建議自動更新裝置"</string>
+    <string name="permdesc_updateLock" msgid="1655625832166778492">"允許應用程式提供資訊,建議系統何時適合透過非互動方式重新啟動並升級裝置。"</string>
     <string name="save_password_message" msgid="767344687139195790">"是否記住此密碼?"</string>
     <string name="save_password_notnow" msgid="6389675316706699758">"現在不要"</string>
     <string name="save_password_remember" msgid="6491879678996749466">"記住"</string>
@@ -1008,8 +1009,7 @@
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"日期設定"</string>
     <string name="date_time_set" msgid="5777075614321087758">"設定"</string>
     <string name="default_permission_group" msgid="2690160991405646128">"預設值"</string>
-    <!-- no translation found for perms_new_perm_prefix (8257740710754301407) -->
-    <skip />
+    <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ffffa3a3">"新增:"</font></string>
     <string name="no_permissions" msgid="7283357728219338112">"無須許可"</string>
     <string name="perms_hide" msgid="7283915391320676226"><b>" 隱藏"</b></string>
     <string name="perms_show_all" msgid="2671791163933091180"><b>"顯示全部"</b></string>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index 6d61260..09777ab 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -26,7 +26,7 @@
     <string name="gigabyteShort" msgid="3259882455212193214">"GB"</string>
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
-    <string name="fileSizeSuffix" msgid="7670819340156489359">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
     <string name="untitled" msgid="4638956954852782576">"&lt;Akunasihloko&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"..."</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -314,7 +314,7 @@
     <string name="permdesc_changeComponentState" product="tablet" msgid="8887435740982237294">"Ivumela ukuthi insiza iguqule ukuthi okuqukethwe kwenye insiza kuyasebenza noma cha. Izinsiza ezinobungozi zingasebenzisa lokhu ukwenza ukuthi izinto ezisemqoka ekhompyutheni yepeni zingasebenzi. Kufanele kuqashelwe uma kukhishwa lemvume njengoba kungenzeka kwenze izinto zensiza zibe sesimweni esingazinzile, nesiguquguqukayo."</string>
     <string name="permdesc_changeComponentState" product="default" msgid="1827232484416505615">"Ivumela ukuthi insiza iguqule ukuthi okuqukethwe kwenye insiza kuyasebenza noma cha. Izinsiza ezinobungozi zingasebenzisa lokhu ukwenza ukuthi izinto ezisemqoka ocingweni zingasebenzi. Kufanele kuqashelwe uma kukhishwa lemvume njengoba kungenzeka kwenze izinto zensiza zibe sesmweni esingazinzile, nesiguquguqukayo."</string>
     <string name="permlab_grantRevokePermissions" msgid="4627315351093508795">"nika noma buyisa izimvume"</string>
-    <string name="permdesc_grantRevokePermissions" msgid="4088642654085850662">"Ivumela izinhlelo zokusebenza ukunika noma ukubuyisa izimvume ezithile zayo noma ezinye izinhlelo lokusebenza. Izinhlelo zokusebenza ezingalungile zingasebenzisa lokhu ukufinyelela izici ongazinikanga zona."</string>
+    <string name="permdesc_grantRevokePermissions" msgid="4088642654085850662">"Ivumela izinhlelo zokusebenza ukunika noma ukubuyisa izimvume ezithile zayo noma ezinye izinhlelo zokusebenza. Izinhlelo zokusebenza ezingalungile zingasebenzisa lokhu ukufinyelela izici ongazinikanga zona."</string>
     <string name="permlab_setPreferredApplications" msgid="8463181628695396391">"setha izinsiza ezincamelwayo"</string>
     <string name="permdesc_setPreferredApplications" msgid="4973986762241783712">"Ivuela insiza ukuthi iguqule izinsiza ezincanyelwayo. Izinsiza ezinobungozi zingashintsha izinsiz buthule ezisebenzyo okwenza ukuthi izinsiza zakho ezikhona zingasebenzi ukuthola ze zithole imininingwane yakho eyimfihlo."</string>
     <string name="permlab_writeSettings" msgid="1365523497395143704">"guqula izilungiselelo zohlelo jikelele"</string>
@@ -671,7 +671,7 @@
     <string name="faceunlock_multiple_failures" msgid="754137583022792429">"Ukuzama Kokuvula Ubuso Okuningi kudluliwe"</string>
     <string name="lockscreen_plugged_in" msgid="8057762828355572315">"Iyashaja (<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>)"</string>
     <string name="lockscreen_charged" msgid="4938930459620989972">"Kushajiwe."</string>
-    <string name="lockscreen_battery_short" msgid="3617549178603354656">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
+    <string name="lockscreen_battery_short" msgid="4477264849386850266">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
     <string name="lockscreen_low_battery" msgid="1482873981919249740">"Xhuma ishaja yakho."</string>
     <string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"Alikho ikhadi le-SIM."</string>
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"Alikho ikhadi le-SIM efonini."</string>
@@ -720,8 +720,8 @@
     <string name="password_keyboard_label_symbol_key" msgid="992280756256536042">"?123"</string>
     <string name="password_keyboard_label_alpha_key" msgid="8001096175167485649">"ABC"</string>
     <string name="password_keyboard_label_alt_key" msgid="1284820942620288678">"ALT"</string>
-    <string name="hour_ampm" msgid="4329881288269772723">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string>
-    <string name="hour_cap_ampm" msgid="1829009197680861107">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string>
+    <string name="hour_ampm" msgid="4584338083529355982">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string>
+    <string name="hour_cap_ampm" msgid="2083465992940444366">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string>
     <string name="factorytest_failed" msgid="5410270329114212041">"Ukuhlola kwemboni kwehlulekile"</string>
     <string name="factorytest_not_system" msgid="4435201656767276723">"Isenzo SOKUHLOLA_KWASEMBONINI sisekelwa kuphela amaphakheji afakwe kwisistimu/uhlelokusebenza."</string>
     <string name="factorytest_no_action" msgid="872991874799998561">"Ayikho iphakheji etholakele enikeze isenzo SOKUHLOLA KWASEMBONINI."</string>
@@ -733,7 +733,7 @@
     <string name="double_tap_toast" msgid="4595046515400268881">"Ithiphu: thepha kabili ukusondeza ngaphandle nangaphakathi."</string>
     <string name="autofill_this_form" msgid="4616758841157816676">"Ukugcwalisa Ngokuzenzakalelayo"</string>
     <string name="setup_autofill" msgid="7103495070180590814">"Misa i-Autofill"</string>
-    <string name="autofill_address_name_separator" msgid="2504700673286691795">" "</string>
+    <string name="autofill_address_name_separator" msgid="6350145154779706772">" "</string>
     <string name="autofill_address_summary_name_format" msgid="3268041054899214945">"$1$2$3"</string>
     <string name="autofill_address_summary_separator" msgid="7483307893170324129">", "</string>
     <string name="autofill_address_summary_format" msgid="4874459455786827344">"$1$2$3"</string>
@@ -768,6 +768,8 @@
     <string name="permdesc_serialPort" msgid="2991639985224598193">"Ivumela umnikai ukuthi athole inombolo ye-serial ukue angene kwiindawo ze-serial esebenzisa i-SerialManager API."</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"finyelela abahlinzeki bokuqukethwe ngaphandle"</string>
     <string name="permdesc_accessContentProvidersExternally" msgid="4544346486697853685">"Ivumela umphathi ukufinyelela abahlinzeki bokuqukethwe kusuka kumasistimu asebenzayo. Akusoze kwadingeka kwizinhlelo zokusebenza ezivamile."</string>
+    <string name="permlab_updateLock" msgid="3527558366616680889">"gxeka izibuyekezo zedivayisi zokuzenzakalela"</string>
+    <string name="permdesc_updateLock" msgid="1655625832166778492">"Ivumela umphathi ukunikela ngolwazi ohlelweni mayela nokuthi kuzoba nini isikhathi esilungile sokuqalisa kabusha okungenakuxoxisana ukuze kuthuthukiswe idivayisi."</string>
     <string name="save_password_message" msgid="767344687139195790">"Ingabe ufuna ukuba isiphequluli sikhumbule lephasiwedi?"</string>
     <string name="save_password_notnow" msgid="6389675316706699758">"Hha yi manje"</string>
     <string name="save_password_remember" msgid="6491879678996749466">"Khumbula"</string>
@@ -1006,7 +1008,7 @@
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Setha idethi"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Hlela"</string>
     <string name="default_permission_group" msgid="2690160991405646128">"Okuzenzakalelayo"</string>
-    <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ffffa3a3">"Okusha: "</font></string>
+    <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ffffa3a3">"OKUSHA: "</font></string>
     <string name="no_permissions" msgid="7283357728219338112">"Ayikho imvume edingekayo"</string>
     <string name="perms_hide" msgid="7283915391320676226"><b>"Fihla "</b></string>
     <string name="perms_show_all" msgid="2671791163933091180"><b>"Bonisa konke"</b></string>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 9375730..db908ca 100755
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -2864,7 +2864,8 @@
         <attr name="minHeight" format="dimension" />
         <attr name="maxHeight" />
         <attr name="interpolator" format="reference" />
-        <!-- Timeout between frames of animation in milliseconds -->
+        <!-- Timeout between frames of animation in milliseconds
+             {@deprecated Not used by the framework.} -->
         <attr name="animationResolution" format="integer" />
     </declare-styleable>
 
@@ -3376,9 +3377,13 @@
     </declare-styleable>
 
     <declare-styleable name="DatePicker">
-        <!-- The first year (inclusive), for example "1940". -->
+        <!-- The first year (inclusive), for example "1940".
+             {@deprecated Use minDate instead.}
+         -->
         <attr name="startYear" format="integer" />
-        <!-- The last year (inclusive), for example "2010". -->
+        <!-- The last year (inclusive), for example "2010".
+             {@deprecated Use maxDate instead.}
+         -->
         <attr name="endYear" format="integer" />
         <!-- Whether the spinners are shown. -->
         <attr name="spinnersShown" format="boolean" />
@@ -3388,8 +3393,8 @@
         <attr name="minDate" format="string" />
         <!-- The minimal date shown by this calendar view in mm/dd/yyyy format. -->
         <attr name="maxDate" format="string" />
-        <!-- @hide The layout of the time picker. -->
-        <attr name="layout" />
+        <!-- @hide The layout of the date picker. -->
+        <attr name="internalLayout" format="reference"  />
     </declare-styleable>
 
     <declare-styleable name="TwoLineListItem">
@@ -3593,15 +3598,15 @@
         <attr name="shownWeekCount" format="integer"/>
         <!-- The background color for the selected week. -->
         <attr name="selectedWeekBackgroundColor" format="color|reference" />
-        <!-- The color for the dates of the selected month. -->
+        <!-- The color for the dates of the focused month. -->
         <attr name="focusedMonthDateColor" format="color|reference" />
         <!-- The color for the dates of an unfocused month. -->
         <attr name="unfocusedMonthDateColor" format="color|reference" />
         <!-- The color for the week numbers. -->
         <attr name="weekNumberColor" format="color|reference" />
-        <!-- The color for the sepatator line between weeks. -->
+        <!-- The color for the separator line between weeks. -->
         <attr name="weekSeparatorLineColor" format="color|reference" />
-        <!-- Drawable for the vertical bar shown at the beggining and at the end of a selected date. -->
+        <!-- Drawable for the vertical bar shown at the beginning and at the end of the selected date. -->
         <attr name="selectedDateVerticalBar" format="reference" />
         <!-- The text appearance for the week day abbreviation of the calendar header. -->
         <attr name="weekDayTextAppearance" format="reference" />
@@ -3619,20 +3624,18 @@
         <!-- @hide The height of the selection divider. -->
         <attr name="selectionDividerHeight" format="dimension" />
         <!-- @hide The min height of the NumberPicker. -->
-        <attr name="minHeight" />
+        <attr name="internalMinHeight" format="dimension" />
         <!-- @hide The max height of the NumberPicker. -->
-        <attr name="maxHeight" />
+        <attr name="internalMaxHeight" format="dimension" />
         <!-- @hide The min width of the NumberPicker. -->
-        <attr name="minWidth" />
+        <attr name="internalMinWidth" format="dimension" />
         <!-- @hide The max width of the NumberPicker. -->
-        <attr name="maxWidth" />
-        <!-- @hide The max width of the NumberPicker. -->
-        <attr name="maxWidth" />
+        <attr name="internalMaxWidth" format="dimension" />
     </declare-styleable>
 
     <declare-styleable name="TimePicker">
         <!-- @hide The layout of the time picker. -->
-        <attr name="layout" />
+        <attr name="internalLayout" />
     </declare-styleable>
 
     <!-- ========================= -->
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 8e5b509..49f2823 100755
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -18,7 +18,7 @@
 -->
 
 <!-- These resources are around just to allow their values to be customized
-     for different hardware and product builds. -->
+     for different hardware and product builds.  Do not translate. -->
 <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <!-- Do not translate. Defines the slots for the right-hand side icons.  That is to say, the
          icons in the status bar that are not notifications. -->
@@ -654,20 +654,37 @@
          PERSIST may improve performance by reducing how often journal blocks are
          reallocated (compared to truncation) resulting in better data block locality
          and less churn of the storage media. -->
-    <string name="db_default_journal_mode">TRUNCATE</string>
+    <string name="db_default_journal_mode">PERSIST</string>
 
     <!-- Maximum size of the persistent journal file in bytes.
          If the journal file grows to be larger than this amount then SQLite will
          truncate it after committing the transaction. -->
     <integer name="db_journal_size_limit">524288</integer>
 
-    <!-- The database synchronization mode.
+    <!-- The database synchronization mode when using the default journal mode.
+         FULL is safest and preserves durability at the cost of extra fsyncs.
+         NORMAL also preserves durability in non-WAL modes and uses checksums to ensure
+         integrity although there is a small chance that an error might go unnoticed.
          Choices are: FULL, NORMAL, OFF. -->
-    <string name="db_sync_mode">FULL</string>
+    <string name="db_default_sync_mode">FULL</string>
 
-    <!-- The Write-Ahead Log auto-checkpoint interval in database pages.
-         The log is checkpointed automatically whenever it exceeds this many pages. -->
-    <integer name="db_wal_autocheckpoint">1</integer>
+    <!-- The database synchronization mode when using Write-Ahead Logging.
+         FULL is safest and preserves durability at the cost of extra fsyncs.
+         NORMAL sacrifices durability in WAL mode because syncs are only performed before
+         and after checkpoint operations.  If checkpoints are infrequent and power loss
+         occurs, then committed transactions could be lost and applications might break.
+         Choices are: FULL, NORMAL, OFF. -->
+    <string name="db_wal_sync_mode">FULL</string>
+
+    <!-- The Write-Ahead Log auto-checkpoint interval in database pages (typically 1 to 4KB).
+         The log is checkpointed automatically whenever it exceeds this many pages.
+         When a database is reopened, its journal mode is set back to the default
+         journal mode, which may cause a checkpoint operation to occur.  Checkpoints
+         can also happen at other times when transactions are committed.
+         The bigger the WAL file, the longer a checkpoint operation takes, so we try
+         to keep the WAL file relatively small to avoid long delays.
+         The size of the WAL file is also constrained by 'db_journal_size_limit'. -->
+    <integer name="db_wal_autocheckpoint">100</integer>
 
     <!-- Max space (in MB) allocated to DownloadManager to store the downloaded
          files if they are to be stored in DownloadManager's data dir,
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 2c80fb7..a089021 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -88,7 +88,6 @@
   <java-symbol type="id" name="hour" />
   <java-symbol type="id" name="icon" />
   <java-symbol type="id" name="image" />
-  <java-symbol type="id" name="imageButton" />
   <java-symbol type="id" name="increment" />
   <java-symbol type="id" name="internalEmpty" />
   <java-symbol type="id" name="info" />
@@ -173,7 +172,6 @@
   <java-symbol type="id" name="switch_old" />
   <java-symbol type="id" name="switchWidget" />
   <java-symbol type="id" name="text" />
-  <java-symbol type="id" name="textButton" />
   <java-symbol type="id" name="time" />
   <java-symbol type="id" name="time_current" />
   <java-symbol type="id" name="timeDisplayBackground" />
@@ -441,7 +439,8 @@
   <java-symbol type="string" name="day_of_week_shortest_tuesday" />
   <java-symbol type="string" name="day_of_week_shortest_wednesday" />
   <java-symbol type="string" name="db_default_journal_mode" />
-  <java-symbol type="string" name="db_sync_mode" />
+  <java-symbol type="string" name="db_default_sync_mode" />
+  <java-symbol type="string" name="db_wal_sync_mode" />
   <java-symbol type="string" name="decline" />
   <java-symbol type="string" name="default_permission_group" />
   <java-symbol type="string" name="default_text_encoding" />
@@ -1281,16 +1280,22 @@
   <!-- From services -->
   <java-symbol type="anim" name="screen_rotate_0_enter" />
   <java-symbol type="anim" name="screen_rotate_0_exit" />
+  <java-symbol type="anim" name="screen_rotate_0_frame" />
   <java-symbol type="anim" name="screen_rotate_180_enter" />
   <java-symbol type="anim" name="screen_rotate_180_exit" />
+  <java-symbol type="anim" name="screen_rotate_180_frame" />
   <java-symbol type="anim" name="screen_rotate_finish_enter" />
   <java-symbol type="anim" name="screen_rotate_finish_exit" />
+  <java-symbol type="anim" name="screen_rotate_finish_frame" />
   <java-symbol type="anim" name="screen_rotate_minus_90_enter" />
   <java-symbol type="anim" name="screen_rotate_minus_90_exit" />
+  <java-symbol type="anim" name="screen_rotate_minus_90_frame" />
   <java-symbol type="anim" name="screen_rotate_plus_90_enter" />
   <java-symbol type="anim" name="screen_rotate_plus_90_exit" />
+  <java-symbol type="anim" name="screen_rotate_plus_90_frame" />
   <java-symbol type="anim" name="screen_rotate_start_enter" />
   <java-symbol type="anim" name="screen_rotate_start_exit" />
+  <java-symbol type="anim" name="screen_rotate_start_frame" />
   <java-symbol type="anim" name="window_move_from_decor" />
   <java-symbol type="array" name="config_autoBrightnessButtonBacklightValues" />
   <java-symbol type="array" name="config_autoBrightnessKeyboardBacklightValues" />
@@ -1954,7 +1959,9 @@
   <public type="attr" name="flipInterval" id="0x01010179" />
   <public type="attr" name="fillViewport" id="0x0101017a" />
   <public type="attr" name="prompt" id="0x0101017b" />
+  <!-- {@deprecated Use minDate instead.} -->
   <public type="attr" name="startYear" id="0x0101017c" />
+  <!-- {@deprecated Use maxDate instead.} -->
   <public type="attr" name="endYear" id="0x0101017d" />
   <public type="attr" name="mode" id="0x0101017e" />
   <public type="attr" name="layout_x" id="0x0101017f" />
@@ -2904,6 +2911,7 @@
   <public type="attr" name="windowEnableSplitTouch" id="0x01010317" />
   <public type="attr" name="indeterminateProgressStyle" id="0x01010318" />
   <public type="attr" name="progressBarPadding" id="0x01010319" />
+  <!-- @deprecated Not used by the framework. -->
   <public type="attr" name="animationResolution" id="0x0101031a" />
   <public type="attr" name="state_accelerated" id="0x0101031b" />
   <public type="attr" name="baseline" id="0x0101031c" />
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index 610bad8..a51f3f9 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -528,11 +528,11 @@
     </style>
 
     <style name="Widget.TimePicker">
-        <item name="android:layout">@android:layout/time_picker</item>
+        <item name="android:internalLayout">@android:layout/time_picker</item>
     </style>
 
     <style name="Widget.DatePicker">
-        <item name="android:layout">@android:layout/date_picker</item>
+        <item name="android:internalLayout">@android:layout/date_picker</item>
         <item name="android:calendarViewShown">false</item>
     </style>
 
@@ -826,6 +826,10 @@
 
     <style name="TextAppearance.Widget.IconMenu.Item" parent="TextAppearance.Small">
         <item name="android:textColor">?textColorPrimary</item>
+        <!-- dp is used on purpose here instead of sp; there is not space
+             for larger font sizes based on the user setting. Newer apps
+             should not receive the legacy icon menu panel. -->
+        <item name="android:textSize">14dp</item>
     </style>
 
     <style name="TextAppearance.Widget.EditText">
@@ -1656,16 +1660,16 @@
         <item name="android:flingable">true</item>
         <item name="android:selectionDivider">@android:drawable/numberpicker_selection_divider</item>
         <item name="android:selectionDividerHeight">2dip</item>
-        <item name="android:minWidth">48dip</item>
-        <item name="android:maxHeight">200dip</item>
+        <item name="android:internalMinWidth">48dip</item>
+        <item name="android:internalMaxHeight">200dip</item>
     </style>
 
     <style name="Widget.Holo.TimePicker" parent="Widget.TimePicker">
-        <item name="android:layout">@android:layout/time_picker_holo</item>
+        <item name="android:internalLayout">@android:layout/time_picker_holo</item>
     </style>
 
     <style name="Widget.Holo.DatePicker" parent="Widget.DatePicker">
-        <item name="android:layout">@android:layout/date_picker_holo</item>
+        <item name="android:internalLayout">@android:layout/date_picker_holo</item>
         <item name="android:calendarViewShown">true</item>
     </style>
 
@@ -1718,7 +1722,6 @@
 
     <style name="Widget.Holo.ProgressBar" parent="Widget.ProgressBar">
         <item name="android:indeterminateDrawable">@android:drawable/progress_medium_holo</item>
-        <item name="android:animationResolution">33</item>
     </style>
 
     <style name="Widget.Holo.ProgressBar.Horizontal" parent="Widget.ProgressBar.Horizontal">
@@ -1730,7 +1733,6 @@
 
     <style name="Widget.Holo.ProgressBar.Small" parent="Widget.ProgressBar.Small">
         <item name="android:indeterminateDrawable">@android:drawable/progress_small_holo</item>
-        <item name="android:animationResolution">33</item>
     </style>
 
     <style name="Widget.Holo.ProgressBar.Small.Title">
@@ -1738,7 +1740,6 @@
 
     <style name="Widget.Holo.ProgressBar.Large" parent="Widget.ProgressBar.Large">
         <item name="android:indeterminateDrawable">@android:drawable/progress_large_holo</item>
-        <item name="android:animationResolution">33</item>
     </style>
 
     <style name="Widget.Holo.ProgressBar.Inverse">
diff --git a/core/tests/benchmarks/README b/core/tests/benchmarks/README
new file mode 100644
index 0000000..0a41bcc
--- /dev/null
+++ b/core/tests/benchmarks/README
@@ -0,0 +1,8 @@
+
+These benchmarks use the Caliper benchmark framework, and can be
+run on a remote device using Vogar:
+
+http://code.google.com/p/caliper/
+http://code.google.com/p/vogar/
+
+$ vogar --benchmark path/to/Benchmark.java
diff --git a/core/tests/benchmarks/src/android/os/ParcelArrayBenchmark.java b/core/tests/benchmarks/src/android/os/ParcelArrayBenchmark.java
new file mode 100644
index 0000000..21cfb09
--- /dev/null
+++ b/core/tests/benchmarks/src/android/os/ParcelArrayBenchmark.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2012 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 com.google.caliper.Param;
+import com.google.caliper.SimpleBenchmark;
+
+public class ParcelArrayBenchmark extends SimpleBenchmark {
+
+    @Param({ "1", "10", "100", "1000" })
+    private int mSize;
+
+    private Parcel mWriteParcel;
+
+    private byte[] mByteArray;
+    private int[] mIntArray;
+    private long[] mLongArray;
+
+    private Parcel mByteParcel;
+    private Parcel mIntParcel;
+    private Parcel mLongParcel;
+
+    @Override
+    protected void setUp() {
+        mWriteParcel = Parcel.obtain();
+
+        mByteArray = new byte[mSize];
+        mIntArray = new int[mSize];
+        mLongArray = new long[mSize];
+
+        mByteParcel = Parcel.obtain();
+        mByteParcel.writeByteArray(mByteArray);
+        mIntParcel = Parcel.obtain();
+        mIntParcel.writeIntArray(mIntArray);
+        mLongParcel = Parcel.obtain();
+        mLongParcel.writeLongArray(mLongArray);
+    }
+
+    @Override
+    protected void tearDown() {
+        mWriteParcel.recycle();
+        mWriteParcel = null;
+    }
+
+    public void timeWriteByteArray(int reps) {
+        for (int i = 0; i < reps; i++) {
+            mWriteParcel.setDataPosition(0);
+            mWriteParcel.writeByteArray(mByteArray);
+        }
+    }
+
+    public void timeCreateByteArray(int reps) {
+        for (int i = 0; i < reps; i++) {
+            mByteParcel.setDataPosition(0);
+            mByteParcel.createByteArray();
+        }
+    }
+
+    public void timeReadByteArray(int reps) {
+        for (int i = 0; i < reps; i++) {
+            mByteParcel.setDataPosition(0);
+            mByteParcel.readByteArray(mByteArray);
+        }
+    }
+
+    public void timeWriteIntArray(int reps) {
+        for (int i = 0; i < reps; i++) {
+            mWriteParcel.setDataPosition(0);
+            mWriteParcel.writeIntArray(mIntArray);
+        }
+    }
+
+    public void timeCreateIntArray(int reps) {
+        for (int i = 0; i < reps; i++) {
+            mIntParcel.setDataPosition(0);
+            mIntParcel.createIntArray();
+        }
+    }
+
+    public void timeReadIntArray(int reps) {
+        for (int i = 0; i < reps; i++) {
+            mIntParcel.setDataPosition(0);
+            mIntParcel.readIntArray(mIntArray);
+        }
+    }
+
+    public void timeWriteLongArray(int reps) {
+        for (int i = 0; i < reps; i++) {
+            mWriteParcel.setDataPosition(0);
+            mWriteParcel.writeLongArray(mLongArray);
+        }
+    }
+
+    public void timeCreateLongArray(int reps) {
+        for (int i = 0; i < reps; i++) {
+            mLongParcel.setDataPosition(0);
+            mLongParcel.createLongArray();
+        }
+    }
+
+    public void timeReadLongArray(int reps) {
+        for (int i = 0; i < reps; i++) {
+            mLongParcel.setDataPosition(0);
+            mLongParcel.readLongArray(mLongArray);
+        }
+    }
+
+}
diff --git a/core/tests/benchmarks/src/android/os/ParcelBenchmark.java b/core/tests/benchmarks/src/android/os/ParcelBenchmark.java
new file mode 100644
index 0000000..6a7b7c89
--- /dev/null
+++ b/core/tests/benchmarks/src/android/os/ParcelBenchmark.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2012 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 com.google.caliper.SimpleBenchmark;
+
+public class ParcelBenchmark extends SimpleBenchmark {
+
+    private Parcel mParcel;
+
+    @Override
+    protected void setUp() {
+        mParcel = Parcel.obtain();
+    }
+
+    @Override
+    protected void tearDown() {
+        mParcel.recycle();
+        mParcel = null;
+    }
+
+    public void timeWriteByte(int reps) {
+        final byte val = 0xF;
+        for (int i = 0; i < reps; i++) {
+            mParcel.writeByte(val);
+        }
+    }
+
+    public void timeReadByte(int reps) {
+        mParcel.setDataCapacity(reps);
+        for (int i = 0; i < reps; i++) {
+            mParcel.readByte();
+        }
+    }
+
+    public void timeWriteInt(int reps) {
+        final int val = 0xF;
+        for (int i = 0; i < reps; i++) {
+            mParcel.writeInt(val);
+        }
+    }
+
+    public void timeReadInt(int reps) {
+        mParcel.setDataCapacity(reps << 2);
+        for (int i = 0; i < reps; i++) {
+            mParcel.readInt();
+        }
+    }
+
+    public void timeWriteLong(int reps) {
+        final long val = 0xF;
+        for (int i = 0; i < reps; i++) {
+            mParcel.writeLong(val);
+        }
+    }
+
+    public void timeReadLong(int reps) {
+        mParcel.setDataCapacity(reps << 3);
+        for (int i = 0; i < reps; i++) {
+            mParcel.readLong();
+        }
+    }
+}
diff --git a/core/tests/coretests/res/layout/textview_test.xml b/core/tests/coretests/res/layout/textview_test.xml
deleted file mode 100644
index f0c7b9e..0000000
--- a/core/tests/coretests/res/layout/textview_test.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2011 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.
--->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-              android:id="@+id/textviewtest_layout"
-              android:layout_width="fill_parent"
-              android:layout_height="fill_parent">
-
-    <TextView android:id="@+id/textviewtest_textview"
-              android:layout_height="wrap_content"
-              android:layout_width="wrap_content"
-              android:text="@string/textview_hebrew_text"/>
-
-</LinearLayout>
\ No newline at end of file
diff --git a/core/tests/coretests/src/android/webkit/ZoomManagerTest.java b/core/tests/coretests/src/android/webkit/ZoomManagerTest.java
index 1c9defe..7e0e0b2 100644
--- a/core/tests/coretests/src/android/webkit/ZoomManagerTest.java
+++ b/core/tests/coretests/src/android/webkit/ZoomManagerTest.java
@@ -24,8 +24,9 @@
     @Override
     public void setUp() {
         WebView webView = new WebView(this.getContext());
-        CallbackProxy callbackProxy = new CallbackProxy(this.getContext(), webView);
-        zoomManager = new ZoomManager(webView, callbackProxy);
+        WebViewClassic webViewClassic = WebViewClassic.fromWebView(webView);
+        CallbackProxy callbackProxy = new CallbackProxy(this.getContext(), webViewClassic);
+        zoomManager = new ZoomManager(webViewClassic, callbackProxy);
 
         zoomManager.init(1.00f);
     }
diff --git a/core/tests/coretests/src/android/widget/TextViewTest.java b/core/tests/coretests/src/android/widget/TextViewTest.java
index d4dbced..af6df1a 100644
--- a/core/tests/coretests/src/android/widget/TextViewTest.java
+++ b/core/tests/coretests/src/android/widget/TextViewTest.java
@@ -16,25 +16,18 @@
 
 package android.widget;
 
-import android.test.ActivityInstrumentationTestCase2;
+import android.test.AndroidTestCase;
 import android.test.suitebuilder.annotation.SmallTest;
 import android.text.GetChars;
-import android.view.View;
-
-import com.android.frameworks.coretests.R;
 
 /**
  * TextViewTest tests {@link TextView}.
  */
-public class TextViewTest extends ActivityInstrumentationTestCase2<TextViewTestActivity> {
-
-    public TextViewTest() {
-        super(TextViewTestActivity.class);
-    }
+public class TextViewTest extends AndroidTestCase {
 
     @SmallTest
     public void testArray() throws Exception {
-        TextView tv = new TextView(getActivity());
+        TextView tv = new TextView(mContext);
 
         char[] c = new char[] { 'H', 'e', 'l', 'l', 'o', ' ',
                                 'W', 'o', 'r', 'l', 'd', '!' };
@@ -61,181 +54,4 @@
         assertEquals('o', c2[4]);
         assertEquals('\0', c2[5]);
     }
-
-    @SmallTest
-    public void testTextDirectionDefault() {
-        TextView tv = new TextView(getActivity());
-        assertEquals(View.TEXT_DIRECTION_INHERIT, tv.getTextDirection());
-    }
-
-    @SmallTest
-    public void testSetGetTextDirection() {
-        TextView tv = new TextView(getActivity());
-
-        tv.setTextDirection(View.TEXT_DIRECTION_FIRST_STRONG);
-        assertEquals(View.TEXT_DIRECTION_FIRST_STRONG, tv.getTextDirection());
-
-        tv.setTextDirection(View.TEXT_DIRECTION_ANY_RTL);
-        assertEquals(View.TEXT_DIRECTION_ANY_RTL, tv.getTextDirection());
-
-        tv.setTextDirection(View.TEXT_DIRECTION_INHERIT);
-        assertEquals(View.TEXT_DIRECTION_INHERIT, tv.getTextDirection());
-
-        tv.setTextDirection(View.TEXT_DIRECTION_LTR);
-        assertEquals(View.TEXT_DIRECTION_LTR, tv.getTextDirection());
-
-        tv.setTextDirection(View.TEXT_DIRECTION_RTL);
-        assertEquals(View.TEXT_DIRECTION_RTL, tv.getTextDirection());
-
-        tv.setTextDirection(View.TEXT_DIRECTION_LOCALE);
-        assertEquals(View.TEXT_DIRECTION_LOCALE, tv.getTextDirection());
-    }
-
-    @SmallTest
-    public void testGetResolvedTextDirectionLtr() {
-        TextView tv = new TextView(getActivity());
-        tv.setText("this is a test");
-
-        assertEquals(View.TEXT_DIRECTION_FIRST_STRONG, tv.getResolvedTextDirection());
-
-        tv.setTextDirection(View.TEXT_DIRECTION_FIRST_STRONG);
-        assertEquals(View.TEXT_DIRECTION_FIRST_STRONG, tv.getResolvedTextDirection());
-
-        tv.setTextDirection(View.TEXT_DIRECTION_ANY_RTL);
-        assertEquals(View.TEXT_DIRECTION_ANY_RTL, tv.getResolvedTextDirection());
-
-        tv.setTextDirection(View.TEXT_DIRECTION_INHERIT);
-        assertEquals(View.TEXT_DIRECTION_FIRST_STRONG, tv.getResolvedTextDirection());
-
-        tv.setTextDirection(View.TEXT_DIRECTION_LTR);
-        assertEquals(View.TEXT_DIRECTION_LTR, tv.getResolvedTextDirection());
-
-        tv.setTextDirection(View.TEXT_DIRECTION_RTL);
-        assertEquals(View.TEXT_DIRECTION_RTL, tv.getResolvedTextDirection());
-
-        tv.setTextDirection(View.TEXT_DIRECTION_LOCALE);
-        assertEquals(View.TEXT_DIRECTION_LOCALE, tv.getResolvedTextDirection());
-    }
-
-    @SmallTest
-    public void testGetResolvedTextDirectionLtrWithInheritance() {
-        LinearLayout ll = new LinearLayout(getActivity());
-        ll.setTextDirection(View.TEXT_DIRECTION_ANY_RTL);
-
-        TextView tv = new TextView(getActivity());
-        tv.setText("this is a test");
-        ll.addView(tv);
-
-        tv.setTextDirection(View.TEXT_DIRECTION_FIRST_STRONG);
-        assertEquals(View.TEXT_DIRECTION_FIRST_STRONG, tv.getResolvedTextDirection());
-
-        tv.setTextDirection(View.TEXT_DIRECTION_ANY_RTL);
-        assertEquals(View.TEXT_DIRECTION_ANY_RTL, tv.getResolvedTextDirection());
-
-        tv.setTextDirection(View.TEXT_DIRECTION_INHERIT);
-        assertEquals(View.TEXT_DIRECTION_ANY_RTL, tv.getResolvedTextDirection());
-
-        tv.setTextDirection(View.TEXT_DIRECTION_LTR);
-        assertEquals(View.TEXT_DIRECTION_LTR, tv.getResolvedTextDirection());
-
-        tv.setTextDirection(View.TEXT_DIRECTION_RTL);
-        assertEquals(View.TEXT_DIRECTION_RTL, tv.getResolvedTextDirection());
-
-        tv.setTextDirection(View.TEXT_DIRECTION_LOCALE);
-        assertEquals(View.TEXT_DIRECTION_LOCALE, tv.getResolvedTextDirection());
-    }
-
-    @SmallTest
-    public void testGetResolvedTextDirectionRtl() {
-        TextView tv = new TextView(getActivity());
-        tv.setText("\u05DD\u05DE"); // hebrew
-
-        assertEquals(View.TEXT_DIRECTION_FIRST_STRONG, tv.getResolvedTextDirection());
-
-        tv.setTextDirection(View.TEXT_DIRECTION_FIRST_STRONG);
-        assertEquals(View.TEXT_DIRECTION_FIRST_STRONG, tv.getResolvedTextDirection());
-
-        tv.setTextDirection(View.TEXT_DIRECTION_ANY_RTL);
-        assertEquals(View.TEXT_DIRECTION_ANY_RTL, tv.getResolvedTextDirection());
-
-        tv.setTextDirection(View.TEXT_DIRECTION_INHERIT);
-        assertEquals(View.TEXT_DIRECTION_FIRST_STRONG, tv.getResolvedTextDirection());
-
-        tv.setTextDirection(View.TEXT_DIRECTION_LTR);
-        assertEquals(View.TEXT_DIRECTION_LTR, tv.getResolvedTextDirection());
-
-        tv.setTextDirection(View.TEXT_DIRECTION_RTL);
-        assertEquals(View.TEXT_DIRECTION_RTL, tv.getResolvedTextDirection());
-
-        tv.setTextDirection(View.TEXT_DIRECTION_LOCALE);
-        assertEquals(View.TEXT_DIRECTION_LOCALE, tv.getResolvedTextDirection());
-    }
-
-    @SmallTest
-    public void testGetResolvedTextDirectionRtlWithInheritance() {
-        LinearLayout ll = new LinearLayout(getActivity());
-        ll.setTextDirection(View.TEXT_DIRECTION_FIRST_STRONG);
-
-        TextView tv = new TextView(getActivity());
-        tv.setText("\u05DD\u05DE"); // hebrew
-        ll.addView(tv);
-
-        tv.setTextDirection(View.TEXT_DIRECTION_FIRST_STRONG);
-        assertEquals(View.TEXT_DIRECTION_FIRST_STRONG, tv.getResolvedTextDirection());
-
-        tv.setTextDirection(View.TEXT_DIRECTION_ANY_RTL);
-        assertEquals(View.TEXT_DIRECTION_ANY_RTL, tv.getResolvedTextDirection());
-
-        tv.setTextDirection(View.TEXT_DIRECTION_INHERIT);
-        assertEquals(View.TEXT_DIRECTION_FIRST_STRONG, tv.getResolvedTextDirection());
-
-        tv.setTextDirection(View.TEXT_DIRECTION_LTR);
-        assertEquals(View.TEXT_DIRECTION_LTR, tv.getResolvedTextDirection());
-
-        tv.setTextDirection(View.TEXT_DIRECTION_RTL);
-        assertEquals(View.TEXT_DIRECTION_RTL, tv.getResolvedTextDirection());
-
-        tv.setTextDirection(View.TEXT_DIRECTION_LOCALE);
-        assertEquals(View.TEXT_DIRECTION_LOCALE, tv.getResolvedTextDirection());
-
-        // Force to RTL text direction on the layout
-        ll.setTextDirection(View.TEXT_DIRECTION_RTL);
-
-        tv.setTextDirection(View.TEXT_DIRECTION_FIRST_STRONG);
-        assertEquals(View.TEXT_DIRECTION_FIRST_STRONG, tv.getResolvedTextDirection());
-
-        tv.setTextDirection(View.TEXT_DIRECTION_ANY_RTL);
-        assertEquals(View.TEXT_DIRECTION_ANY_RTL, tv.getResolvedTextDirection());
-
-        tv.setTextDirection(View.TEXT_DIRECTION_INHERIT);
-        assertEquals(View.TEXT_DIRECTION_RTL, tv.getResolvedTextDirection());
-
-        tv.setTextDirection(View.TEXT_DIRECTION_LTR);
-        assertEquals(View.TEXT_DIRECTION_LTR, tv.getResolvedTextDirection());
-
-        tv.setTextDirection(View.TEXT_DIRECTION_RTL);
-        assertEquals(View.TEXT_DIRECTION_RTL, tv.getResolvedTextDirection());
-
-        tv.setTextDirection(View.TEXT_DIRECTION_LOCALE);
-        assertEquals(View.TEXT_DIRECTION_LOCALE, tv.getResolvedTextDirection());
-    }
-
-    @SmallTest
-    public void testResetTextDirection() {
-        final TextViewTestActivity activity = getActivity();
-
-        final LinearLayout ll = (LinearLayout) activity.findViewById(R.id.textviewtest_layout);
-        final TextView tv = (TextView) activity.findViewById(R.id.textviewtest_textview);
-
-        getActivity().runOnUiThread(new Runnable() {
-            public void run() {
-                ll.setTextDirection(View.TEXT_DIRECTION_RTL);
-                tv.setTextDirection(View.TEXT_DIRECTION_INHERIT);
-                assertEquals(View.TEXT_DIRECTION_RTL, tv.getResolvedTextDirection());
-
-                ll.removeView(tv);
-                assertEquals(View.TEXT_DIRECTION_FIRST_STRONG, tv.getResolvedTextDirection());
-            }
-        });
-    }
 }
diff --git a/core/tests/coretests/src/android/widget/TextViewTestActivity.java b/core/tests/coretests/src/android/widget/TextViewTestActivity.java
deleted file mode 100644
index 1bb4d24..0000000
--- a/core/tests/coretests/src/android/widget/TextViewTestActivity.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (C) 2011 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.widget;
-
-import android.app.Activity;
-import android.os.Bundle;
-
-import com.android.frameworks.coretests.R;
-
-public class TextViewTestActivity extends Activity {
-
-    @Override
-    protected void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        setContentView(R.layout.textview_test);
-    }
-}
diff --git a/docs/html/design/building-blocks/buttons.html b/docs/html/design/building-blocks/buttons.html
deleted file mode 100644
index 9f9652f9..0000000
--- a/docs/html/design/building-blocks/buttons.html
+++ /dev/null
@@ -1,197 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-  <head>
-    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
-    <title>
-
-Android Design - Buttons
-    </title>
-    <link rel="shortcut icon" type="image/x-icon" href="/favicon.ico">
-    <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Roboto:regular,medium,thin,italic,mediumitalic">
-    <link rel="stylesheet" href="../static/yui-3.3.0-reset-min.css">
-    <link rel="stylesheet" href="../static/default.css">
-
-  </head>
-  <body>
-
-    <div id="page-container">
-
-      <div id="page-header"><a href="../index.html">Android Design</a></div>
-
-      <div id="main-row">
-
-        <ul id="nav">
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../index.html">Get Started</a></div>
-            <ul>
-              <li><a href="../get-started/creative-vision.html">Creative Vision</a></li>
-              <li><a href="../get-started/principles.html">Design Principles</a></li>
-              <li><a href="../get-started/ui-overview.html">UI Overview</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../style/index.html">Style</a></div>
-            <ul>
-              <li><a href="../style/devices-displays.html">Devices and Displays</a></li>
-              <li><a href="../style/themes.html">Themes</a></li>
-              <li><a href="../style/touch-feedback.html">Touch Feedback</a></li>
-              <li><a href="../style/metrics-grids.html">Metrics and Grids</a></li>
-              <li><a href="../style/typography.html">Typography</a></li>
-              <li><a href="../style/color.html">Color</a></li>
-              <li><a href="../style/iconography.html">Iconography</a></li>
-              <li><a href="../style/writing.html">Writing Style</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../patterns/index.html">Patterns</a></div>
-            <ul>
-              <li><a href="../patterns/new-4-0.html">New in Android 4.0</a></li>
-              <li><a href="../patterns/gestures.html">Gestures</a></li>
-              <li><a href="../patterns/app-structure.html">App Structure</a></li>
-              <li><a href="../patterns/navigation.html">Navigation</a></li>
-              <li><a href="../patterns/actionbar.html">Action Bar</a></li>
-              <li><a href="../patterns/multi-pane-layouts.html">Multi-pane Layouts</a></li>
-              <li><a href="../patterns/swipe-views.html">Swipe Views</a></li>
-              <li><a href="../patterns/selection.html">Selection</a></li>
-              <li><a href="../patterns/notifications.html">Notifications</a></li>
-              <li><a href="../patterns/compatibility.html">Compatibility</a></li>
-              <li><a href="../patterns/pure-android.html">Pure Android</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../building-blocks/index.html">Building Blocks</a></div>
-            <ul>
-              <li><a href="../building-blocks/tabs.html">Tabs</a></li>
-              <li><a href="../building-blocks/lists.html">Lists</a></li>
-              <li><a href="../building-blocks/grid-lists.html">Grid Lists</a></li>
-              <li><a href="../building-blocks/scrolling.html">Scrolling</a></li>
-              <li><a href="../building-blocks/spinners.html">Spinners</a></li>
-              <li><a href="../building-blocks/buttons.html">Buttons</a></li>
-              <li><a href="../building-blocks/text-fields.html">Text Fields</a></li>
-              <li><a href="../building-blocks/seek-bars.html">Seek Bars</a></li>
-              <li><a href="../building-blocks/progress.html">Progress &amp; Activity</a></li>
-              <li><a href="../building-blocks/switches.html">Switches</a></li>
-              <li><a href="../building-blocks/dialogs.html">Dialogs</a></li>
-              <li><a href="../building-blocks/pickers.html">Pickers</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header empty"><a href="../downloads/index.html">Downloads</a></div>
-          </li>
-
-          <li>
-            <div id="back-dac-section"><a href="../../index.html">Developers</a></div>
-          </li>
-
-        </ul>
-
-        <div id="content">
-
-          
-          <div class="layout-content-row content-header">
-            <div class="layout-content-col span-9">
-              <h2>Buttons</h2>
-            </div>
-            <div class="paging-links layout-content-col span-4">
-              <a href="#" class="prev-page-link">Previous</a>
-              <a href="#" class="next-page-link">Next</a>
-            </div>
-          </div>
-          
-
-          
-
-<p>A button consists of text and/or an image that clearly communicates what action will occur when the
-user touches it. Android supports two different types of buttons: <em>basic buttons</em> and <em>borderless
-buttons</em>. Both can contain text labels and/or images.</p>
-
-<div style="text-align: center">
-  <img src="../static/content/buttons_basic.png">
-</div>
-
-<h2 id="basic">Basic Buttons</h2>
-
-<p>Basic buttons are traditional buttons with borders and background. Android supports two styles for
-basic buttons: default and small. Default buttons have slightly larger font size and are optimized
-for display outside of form content. Small buttons are intended for display alongside other content.
-They have a smaller font and smaller minimum height. Use small buttons in forms where they need to
-align with other UI elements.</p>
-
-<img src="../static/content/buttons_default_small.png">
-<div class="layout-content-row">
-  <div class="layout-content-col span-6">
-    <div class="figure-caption">
-      Default buttons in Holo Dark &amp; Light.
-    </div>
-  </div>
-  <div class="layout-content-col span-6">
-    <div class="figure-caption">
-      Small buttons in Holo Dark &amp; Light.
-    </div>
-  </div>
-</div>
-
-<h2 id="borderless">Borderless Buttons</h2>
-
-<p>Borderless buttons resemble basic buttons except that they have no borders or background. You can
-use borderless buttons with both icons and text. Borderless buttons are visually more lightweight
-than basic buttons and integrate nicely with other content.</p>
-
-<img src="../static/content/buttons_borderless.png">
-
-
-
-          
-          <div class="layout-content-row content-footer">
-            <div class="paging-links layout-content-col span-9">&nbsp;</div>
-            <div class="paging-links layout-content-col span-4">
-              <a href="#" class="prev-page-link">Previous</a>
-              <a href="#" class="next-page-link">Next</a>
-            </div>
-          </div>
-          
-        </div>
-
-      </div>
-
-      <div id="page-footer">
-
-        <p id="copyright">
-          Except as noted, this content is licensed under
-          <a href="http://creativecommons.org/licenses/by/2.5/">
-          Creative Commons Attribution 2.5</a>.<br>
-          For details and restrictions, see the
-          <a href="http://developer.android.com/license.html">Content License</a>.
-        </p>
-
-        <p>
-          <a href="http://www.android.com/terms.html">Site Terms of Service</a> &ndash;
-          <a href="http://www.android.com/privacy.html">Privacy Policy</a> &ndash;
-          <a href="http://www.android.com/branding.html">Brand Guidelines</a>
-        </p>
-
-      </div>
-    </div>
-
-    <script src="../static/jquery-1.6.2.min.js"></script>
-    <script>
-    var SITE_ROOT = '../';
-    </script>
-    <script src="../static/default.js"></script>
-
-
-    <script type="text/javascript">
-    var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
-    document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
-    </script>
-    <script type="text/javascript">
-    var pageTracker = _gat._getTracker("UA-5831155-1");
-    pageTracker._trackPageview();
-    </script>
-  </body>
-</html>
diff --git a/docs/html/design/building-blocks/buttons.jd b/docs/html/design/building-blocks/buttons.jd
new file mode 100644
index 0000000..18beab0
--- /dev/null
+++ b/docs/html/design/building-blocks/buttons.jd
@@ -0,0 +1,40 @@
+page.title=Buttons
+@jd:body
+
+<p>A button consists of text and/or an image that clearly communicates what action will occur when the
+user touches it. Android supports two different types of buttons: <em>basic buttons</em> and <em>borderless
+buttons</em>. Both can contain text labels and/or images.</p>
+
+<div style="text-align: center">
+  <img src="{@docRoot}design/media/buttons_basic.png">
+</div>
+
+<h2 id="basic">Basic Buttons</h2>
+
+<p>Basic buttons are traditional buttons with borders and background. Android supports two styles for
+basic buttons: default and small. Default buttons have slightly larger font size and are optimized
+for display outside of form content. Small buttons are intended for display alongside other content.
+They have a smaller font and smaller minimum height. Use small buttons in forms where they need to
+align with other UI elements.</p>
+
+<img src="{@docRoot}design/media/buttons_default_small.png">
+<div class="layout-content-row">
+  <div class="layout-content-col span-6">
+    <div class="figure-caption">
+      Default buttons in Holo Dark &amp; Light.
+    </div>
+  </div>
+  <div class="layout-content-col span-6">
+    <div class="figure-caption">
+      Small buttons in Holo Dark &amp; Light.
+    </div>
+  </div>
+</div>
+
+<h2 id="borderless">Borderless Buttons</h2>
+
+<p>Borderless buttons resemble basic buttons except that they have no borders or background. You can
+use borderless buttons with both icons and text. Borderless buttons are visually more lightweight
+than basic buttons and integrate nicely with other content.</p>
+
+<img src="{@docRoot}design/media/buttons_borderless.png">
diff --git a/docs/html/design/building-blocks/dialogs.html b/docs/html/design/building-blocks/dialogs.html
deleted file mode 100644
index f03a57a..0000000
--- a/docs/html/design/building-blocks/dialogs.html
+++ /dev/null
@@ -1,269 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-  <head>
-    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
-    <title>
-
-Android Design - Dialogs
-    </title>
-    <link rel="shortcut icon" type="image/x-icon" href="/favicon.ico">
-    <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Roboto:regular,medium,thin,italic,mediumitalic">
-    <link rel="stylesheet" href="../static/yui-3.3.0-reset-min.css">
-    <link rel="stylesheet" href="../static/default.css">
-
-  </head>
-  <body>
-
-    <div id="page-container">
-
-      <div id="page-header"><a href="../index.html">Android Design</a></div>
-
-      <div id="main-row">
-
-        <ul id="nav">
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../index.html">Get Started</a></div>
-            <ul>
-              <li><a href="../get-started/creative-vision.html">Creative Vision</a></li>
-              <li><a href="../get-started/principles.html">Design Principles</a></li>
-              <li><a href="../get-started/ui-overview.html">UI Overview</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../style/index.html">Style</a></div>
-            <ul>
-              <li><a href="../style/devices-displays.html">Devices and Displays</a></li>
-              <li><a href="../style/themes.html">Themes</a></li>
-              <li><a href="../style/touch-feedback.html">Touch Feedback</a></li>
-              <li><a href="../style/metrics-grids.html">Metrics and Grids</a></li>
-              <li><a href="../style/typography.html">Typography</a></li>
-              <li><a href="../style/color.html">Color</a></li>
-              <li><a href="../style/iconography.html">Iconography</a></li>
-              <li><a href="../style/writing.html">Writing Style</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../patterns/index.html">Patterns</a></div>
-            <ul>
-              <li><a href="../patterns/new-4-0.html">New in Android 4.0</a></li>
-              <li><a href="../patterns/gestures.html">Gestures</a></li>
-              <li><a href="../patterns/app-structure.html">App Structure</a></li>
-              <li><a href="../patterns/navigation.html">Navigation</a></li>
-              <li><a href="../patterns/actionbar.html">Action Bar</a></li>
-              <li><a href="../patterns/multi-pane-layouts.html">Multi-pane Layouts</a></li>
-              <li><a href="../patterns/swipe-views.html">Swipe Views</a></li>
-              <li><a href="../patterns/selection.html">Selection</a></li>
-              <li><a href="../patterns/notifications.html">Notifications</a></li>
-              <li><a href="../patterns/compatibility.html">Compatibility</a></li>
-              <li><a href="../patterns/pure-android.html">Pure Android</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../building-blocks/index.html">Building Blocks</a></div>
-            <ul>
-              <li><a href="../building-blocks/tabs.html">Tabs</a></li>
-              <li><a href="../building-blocks/lists.html">Lists</a></li>
-              <li><a href="../building-blocks/grid-lists.html">Grid Lists</a></li>
-              <li><a href="../building-blocks/scrolling.html">Scrolling</a></li>
-              <li><a href="../building-blocks/spinners.html">Spinners</a></li>
-              <li><a href="../building-blocks/buttons.html">Buttons</a></li>
-              <li><a href="../building-blocks/text-fields.html">Text Fields</a></li>
-              <li><a href="../building-blocks/seek-bars.html">Seek Bars</a></li>
-              <li><a href="../building-blocks/progress.html">Progress &amp; Activity</a></li>
-              <li><a href="../building-blocks/switches.html">Switches</a></li>
-              <li><a href="../building-blocks/dialogs.html">Dialogs</a></li>
-              <li><a href="../building-blocks/pickers.html">Pickers</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header empty"><a href="../downloads/index.html">Downloads</a></div>
-          </li>
-
-          <li>
-            <div id="back-dac-section"><a href="../../index.html">Developers</a></div>
-          </li>
-
-        </ul>
-
-        <div id="content">
-
-          
-          <div class="layout-content-row content-header">
-            <div class="layout-content-col span-9">
-              <h2>Dialogs</h2>
-            </div>
-            <div class="paging-links layout-content-col span-4">
-              <a href="#" class="prev-page-link">Previous</a>
-              <a href="#" class="next-page-link">Next</a>
-            </div>
-          </div>
-          
-
-          
-
-<p>Dialogs prompt the user for decisions or additional information required by the app to continue a
-task. Such requests can range from simple Cancel/OK decisions to more complex layouts asking the
-user to adjust settings or enter text.</p>
-
-<img src="../static/content/dialogs_main.png">
-
-<div class="with-callouts">
-
-<ol>
-<li>
-<h4>Optional title region</h4>
-<p>The title introduces the content of your dialog. It can, for example, identify the name of a
- setting that the user is about to change, or request a decision.</p>
-</li>
-<li>
-<h4>Content area</h4>
-<p>Dialog content varies widely. For settings dialogs, a dialog may contain UI elements such as
- sliders, text fields, checkboxes, or radio buttons that allow the user to change app or system
- settings. In other cases, such as alerts, the content may consist solely of text that provides
- further context for a user decision.</p>
-</li>
-<li>
-<h4>Action buttons</h4>
-<p>Action buttons are typically Cancel and/or OK, with OK indicating the preferred or most likely
- action. However, if the options consist of specific actions such as Close or Wait rather than
- a confirmation or cancellation of the action described in the content, then all the buttons
- should be active verbs. As a rule, the dismissive action of a dialog is always on the left
- whereas the affirmative actions are on the right.</p>
-</li>
-</ol>
-
-</div>
-
-<img src="../static/content/dialogs_examples.png">
-<div class="figure-caption">
-  Samples of typical dialog use in Android.
-</div>
-
-<h2 id="alerts">Alerts</h2>
-
-<p>Alerts inform the user about a situation that requires their confirmation or acknowledgement before
-proceeding. They differ slightly in appearance based upon the severity and impact of the message
-conveyed.</p>
-
-<div class="layout-content-row">
-  <div class="layout-content-col span-8">
-
-    <img src="../static/content/dialogs_w_no_title.png">
-
-  </div>
-  <div class="layout-content-col span-5">
-
-<h4>Alerts without title bars</h4>
-<p>Most alerts don't need titles. Usually the decision doesn't have a severe impact and can be summed
-up succinctly in a sentence or two. The content area should either ask a question (such as "Delete
-this conversation?") or make a clear statement whose relationship to the action buttons is obvious.</p>
-
-  </div>
-</div>
-
-
-<div class="layout-content-row">
-  <div class="layout-content-col span-8">
-
-    <img src="../static/content/dialogs_w_title.png">
-
-  </div>
-  <div class="layout-content-col span-5">
-
-<h4>Alerts with title bars</h4>
-<p>Use alerts with title bars sparingly. They are appropriate only when a high-risk operation involving
-potential loss of data, connectivity, extra charges, and so on requires a clear question or
-statement (the title) and some additional explanation (in the content area).</p>
-<p>Keep the question or statement short: for example, "Erase USB storage?" Avoid apologies. A user
-should be able to skip the content completely and still have a clear idea of what choices are
-available based on the title and the text of the action buttons.</p>
-
-  </div>
-</div>
-
-
-<h2 id="popups">Popups</h2>
-
-<p>Popups are lightweight version of dialogs that require a single selection from the user. Popups
-don't have have explicit buttons that accept or cancel the operation. Instead, making a selection
-advances the workflow, and simply touching outside the popup dismisses it.</p>
-
-<img src="../static/content/dialogs_popups_example.png">
-
-
-<h2 id="toasts">Toasts</h2>
-
-
-<div class="layout-content-row">
-  <div class="layout-content-col span-6">
-
-    <div class="vspace size-6"></div>
-
-<p>Toasts provide lightweight feedback about an operation in a small popup. For example, navigating
-away from an email before you send it triggers a "Draft saved" toast to let you know that you can
-continue editing later. Toasts automatically disappear after a timeout.</p>
-
-  </div>
-  <div class="layout-content-col span-7">
-
-    <img src="../static/content/dialogs_toasts.png">
-
-  </div>
-</div>
-
-
-
-          
-          <div class="layout-content-row content-footer">
-            <div class="paging-links layout-content-col span-9">&nbsp;</div>
-            <div class="paging-links layout-content-col span-4">
-              <a href="#" class="prev-page-link">Previous</a>
-              <a href="#" class="next-page-link">Next</a>
-            </div>
-          </div>
-          
-        </div>
-
-      </div>
-
-      <div id="page-footer">
-
-        <p id="copyright">
-          Except as noted, this content is licensed under
-          <a href="http://creativecommons.org/licenses/by/2.5/">
-          Creative Commons Attribution 2.5</a>.<br>
-          For details and restrictions, see the
-          <a href="http://developer.android.com/license.html">Content License</a>.
-        </p>
-
-        <p>
-          <a href="http://www.android.com/terms.html">Site Terms of Service</a> &ndash;
-          <a href="http://www.android.com/privacy.html">Privacy Policy</a> &ndash;
-          <a href="http://www.android.com/branding.html">Brand Guidelines</a>
-        </p>
-
-      </div>
-    </div>
-
-    <script src="../static/jquery-1.6.2.min.js"></script>
-    <script>
-    var SITE_ROOT = '../';
-    </script>
-    <script src="../static/default.js"></script>
-
-
-    <script type="text/javascript">
-    var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
-    document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
-    </script>
-    <script type="text/javascript">
-    var pageTracker = _gat._getTracker("UA-5831155-1");
-    pageTracker._trackPageview();
-    </script>
-  </body>
-</html>
diff --git a/docs/html/design/building-blocks/dialogs.jd b/docs/html/design/building-blocks/dialogs.jd
new file mode 100644
index 0000000..9b653ee
--- /dev/null
+++ b/docs/html/design/building-blocks/dialogs.jd
@@ -0,0 +1,112 @@
+page.title=Dialogs
+@jd:body
+
+<p>Dialogs prompt the user for decisions or additional information required by the app to continue a
+task. Such requests can range from simple Cancel/OK decisions to more complex layouts asking the
+user to adjust settings or enter text.</p>
+
+<img src="{@docRoot}design/media/dialogs_main.png">
+
+<div class="with-callouts">
+
+<ol>
+<li>
+<h4>Optional title region</h4>
+<p>The title introduces the content of your dialog. It can, for example, identify the name of a
+ setting that the user is about to change, or request a decision.</p>
+</li>
+<li>
+<h4>Content area</h4>
+<p>Dialog content varies widely. For settings dialogs, a dialog may contain UI elements such as
+ sliders, text fields, checkboxes, or radio buttons that allow the user to change app or system
+ settings. In other cases, such as alerts, the content may consist solely of text that provides
+ further context for a user decision.</p>
+</li>
+<li>
+<h4>Action buttons</h4>
+<p>Action buttons are typically Cancel and/or OK, with OK indicating the preferred or most likely
+ action. However, if the options consist of specific actions such as Close or Wait rather than
+ a confirmation or cancellation of the action described in the content, then all the buttons
+ should be active verbs. As a rule, the dismissive action of a dialog is always on the left
+ whereas the affirmative actions are on the right.</p>
+</li>
+</ol>
+
+</div>
+
+<img src="{@docRoot}design/media/dialogs_examples.png">
+<div class="figure-caption">
+  Samples of typical dialog use in Android.
+</div>
+
+<h2 id="alerts">Alerts</h2>
+
+<p>Alerts inform the user about a situation that requires their confirmation or acknowledgement before
+proceeding. They differ slightly in appearance based upon the severity and impact of the message
+conveyed.</p>
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-8">
+
+    <img src="{@docRoot}design/media/dialogs_w_no_title.png">
+
+  </div>
+  <div class="layout-content-col span-5">
+
+<h4>Alerts without title bars</h4>
+<p>Most alerts don't need titles. Usually the decision doesn't have a severe impact and can be summed
+up succinctly in a sentence or two. The content area should either ask a question (such as "Delete
+this conversation?") or make a clear statement whose relationship to the action buttons is obvious.</p>
+
+  </div>
+</div>
+
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-8">
+
+    <img src="{@docRoot}design/media/dialogs_w_title.png">
+
+  </div>
+  <div class="layout-content-col span-5">
+
+<h4>Alerts with title bars</h4>
+<p>Use alerts with title bars sparingly. They are appropriate only when a high-risk operation involving
+potential loss of data, connectivity, extra charges, and so on requires a clear question or
+statement (the title) and some additional explanation (in the content area).</p>
+<p>Keep the question or statement short: for example, "Erase USB storage?" Avoid apologies. A user
+should be able to skip the content completely and still have a clear idea of what choices are
+available based on the title and the text of the action buttons.</p>
+
+  </div>
+</div>
+
+
+<h2 id="popups">Popups</h2>
+
+<p>Popups are lightweight version of dialogs that require a single selection from the user. Popups
+don't have have explicit buttons that accept or cancel the operation. Instead, making a selection
+advances the workflow, and simply touching outside the popup dismisses it.</p>
+
+<img src="{@docRoot}design/media/dialogs_popups_example.png">
+
+
+<h2 id="toasts">Toasts</h2>
+
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-6">
+
+    <div class="vspace size-6"></div>
+
+<p>Toasts provide lightweight feedback about an operation in a small popup. For example, navigating
+away from an email before you send it triggers a "Draft saved" toast to let you know that you can
+continue editing later. Toasts automatically disappear after a timeout.</p>
+
+  </div>
+  <div class="layout-content-col span-7">
+
+    <img src="{@docRoot}design/media/dialogs_toasts.png">
+
+  </div>
+</div>
diff --git a/docs/html/design/building-blocks/grid-lists.html b/docs/html/design/building-blocks/grid-lists.html
deleted file mode 100644
index 3f60216..0000000
--- a/docs/html/design/building-blocks/grid-lists.html
+++ /dev/null
@@ -1,237 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-  <head>
-    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
-    <title>
-
-Android Design - Grid Lists
-    </title>
-    <link rel="shortcut icon" type="image/x-icon" href="/favicon.ico">
-    <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Roboto:regular,medium,thin,italic,mediumitalic">
-    <link rel="stylesheet" href="../static/yui-3.3.0-reset-min.css">
-    <link rel="stylesheet" href="../static/default.css">
-
-  </head>
-  <body>
-
-    <div id="page-container">
-
-      <div id="page-header"><a href="../index.html">Android Design</a></div>
-
-      <div id="main-row">
-
-        <ul id="nav">
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../index.html">Get Started</a></div>
-            <ul>
-              <li><a href="../get-started/creative-vision.html">Creative Vision</a></li>
-              <li><a href="../get-started/principles.html">Design Principles</a></li>
-              <li><a href="../get-started/ui-overview.html">UI Overview</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../style/index.html">Style</a></div>
-            <ul>
-              <li><a href="../style/devices-displays.html">Devices and Displays</a></li>
-              <li><a href="../style/themes.html">Themes</a></li>
-              <li><a href="../style/touch-feedback.html">Touch Feedback</a></li>
-              <li><a href="../style/metrics-grids.html">Metrics and Grids</a></li>
-              <li><a href="../style/typography.html">Typography</a></li>
-              <li><a href="../style/color.html">Color</a></li>
-              <li><a href="../style/iconography.html">Iconography</a></li>
-              <li><a href="../style/writing.html">Writing Style</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../patterns/index.html">Patterns</a></div>
-            <ul>
-              <li><a href="../patterns/new-4-0.html">New in Android 4.0</a></li>
-              <li><a href="../patterns/gestures.html">Gestures</a></li>
-              <li><a href="../patterns/app-structure.html">App Structure</a></li>
-              <li><a href="../patterns/navigation.html">Navigation</a></li>
-              <li><a href="../patterns/actionbar.html">Action Bar</a></li>
-              <li><a href="../patterns/multi-pane-layouts.html">Multi-pane Layouts</a></li>
-              <li><a href="../patterns/swipe-views.html">Swipe Views</a></li>
-              <li><a href="../patterns/selection.html">Selection</a></li>
-              <li><a href="../patterns/notifications.html">Notifications</a></li>
-              <li><a href="../patterns/compatibility.html">Compatibility</a></li>
-              <li><a href="../patterns/pure-android.html">Pure Android</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../building-blocks/index.html">Building Blocks</a></div>
-            <ul>
-              <li><a href="../building-blocks/tabs.html">Tabs</a></li>
-              <li><a href="../building-blocks/lists.html">Lists</a></li>
-              <li><a href="../building-blocks/grid-lists.html">Grid Lists</a></li>
-              <li><a href="../building-blocks/scrolling.html">Scrolling</a></li>
-              <li><a href="../building-blocks/spinners.html">Spinners</a></li>
-              <li><a href="../building-blocks/buttons.html">Buttons</a></li>
-              <li><a href="../building-blocks/text-fields.html">Text Fields</a></li>
-              <li><a href="../building-blocks/seek-bars.html">Seek Bars</a></li>
-              <li><a href="../building-blocks/progress.html">Progress &amp; Activity</a></li>
-              <li><a href="../building-blocks/switches.html">Switches</a></li>
-              <li><a href="../building-blocks/dialogs.html">Dialogs</a></li>
-              <li><a href="../building-blocks/pickers.html">Pickers</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header empty"><a href="../downloads/index.html">Downloads</a></div>
-          </li>
-
-          <li>
-            <div id="back-dac-section"><a href="../../index.html">Developers</a></div>
-          </li>
-
-        </ul>
-
-        <div id="content">
-
-          
-          <div class="layout-content-row content-header">
-            <div class="layout-content-col span-9">
-              <h2>Grid Lists</h2>
-            </div>
-            <div class="paging-links layout-content-col span-4">
-              <a href="#" class="prev-page-link">Previous</a>
-              <a href="#" class="next-page-link">Next</a>
-            </div>
-          </div>
-          
-
-          
-
-<img src="../static/content/gridview_overview.png">
-
-<p>Grid lists are an alternative to standard list views. They are best suited for showing data sets
-that represent themselves through images. In contrast to simple lists, grid lists may scroll either
-vertically or horizontally.</p>
-
-
-
-<h2 id="generic_grid">Generic Grids</h2>
-
-
-<p>The items in a grid list are arranged in two dimensions, one of which is fixed when scrolling
-content. The scrolling direction dictates the ordering of the items within the grid list. Since the
-scrolling direction is not deterministic, make it easy for the user to determine the orientation by
-cutting off grid items to communicate where the overflow is located.</p>
-<p>Avoid creating grid lists that scroll in two dimensions.</p>
-
-
-<div class="layout-content-row">
-  <div class="layout-content-col span-7">
-
-    <img src="../static/content/gridview_vertical.png">
-
-  </div>
-  <div class="layout-content-col span-6">
-
-<h4>Vertical scrolling</h4>
-<p>Vertically scrolling grid list items are sorted in traditional western reading direction:
-left-to-right and top-down. When displaying the list, cut off the items in the bottom row to
-communicate that the user can scroll the list down to show additional items. Be sure to retain this
-scheme when the user rotates the screen.</p>
-
-  </div>
-</div>
-
-<div class="layout-content-row">
-  <div class="layout-content-col span-7">
-
-    <img src="../static/content/gridview_horizontal.png">
-
-  </div>
-  <div class="layout-content-col span-6">
-
-<h4>Horizontal scrolling</h4>
-<p>Horizontally scrolling lists fix the vertical axis of the item grid. Compared to vertically
-scrolling lists, the sorting changes slightly to a top-down and left-to-right arrangement. Employ
-the same technique of cutting off the items in the rightmost column to indicate the scrolling
-direction.</p>
-<p>Don't use scrolling tabs as a means to switch views in conjunction with horizontally scrolling grid
-lists, because the horizontal gesture for view and content navigation will conflict. If you show
-scrolling tabs for view navigation together with a grid list, use vertical grid scrolling for list
-navigation.</p>
-
-  </div>
-</div>
-
-
-<h2 id="with-labels">Grid List with Labels</h2>
-
-<p>Use labels to display additional contextual information for your grid list items.</p>
-
-
-<div class="layout-content-row">
-  <div class="layout-content-col span-7">
-
-    <img src="../static/content/gridview_style.png">
-
-  </div>
-  <div class="layout-content-col span-6">
-
-<h4>Style</h4>
-<p>Use semi-transparent panels on top of the grid list items to display your labels. This allows you to
-control the contrast and ensures legibility of the labels while letting the content "shine through".</p>
-
-  </div>
-</div>
-
-
-
-
-          
-          <div class="layout-content-row content-footer">
-            <div class="paging-links layout-content-col span-9">&nbsp;</div>
-            <div class="paging-links layout-content-col span-4">
-              <a href="#" class="prev-page-link">Previous</a>
-              <a href="#" class="next-page-link">Next</a>
-            </div>
-          </div>
-          
-        </div>
-
-      </div>
-
-      <div id="page-footer">
-
-        <p id="copyright">
-          Except as noted, this content is licensed under
-          <a href="http://creativecommons.org/licenses/by/2.5/">
-          Creative Commons Attribution 2.5</a>.<br>
-          For details and restrictions, see the
-          <a href="http://developer.android.com/license.html">Content License</a>.
-        </p>
-
-        <p>
-          <a href="http://www.android.com/terms.html">Site Terms of Service</a> &ndash;
-          <a href="http://www.android.com/privacy.html">Privacy Policy</a> &ndash;
-          <a href="http://www.android.com/branding.html">Brand Guidelines</a>
-        </p>
-
-      </div>
-    </div>
-
-    <script src="../static/jquery-1.6.2.min.js"></script>
-    <script>
-    var SITE_ROOT = '../';
-    </script>
-    <script src="../static/default.js"></script>
-
-
-    <script type="text/javascript">
-    var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
-    document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
-    </script>
-    <script type="text/javascript">
-    var pageTracker = _gat._getTracker("UA-5831155-1");
-    pageTracker._trackPageview();
-    </script>
-  </body>
-</html>
diff --git a/docs/html/design/building-blocks/grid-lists.jd b/docs/html/design/building-blocks/grid-lists.jd
new file mode 100644
index 0000000..775ebcc
--- /dev/null
+++ b/docs/html/design/building-blocks/grid-lists.jd
@@ -0,0 +1,79 @@
+page.title=Grid Lists
+@jd:body
+
+<img src="{@docRoot}design/media/gridview_overview.png">
+
+<p>Grid lists are an alternative to standard list views. They are best suited for showing data sets
+that represent themselves through images. In contrast to simple lists, grid lists may scroll either
+vertically or horizontally.</p>
+
+
+
+<h2 id="generic_grid">Generic Grids</h2>
+
+
+<p>The items in a grid list are arranged in two dimensions, one of which is fixed when scrolling
+content. The scrolling direction dictates the ordering of the items within the grid list. Since the
+scrolling direction is not deterministic, make it easy for the user to determine the orientation by
+cutting off grid items to communicate where the overflow is located.</p>
+<p>Avoid creating grid lists that scroll in two dimensions.</p>
+
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-7">
+
+    <img src="{@docRoot}design/media/gridview_vertical.png">
+
+  </div>
+  <div class="layout-content-col span-6">
+
+<h4>Vertical scrolling</h4>
+<p>Vertically scrolling grid list items are sorted in traditional western reading direction:
+left-to-right and top-down. When displaying the list, cut off the items in the bottom row to
+communicate that the user can scroll the list down to show additional items. Be sure to retain this
+scheme when the user rotates the screen.</p>
+
+  </div>
+</div>
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-7">
+
+    <img src="{@docRoot}design/media/gridview_horizontal.png">
+
+  </div>
+  <div class="layout-content-col span-6">
+
+<h4>Horizontal scrolling</h4>
+<p>Horizontally scrolling lists fix the vertical axis of the item grid. Compared to vertically
+scrolling lists, the sorting changes slightly to a top-down and left-to-right arrangement. Employ
+the same technique of cutting off the items in the rightmost column to indicate the scrolling
+direction.</p>
+<p>Don't use scrolling tabs as a means to switch views in conjunction with horizontally scrolling grid
+lists, because the horizontal gesture for view and content navigation will conflict. If you show
+scrolling tabs for view navigation together with a grid list, use vertical grid scrolling for list
+navigation.</p>
+
+  </div>
+</div>
+
+
+<h2 id="with-labels">Grid List with Labels</h2>
+
+<p>Use labels to display additional contextual information for your grid list items.</p>
+
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-7">
+
+    <img src="{@docRoot}design/media/gridview_style.png">
+
+  </div>
+  <div class="layout-content-col span-6">
+
+<h4>Style</h4>
+<p>Use semi-transparent panels on top of the grid list items to display your labels. This allows you to
+control the contrast and ensures legibility of the labels while letting the content "shine through".</p>
+
+  </div>
+</div>
diff --git a/docs/html/design/building-blocks/index.html b/docs/html/design/building-blocks/index.html
deleted file mode 100644
index 029cabf..0000000
--- a/docs/html/design/building-blocks/index.html
+++ /dev/null
@@ -1,175 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-  <head>
-    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
-    <title>
-
-Android Design - Building Blocks
-    </title>
-    <link rel="shortcut icon" type="image/x-icon" href="/favicon.ico">
-    <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Roboto:regular,medium,thin,italic,mediumitalic">
-    <link rel="stylesheet" href="../static/yui-3.3.0-reset-min.css">
-    <link rel="stylesheet" href="../static/default.css">
-
-<style>
-#landing-graphic-container {
-  position: relative;
-}
-
-#text-overlay {
-  position: absolute;
-  left: 10px;
-  top: 472px;
-  width: 450px;
-}
-</style>
-
-  </head>
-  <body>
-
-    <div id="page-container">
-
-      <div id="page-header"><a href="../index.html">Android Design</a></div>
-
-      <div id="main-row">
-
-        <ul id="nav">
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../index.html">Get Started</a></div>
-            <ul>
-              <li><a href="../get-started/creative-vision.html">Creative Vision</a></li>
-              <li><a href="../get-started/principles.html">Design Principles</a></li>
-              <li><a href="../get-started/ui-overview.html">UI Overview</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../style/index.html">Style</a></div>
-            <ul>
-              <li><a href="../style/devices-displays.html">Devices and Displays</a></li>
-              <li><a href="../style/themes.html">Themes</a></li>
-              <li><a href="../style/touch-feedback.html">Touch Feedback</a></li>
-              <li><a href="../style/metrics-grids.html">Metrics and Grids</a></li>
-              <li><a href="../style/typography.html">Typography</a></li>
-              <li><a href="../style/color.html">Color</a></li>
-              <li><a href="../style/iconography.html">Iconography</a></li>
-              <li><a href="../style/writing.html">Writing Style</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../patterns/index.html">Patterns</a></div>
-            <ul>
-              <li><a href="../patterns/new-4-0.html">New in Android 4.0</a></li>
-              <li><a href="../patterns/gestures.html">Gestures</a></li>
-              <li><a href="../patterns/app-structure.html">App Structure</a></li>
-              <li><a href="../patterns/navigation.html">Navigation</a></li>
-              <li><a href="../patterns/actionbar.html">Action Bar</a></li>
-              <li><a href="../patterns/multi-pane-layouts.html">Multi-pane Layouts</a></li>
-              <li><a href="../patterns/swipe-views.html">Swipe Views</a></li>
-              <li><a href="../patterns/selection.html">Selection</a></li>
-              <li><a href="../patterns/notifications.html">Notifications</a></li>
-              <li><a href="../patterns/compatibility.html">Compatibility</a></li>
-              <li><a href="../patterns/pure-android.html">Pure Android</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../building-blocks/index.html">Building Blocks</a></div>
-            <ul>
-              <li><a href="../building-blocks/tabs.html">Tabs</a></li>
-              <li><a href="../building-blocks/lists.html">Lists</a></li>
-              <li><a href="../building-blocks/grid-lists.html">Grid Lists</a></li>
-              <li><a href="../building-blocks/scrolling.html">Scrolling</a></li>
-              <li><a href="../building-blocks/spinners.html">Spinners</a></li>
-              <li><a href="../building-blocks/buttons.html">Buttons</a></li>
-              <li><a href="../building-blocks/text-fields.html">Text Fields</a></li>
-              <li><a href="../building-blocks/seek-bars.html">Seek Bars</a></li>
-              <li><a href="../building-blocks/progress.html">Progress &amp; Activity</a></li>
-              <li><a href="../building-blocks/switches.html">Switches</a></li>
-              <li><a href="../building-blocks/dialogs.html">Dialogs</a></li>
-              <li><a href="../building-blocks/pickers.html">Pickers</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header empty"><a href="../downloads/index.html">Downloads</a></div>
-          </li>
-
-          <li>
-            <div id="back-dac-section"><a href="../../index.html">Developers</a></div>
-          </li>
-
-        </ul>
-
-        <div id="content">
-
-          
-<div class="layout-content-row content-header just-links">
-  <div class="layout-content-col span-9">&nbsp;</div>
-  <div class="paging-links layout-content-col span-4">
-    <a href="#" class="prev-page-link">Previous</a>
-    <a href="#" class="next-page-link">Next</a>
-  </div>
-</div>
-
-
-          
-
-<div id="landing-graphic-container">
-  <div id="text-overlay">
-    Your inventory of ready-to-use elements for creating outstanding apps.
-    <br><br>
-    <a href="../building-blocks/tabs.html" class="landing-page-link">Tabs</a>
-  </div>
-
-  <a href="../building-blocks/tabs.html">
-    <img src="../static/content/building_blocks_landing.png">
-  </a>
-</div>
-
-
-
-          
-
-        </div>
-
-      </div>
-
-      <div id="page-footer">
-
-        <p id="copyright">
-          Except as noted, this content is licensed under
-          <a href="http://creativecommons.org/licenses/by/2.5/">
-          Creative Commons Attribution 2.5</a>.<br>
-          For details and restrictions, see the
-          <a href="http://developer.android.com/license.html">Content License</a>.
-        </p>
-
-        <p>
-          <a href="http://www.android.com/terms.html">Site Terms of Service</a> &ndash;
-          <a href="http://www.android.com/privacy.html">Privacy Policy</a> &ndash;
-          <a href="http://www.android.com/branding.html">Brand Guidelines</a>
-        </p>
-
-      </div>
-    </div>
-
-    <script src="../static/jquery-1.6.2.min.js"></script>
-    <script>
-    var SITE_ROOT = '../';
-    </script>
-    <script src="../static/default.js"></script>
-
-
-    <script type="text/javascript">
-    var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
-    document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
-    </script>
-    <script type="text/javascript">
-    var pageTracker = _gat._getTracker("UA-5831155-1");
-    pageTracker._trackPageview();
-    </script>
-  </body>
-</html>
diff --git a/docs/html/design/building-blocks/index.jd b/docs/html/design/building-blocks/index.jd
new file mode 100644
index 0000000..52b4915
--- /dev/null
+++ b/docs/html/design/building-blocks/index.jd
@@ -0,0 +1,29 @@
+page.title=Building Blocks
+header.justLinks=1
+footer.hide=1
+@jd:body
+
+<style>
+#landing-graphic-container {
+  position: relative;
+}
+
+#text-overlay {
+  position: absolute;
+  left: 10px;
+  top: 472px;
+  width: 450px;
+}
+</style>
+
+<div id="landing-graphic-container">
+  <div id="text-overlay">
+    Your inventory of ready-to-use elements for creating outstanding apps.
+    <br><br>
+    <a href="{@docRoot}design/building-blocks/tabs.html" class="landing-page-link">Tabs</a>
+  </div>
+
+  <a href="{@docRoot}design/building-blocks/tabs.html">
+    <img src="{@docRoot}design/media/building_blocks_landing.png">
+  </a>
+</div>
diff --git a/docs/html/design/building-blocks/lists.html b/docs/html/design/building-blocks/lists.html
deleted file mode 100644
index dfd13d9..0000000
--- a/docs/html/design/building-blocks/lists.html
+++ /dev/null
@@ -1,188 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-  <head>
-    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
-    <title>
-
-Android Design - Lists
-    </title>
-    <link rel="shortcut icon" type="image/x-icon" href="/favicon.ico">
-    <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Roboto:regular,medium,thin,italic,mediumitalic">
-    <link rel="stylesheet" href="../static/yui-3.3.0-reset-min.css">
-    <link rel="stylesheet" href="../static/default.css">
-
-  </head>
-  <body>
-
-    <div id="page-container">
-
-      <div id="page-header"><a href="../index.html">Android Design</a></div>
-
-      <div id="main-row">
-
-        <ul id="nav">
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../index.html">Get Started</a></div>
-            <ul>
-              <li><a href="../get-started/creative-vision.html">Creative Vision</a></li>
-              <li><a href="../get-started/principles.html">Design Principles</a></li>
-              <li><a href="../get-started/ui-overview.html">UI Overview</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../style/index.html">Style</a></div>
-            <ul>
-              <li><a href="../style/devices-displays.html">Devices and Displays</a></li>
-              <li><a href="../style/themes.html">Themes</a></li>
-              <li><a href="../style/touch-feedback.html">Touch Feedback</a></li>
-              <li><a href="../style/metrics-grids.html">Metrics and Grids</a></li>
-              <li><a href="../style/typography.html">Typography</a></li>
-              <li><a href="../style/color.html">Color</a></li>
-              <li><a href="../style/iconography.html">Iconography</a></li>
-              <li><a href="../style/writing.html">Writing Style</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../patterns/index.html">Patterns</a></div>
-            <ul>
-              <li><a href="../patterns/new-4-0.html">New in Android 4.0</a></li>
-              <li><a href="../patterns/gestures.html">Gestures</a></li>
-              <li><a href="../patterns/app-structure.html">App Structure</a></li>
-              <li><a href="../patterns/navigation.html">Navigation</a></li>
-              <li><a href="../patterns/actionbar.html">Action Bar</a></li>
-              <li><a href="../patterns/multi-pane-layouts.html">Multi-pane Layouts</a></li>
-              <li><a href="../patterns/swipe-views.html">Swipe Views</a></li>
-              <li><a href="../patterns/selection.html">Selection</a></li>
-              <li><a href="../patterns/notifications.html">Notifications</a></li>
-              <li><a href="../patterns/compatibility.html">Compatibility</a></li>
-              <li><a href="../patterns/pure-android.html">Pure Android</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../building-blocks/index.html">Building Blocks</a></div>
-            <ul>
-              <li><a href="../building-blocks/tabs.html">Tabs</a></li>
-              <li><a href="../building-blocks/lists.html">Lists</a></li>
-              <li><a href="../building-blocks/grid-lists.html">Grid Lists</a></li>
-              <li><a href="../building-blocks/scrolling.html">Scrolling</a></li>
-              <li><a href="../building-blocks/spinners.html">Spinners</a></li>
-              <li><a href="../building-blocks/buttons.html">Buttons</a></li>
-              <li><a href="../building-blocks/text-fields.html">Text Fields</a></li>
-              <li><a href="../building-blocks/seek-bars.html">Seek Bars</a></li>
-              <li><a href="../building-blocks/progress.html">Progress &amp; Activity</a></li>
-              <li><a href="../building-blocks/switches.html">Switches</a></li>
-              <li><a href="../building-blocks/dialogs.html">Dialogs</a></li>
-              <li><a href="../building-blocks/pickers.html">Pickers</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header empty"><a href="../downloads/index.html">Downloads</a></div>
-          </li>
-
-          <li>
-            <div id="back-dac-section"><a href="../../index.html">Developers</a></div>
-          </li>
-
-        </ul>
-
-        <div id="content">
-
-          
-          <div class="layout-content-row content-header">
-            <div class="layout-content-col span-9">
-              <h2>Lists</h2>
-            </div>
-            <div class="paging-links layout-content-col span-4">
-              <a href="#" class="prev-page-link">Previous</a>
-              <a href="#" class="next-page-link">Next</a>
-            </div>
-          </div>
-          
-
-          
-
-<p>Lists present multiple line items in a vertical arrangement. They can be used for data selection as
-well as drilldown navigation.</p>
-
-<div class="vspace size-1">&nbsp;</div>
-
-<div class="layout-content-row clearfix">
-  <div class="layout-content-col span-9">
-
-    <img src="../static/content/lists_main.png">
-
-  </div>
-  <div class="layout-content-col span-4 with-callouts">
-
-<ol>
-<li>
-<h4>Section Divider</h4>
-<p>Use section dividers to organize the content of your list into groups and facilitate scanning.</p>
-</li>
-<li>
-<h4>Line Items</h4>
-<p>List items can accommodate a wide range of data types in different arrangements, including
- simple single-line items, multi-line items, and custom items with icons, checkboxes, and action
- buttons.</p>
-</li>
-</ol>
-
-  </div>
-</div>
-
-
-
-          
-          <div class="layout-content-row content-footer">
-            <div class="paging-links layout-content-col span-9">&nbsp;</div>
-            <div class="paging-links layout-content-col span-4">
-              <a href="#" class="prev-page-link">Previous</a>
-              <a href="#" class="next-page-link">Next</a>
-            </div>
-          </div>
-          
-        </div>
-
-      </div>
-
-      <div id="page-footer">
-
-        <p id="copyright">
-          Except as noted, this content is licensed under
-          <a href="http://creativecommons.org/licenses/by/2.5/">
-          Creative Commons Attribution 2.5</a>.<br>
-          For details and restrictions, see the
-          <a href="http://developer.android.com/license.html">Content License</a>.
-        </p>
-
-        <p>
-          <a href="http://www.android.com/terms.html">Site Terms of Service</a> &ndash;
-          <a href="http://www.android.com/privacy.html">Privacy Policy</a> &ndash;
-          <a href="http://www.android.com/branding.html">Brand Guidelines</a>
-        </p>
-
-      </div>
-    </div>
-
-    <script src="../static/jquery-1.6.2.min.js"></script>
-    <script>
-    var SITE_ROOT = '../';
-    </script>
-    <script src="../static/default.js"></script>
-
-
-    <script type="text/javascript">
-    var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
-    document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
-    </script>
-    <script type="text/javascript">
-    var pageTracker = _gat._getTracker("UA-5831155-1");
-    pageTracker._trackPageview();
-    </script>
-  </body>
-</html>
diff --git a/docs/html/design/building-blocks/lists.jd b/docs/html/design/building-blocks/lists.jd
new file mode 100644
index 0000000..aaa86b8
--- /dev/null
+++ b/docs/html/design/building-blocks/lists.jd
@@ -0,0 +1,31 @@
+page.title=Lists
+@jd:body
+
+<p>Lists present multiple line items in a vertical arrangement. They can be used for data selection as
+well as drilldown navigation.</p>
+
+<div class="vspace size-1">&nbsp;</div>
+
+<div class="layout-content-row clearfix">
+  <div class="layout-content-col span-9">
+
+    <img src="{@docRoot}design/media/lists_main.png">
+
+  </div>
+  <div class="layout-content-col span-4 with-callouts">
+
+<ol>
+<li>
+<h4>Section Divider</h4>
+<p>Use section dividers to organize the content of your list into groups and facilitate scanning.</p>
+</li>
+<li>
+<h4>Line Items</h4>
+<p>List items can accommodate a wide range of data types in different arrangements, including
+ simple single-line items, multi-line items, and custom items with icons, checkboxes, and action
+ buttons.</p>
+</li>
+</ol>
+
+  </div>
+</div>
diff --git a/docs/html/design/building-blocks/pickers.html b/docs/html/design/building-blocks/pickers.html
deleted file mode 100644
index fc9989c..0000000
--- a/docs/html/design/building-blocks/pickers.html
+++ /dev/null
@@ -1,191 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-  <head>
-    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
-    <title>
-
-Android Design - Pickers
-    </title>
-    <link rel="shortcut icon" type="image/x-icon" href="/favicon.ico">
-    <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Roboto:regular,medium,thin,italic,mediumitalic">
-    <link rel="stylesheet" href="../static/yui-3.3.0-reset-min.css">
-    <link rel="stylesheet" href="../static/default.css">
-
-  </head>
-  <body>
-
-    <div id="page-container">
-
-      <div id="page-header"><a href="../index.html">Android Design</a></div>
-
-      <div id="main-row">
-
-        <ul id="nav">
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../index.html">Get Started</a></div>
-            <ul>
-              <li><a href="../get-started/creative-vision.html">Creative Vision</a></li>
-              <li><a href="../get-started/principles.html">Design Principles</a></li>
-              <li><a href="../get-started/ui-overview.html">UI Overview</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../style/index.html">Style</a></div>
-            <ul>
-              <li><a href="../style/devices-displays.html">Devices and Displays</a></li>
-              <li><a href="../style/themes.html">Themes</a></li>
-              <li><a href="../style/touch-feedback.html">Touch Feedback</a></li>
-              <li><a href="../style/metrics-grids.html">Metrics and Grids</a></li>
-              <li><a href="../style/typography.html">Typography</a></li>
-              <li><a href="../style/color.html">Color</a></li>
-              <li><a href="../style/iconography.html">Iconography</a></li>
-              <li><a href="../style/writing.html">Writing Style</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../patterns/index.html">Patterns</a></div>
-            <ul>
-              <li><a href="../patterns/new-4-0.html">New in Android 4.0</a></li>
-              <li><a href="../patterns/gestures.html">Gestures</a></li>
-              <li><a href="../patterns/app-structure.html">App Structure</a></li>
-              <li><a href="../patterns/navigation.html">Navigation</a></li>
-              <li><a href="../patterns/actionbar.html">Action Bar</a></li>
-              <li><a href="../patterns/multi-pane-layouts.html">Multi-pane Layouts</a></li>
-              <li><a href="../patterns/swipe-views.html">Swipe Views</a></li>
-              <li><a href="../patterns/selection.html">Selection</a></li>
-              <li><a href="../patterns/notifications.html">Notifications</a></li>
-              <li><a href="../patterns/compatibility.html">Compatibility</a></li>
-              <li><a href="../patterns/pure-android.html">Pure Android</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../building-blocks/index.html">Building Blocks</a></div>
-            <ul>
-              <li><a href="../building-blocks/tabs.html">Tabs</a></li>
-              <li><a href="../building-blocks/lists.html">Lists</a></li>
-              <li><a href="../building-blocks/grid-lists.html">Grid Lists</a></li>
-              <li><a href="../building-blocks/scrolling.html">Scrolling</a></li>
-              <li><a href="../building-blocks/spinners.html">Spinners</a></li>
-              <li><a href="../building-blocks/buttons.html">Buttons</a></li>
-              <li><a href="../building-blocks/text-fields.html">Text Fields</a></li>
-              <li><a href="../building-blocks/seek-bars.html">Seek Bars</a></li>
-              <li><a href="../building-blocks/progress.html">Progress &amp; Activity</a></li>
-              <li><a href="../building-blocks/switches.html">Switches</a></li>
-              <li><a href="../building-blocks/dialogs.html">Dialogs</a></li>
-              <li><a href="../building-blocks/pickers.html">Pickers</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header empty"><a href="../downloads/index.html">Downloads</a></div>
-          </li>
-
-          <li>
-            <div id="back-dac-section"><a href="../../index.html">Developers</a></div>
-          </li>
-
-        </ul>
-
-        <div id="content">
-
-          
-          <div class="layout-content-row content-header">
-            <div class="layout-content-col span-9">
-              <h2>Pickers</h2>
-            </div>
-            <div class="paging-links layout-content-col span-4">
-              <a href="#" class="prev-page-link">Previous</a>
-              <a href="#" class="next-page-link">Next</a>
-            </div>
-          </div>
-          
-
-          
-
-<p>Pickers provide a simple way to select a single value from a set. In addition to touching the
-up/down arrow buttons, it's possible to set the desired value from the keyboard or via a swipe
-gesture.</p>
-
-<div class="layout-content-row">
-  <div class="layout-content-col span-2">&nbsp;</div>
-  <div class="layout-content-col span-6">
-
-    <img src="../static/content/picker_space.png">
-
-  </div>
-  <div class="layout-content-col span-5">
-
-<h4>Space considerations</h4>
-<p>Pickers can be used inline on a form, but their relatively large footprint is best suited for
-display in a dialog. For inline display, consider using more compact controls such as text fields or
-spinners.</p>
-
-  </div>
-</div>
-
-<h2 id="date-time">Date and time pickers</h2>
-
-<p>Android provides these as ready-to-use dialogs. Each picker is a dialog with a set of controls for
-entering the parts of the date (month, day, year) or time (hour, minute, AM/PM). Using these in your
-app helps ensure that a user's specification of a data or time input is valid and formatted
-correctly. The format of a time and date picker adjusts automatically to the locale.</p>
-
-<img src="../static/content/picker_datetime.png">
-
-
-
-
-
-          
-          <div class="layout-content-row content-footer">
-            <div class="paging-links layout-content-col span-9">&nbsp;</div>
-            <div class="paging-links layout-content-col span-4">
-              <a href="#" class="prev-page-link">Previous</a>
-              <a href="#" class="next-page-link">Next</a>
-            </div>
-          </div>
-          
-        </div>
-
-      </div>
-
-      <div id="page-footer">
-
-        <p id="copyright">
-          Except as noted, this content is licensed under
-          <a href="http://creativecommons.org/licenses/by/2.5/">
-          Creative Commons Attribution 2.5</a>.<br>
-          For details and restrictions, see the
-          <a href="http://developer.android.com/license.html">Content License</a>.
-        </p>
-
-        <p>
-          <a href="http://www.android.com/terms.html">Site Terms of Service</a> &ndash;
-          <a href="http://www.android.com/privacy.html">Privacy Policy</a> &ndash;
-          <a href="http://www.android.com/branding.html">Brand Guidelines</a>
-        </p>
-
-      </div>
-    </div>
-
-    <script src="../static/jquery-1.6.2.min.js"></script>
-    <script>
-    var SITE_ROOT = '../';
-    </script>
-    <script src="../static/default.js"></script>
-
-
-    <script type="text/javascript">
-    var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
-    document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
-    </script>
-    <script type="text/javascript">
-    var pageTracker = _gat._getTracker("UA-5831155-1");
-    pageTracker._trackPageview();
-    </script>
-  </body>
-</html>
diff --git a/docs/html/design/building-blocks/pickers.jd b/docs/html/design/building-blocks/pickers.jd
new file mode 100644
index 0000000..85f2187
--- /dev/null
+++ b/docs/html/design/building-blocks/pickers.jd
@@ -0,0 +1,32 @@
+page.title=Pickers
+@jd:body
+
+<p>Pickers provide a simple way to select a single value from a set. In addition to touching the
+up/down arrow buttons, it's possible to set the desired value from the keyboard or via a swipe
+gesture.</p>
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-2">&nbsp;</div>
+  <div class="layout-content-col span-6">
+
+    <img src="{@docRoot}design/media/picker_space.png">
+
+  </div>
+  <div class="layout-content-col span-5">
+
+<h4>Space considerations</h4>
+<p>Pickers can be used inline on a form, but their relatively large footprint is best suited for
+display in a dialog. For inline display, consider using more compact controls such as text fields or
+spinners.</p>
+
+  </div>
+</div>
+
+<h2 id="date-time">Date and time pickers</h2>
+
+<p>Android provides these as ready-to-use dialogs. Each picker is a dialog with a set of controls for
+entering the parts of the date (month, day, year) or time (hour, minute, AM/PM). Using these in your
+app helps ensure that a user's specification of a data or time input is valid and formatted
+correctly. The format of a time and date picker adjusts automatically to the locale.</p>
+
+<img src="{@docRoot}design/media/picker_datetime.png">
diff --git a/docs/html/design/building-blocks/progress.html b/docs/html/design/building-blocks/progress.html
deleted file mode 100644
index 32183bc..0000000
--- a/docs/html/design/building-blocks/progress.html
+++ /dev/null
@@ -1,238 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-  <head>
-    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
-    <title>
-
-Android Design - Progress and Activity
-    </title>
-    <link rel="shortcut icon" type="image/x-icon" href="/favicon.ico">
-    <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Roboto:regular,medium,thin,italic,mediumitalic">
-    <link rel="stylesheet" href="../static/yui-3.3.0-reset-min.css">
-    <link rel="stylesheet" href="../static/default.css">
-
-  </head>
-  <body>
-
-    <div id="page-container">
-
-      <div id="page-header"><a href="../index.html">Android Design</a></div>
-
-      <div id="main-row">
-
-        <ul id="nav">
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../index.html">Get Started</a></div>
-            <ul>
-              <li><a href="../get-started/creative-vision.html">Creative Vision</a></li>
-              <li><a href="../get-started/principles.html">Design Principles</a></li>
-              <li><a href="../get-started/ui-overview.html">UI Overview</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../style/index.html">Style</a></div>
-            <ul>
-              <li><a href="../style/devices-displays.html">Devices and Displays</a></li>
-              <li><a href="../style/themes.html">Themes</a></li>
-              <li><a href="../style/touch-feedback.html">Touch Feedback</a></li>
-              <li><a href="../style/metrics-grids.html">Metrics and Grids</a></li>
-              <li><a href="../style/typography.html">Typography</a></li>
-              <li><a href="../style/color.html">Color</a></li>
-              <li><a href="../style/iconography.html">Iconography</a></li>
-              <li><a href="../style/writing.html">Writing Style</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../patterns/index.html">Patterns</a></div>
-            <ul>
-              <li><a href="../patterns/new-4-0.html">New in Android 4.0</a></li>
-              <li><a href="../patterns/gestures.html">Gestures</a></li>
-              <li><a href="../patterns/app-structure.html">App Structure</a></li>
-              <li><a href="../patterns/navigation.html">Navigation</a></li>
-              <li><a href="../patterns/actionbar.html">Action Bar</a></li>
-              <li><a href="../patterns/multi-pane-layouts.html">Multi-pane Layouts</a></li>
-              <li><a href="../patterns/swipe-views.html">Swipe Views</a></li>
-              <li><a href="../patterns/selection.html">Selection</a></li>
-              <li><a href="../patterns/notifications.html">Notifications</a></li>
-              <li><a href="../patterns/compatibility.html">Compatibility</a></li>
-              <li><a href="../patterns/pure-android.html">Pure Android</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../building-blocks/index.html">Building Blocks</a></div>
-            <ul>
-              <li><a href="../building-blocks/tabs.html">Tabs</a></li>
-              <li><a href="../building-blocks/lists.html">Lists</a></li>
-              <li><a href="../building-blocks/grid-lists.html">Grid Lists</a></li>
-              <li><a href="../building-blocks/scrolling.html">Scrolling</a></li>
-              <li><a href="../building-blocks/spinners.html">Spinners</a></li>
-              <li><a href="../building-blocks/buttons.html">Buttons</a></li>
-              <li><a href="../building-blocks/text-fields.html">Text Fields</a></li>
-              <li><a href="../building-blocks/seek-bars.html">Seek Bars</a></li>
-              <li><a href="../building-blocks/progress.html">Progress &amp; Activity</a></li>
-              <li><a href="../building-blocks/switches.html">Switches</a></li>
-              <li><a href="../building-blocks/dialogs.html">Dialogs</a></li>
-              <li><a href="../building-blocks/pickers.html">Pickers</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header empty"><a href="../downloads/index.html">Downloads</a></div>
-          </li>
-
-          <li>
-            <div id="back-dac-section"><a href="../../index.html">Developers</a></div>
-          </li>
-
-        </ul>
-
-        <div id="content">
-
-          
-
-
-          
-
-<div class="layout-content-row content-header">
-  <div class="layout-content-col span-9">
-    <h2 id="system">Feedback</h2>
-  </div>
-  <div class="paging-links layout-content-col span-4">
-    <a href="#" class="prev-page-link">Previous</a>
-    <a href="#" class="next-page-link">Next</a>
-  </div>
-</div>
-
-<p>When an operation of interest to the user is taking place over a relatively long period of time,
-provide visual feedback that it's still happening and in the process of being completed.</p>
-<h2 id="progress">Progress</h2>
-
-<p>If you know the percentage of the operation that has been completed, use a determinate progress bar
-to give the user a sense of how much longer it will take.</p>
-
-<img src="../static/content/progress_download.png">
-
-<p>The progress bar should always travel from 0% to 100% completion. Avoid setting the bar to a lower
-value than a previous value, or using the same progress bar to represent the progress of multiple
-events, since doing so makes the display meaningless. If you're not sure how long a particular
-operation will take, use an indeterminate progress indicator.</p>
-
-<div class="vspace size-2">&nbsp;</div>
-
-<img src="../static/content/progress_themes.png">
-<div class="figure-caption">
-  Progress bar in Holo Dark and Holo Light.
-</div>
-
-<h2 id="activity">Activity</h2>
-
-<p>If you don't know how much longer an operation will continue, use an indeterminate progress
-indicator. There are two styles available: a flat bar and a circle. Use the one that best fits the
-available space.</p>
-
-
-<div class="layout-content-row">
-  <div class="layout-content-col span-6">
-
-    <img src="../static/content/progress_activity.png">
-
-  </div>
-  <div class="layout-content-col span-7 with-callouts">
-
-    <ol>
-      <li class="value-1"><h4>Activity bar (shown with the Holo Dark theme)</h4>
-        <p>
-
-An indeterminate activity bar is used at the start of an application download because Market hasn't
-been able to contact the server yet, and it's not possible to determine how long it will take for
-the download to begin.
-
-        </p>
-      </li>
-    </ol>
-
-  </div>
-</div>
-
-<div class="layout-content-row">
-  <div class="layout-content-col span-6">
-
-    <img src="../static/content/progress_activity2.png">
-
-  </div>
-  <div class="layout-content-col span-7 with-callouts">
-
-    <ol>
-      <li class="value-2"><h4>Activity circle (shown with the Holo Light theme)</h4>
-        <p>
-
-An indeterminate activity circle is used in the Gmail application when a message is being
-loaded because it's not possible to determine how long it will take to download the email.
-
-        </p>
-      </li>
-    </ol>
-
-  </div>
-</div>
-
-<p>You should only use one activity indicator on screen per activity, and it should appropriately sized
-for the surrounding context. For example, the largest activity circle works well when displayed in a
-blank content area, but not in a smaller dialog box.</p>
-
-
-
-
-          
-          <div class="layout-content-row content-footer">
-            <div class="paging-links layout-content-col span-9">&nbsp;</div>
-            <div class="paging-links layout-content-col span-4">
-              <a href="#" class="prev-page-link">Previous</a>
-              <a href="#" class="next-page-link">Next</a>
-            </div>
-          </div>
-          
-        </div>
-
-      </div>
-
-      <div id="page-footer">
-
-        <p id="copyright">
-          Except as noted, this content is licensed under
-          <a href="http://creativecommons.org/licenses/by/2.5/">
-          Creative Commons Attribution 2.5</a>.<br>
-          For details and restrictions, see the
-          <a href="http://developer.android.com/license.html">Content License</a>.
-        </p>
-
-        <p>
-          <a href="http://www.android.com/terms.html">Site Terms of Service</a> &ndash;
-          <a href="http://www.android.com/privacy.html">Privacy Policy</a> &ndash;
-          <a href="http://www.android.com/branding.html">Brand Guidelines</a>
-        </p>
-
-      </div>
-    </div>
-
-    <script src="../static/jquery-1.6.2.min.js"></script>
-    <script>
-    var SITE_ROOT = '../';
-    </script>
-    <script src="../static/default.js"></script>
-
-
-    <script type="text/javascript">
-    var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
-    document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
-    </script>
-    <script type="text/javascript">
-    var pageTracker = _gat._getTracker("UA-5831155-1");
-    pageTracker._trackPageview();
-    </script>
-  </body>
-</html>
diff --git a/docs/html/design/building-blocks/progress.jd b/docs/html/design/building-blocks/progress.jd
new file mode 100644
index 0000000..dc3ded1
--- /dev/null
+++ b/docs/html/design/building-blocks/progress.jd
@@ -0,0 +1,80 @@
+page.title=Progress and Activity
+header.title=Feedback
+@jd:body
+
+<p>When an operation of interest to the user is taking place over a relatively long period of time,
+provide visual feedback that it's still happening and in the process of being completed.</p>
+<h2 id="progress">Progress</h2>
+
+<p>If you know the percentage of the operation that has been completed, use a determinate progress bar
+to give the user a sense of how much longer it will take.</p>
+
+<img src="{@docRoot}design/media/progress_download.png">
+
+<p>The progress bar should always travel from 0% to 100% completion. Avoid setting the bar to a lower
+value than a previous value, or using the same progress bar to represent the progress of multiple
+events, since doing so makes the display meaningless. If you're not sure how long a particular
+operation will take, use an indeterminate progress indicator.</p>
+
+<div class="vspace size-2">&nbsp;</div>
+
+<img src="{@docRoot}design/media/progress_themes.png">
+<div class="figure-caption">
+  Progress bar in Holo Dark and Holo Light.
+</div>
+
+<h2 id="activity">Activity</h2>
+
+<p>If you don't know how much longer an operation will continue, use an indeterminate progress
+indicator. There are two styles available: a flat bar and a circle. Use the one that best fits the
+available space.</p>
+
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-6">
+
+    <img src="{@docRoot}design/media/progress_activity.png">
+
+  </div>
+  <div class="layout-content-col span-7 with-callouts">
+
+    <ol>
+      <li class="value-1"><h4>Activity bar (shown with the Holo Dark theme)</h4>
+        <p>
+
+An indeterminate activity bar is used at the start of an application download because Google Play hasn't
+been able to contact the server yet, and it's not possible to determine how long it will take for
+the download to begin.
+
+        </p>
+      </li>
+    </ol>
+
+  </div>
+</div>
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-6">
+
+    <img src="{@docRoot}design/media/progress_activity2.png">
+
+  </div>
+  <div class="layout-content-col span-7 with-callouts">
+
+    <ol>
+      <li class="value-2"><h4>Activity circle (shown with the Holo Light theme)</h4>
+        <p>
+
+An indeterminate activity circle is used in the Gmail application when a message is being
+loaded because it's not possible to determine how long it will take to download the email.
+
+        </p>
+      </li>
+    </ol>
+
+  </div>
+</div>
+
+<p>You should only use one activity indicator on screen per activity, and it should appropriately sized
+for the surrounding context. For example, the largest activity circle works well when displayed in a
+blank content area, but not in a smaller dialog box.</p>
diff --git a/docs/html/design/building-blocks/scrolling.html b/docs/html/design/building-blocks/scrolling.html
deleted file mode 100644
index 3599a97..0000000
--- a/docs/html/design/building-blocks/scrolling.html
+++ /dev/null
@@ -1,194 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-  <head>
-    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
-    <title>
-
-Android Design - Scrolling
-    </title>
-    <link rel="shortcut icon" type="image/x-icon" href="/favicon.ico">
-    <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Roboto:regular,medium,thin,italic,mediumitalic">
-    <link rel="stylesheet" href="../static/yui-3.3.0-reset-min.css">
-    <link rel="stylesheet" href="../static/default.css">
-
-  </head>
-  <body>
-
-    <div id="page-container">
-
-      <div id="page-header"><a href="../index.html">Android Design</a></div>
-
-      <div id="main-row">
-
-        <ul id="nav">
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../index.html">Get Started</a></div>
-            <ul>
-              <li><a href="../get-started/creative-vision.html">Creative Vision</a></li>
-              <li><a href="../get-started/principles.html">Design Principles</a></li>
-              <li><a href="../get-started/ui-overview.html">UI Overview</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../style/index.html">Style</a></div>
-            <ul>
-              <li><a href="../style/devices-displays.html">Devices and Displays</a></li>
-              <li><a href="../style/themes.html">Themes</a></li>
-              <li><a href="../style/touch-feedback.html">Touch Feedback</a></li>
-              <li><a href="../style/metrics-grids.html">Metrics and Grids</a></li>
-              <li><a href="../style/typography.html">Typography</a></li>
-              <li><a href="../style/color.html">Color</a></li>
-              <li><a href="../style/iconography.html">Iconography</a></li>
-              <li><a href="../style/writing.html">Writing Style</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../patterns/index.html">Patterns</a></div>
-            <ul>
-              <li><a href="../patterns/new-4-0.html">New in Android 4.0</a></li>
-              <li><a href="../patterns/gestures.html">Gestures</a></li>
-              <li><a href="../patterns/app-structure.html">App Structure</a></li>
-              <li><a href="../patterns/navigation.html">Navigation</a></li>
-              <li><a href="../patterns/actionbar.html">Action Bar</a></li>
-              <li><a href="../patterns/multi-pane-layouts.html">Multi-pane Layouts</a></li>
-              <li><a href="../patterns/swipe-views.html">Swipe Views</a></li>
-              <li><a href="../patterns/selection.html">Selection</a></li>
-              <li><a href="../patterns/notifications.html">Notifications</a></li>
-              <li><a href="../patterns/compatibility.html">Compatibility</a></li>
-              <li><a href="../patterns/pure-android.html">Pure Android</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../building-blocks/index.html">Building Blocks</a></div>
-            <ul>
-              <li><a href="../building-blocks/tabs.html">Tabs</a></li>
-              <li><a href="../building-blocks/lists.html">Lists</a></li>
-              <li><a href="../building-blocks/grid-lists.html">Grid Lists</a></li>
-              <li><a href="../building-blocks/scrolling.html">Scrolling</a></li>
-              <li><a href="../building-blocks/spinners.html">Spinners</a></li>
-              <li><a href="../building-blocks/buttons.html">Buttons</a></li>
-              <li><a href="../building-blocks/text-fields.html">Text Fields</a></li>
-              <li><a href="../building-blocks/seek-bars.html">Seek Bars</a></li>
-              <li><a href="../building-blocks/progress.html">Progress &amp; Activity</a></li>
-              <li><a href="../building-blocks/switches.html">Switches</a></li>
-              <li><a href="../building-blocks/dialogs.html">Dialogs</a></li>
-              <li><a href="../building-blocks/pickers.html">Pickers</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header empty"><a href="../downloads/index.html">Downloads</a></div>
-          </li>
-
-          <li>
-            <div id="back-dac-section"><a href="../../index.html">Developers</a></div>
-          </li>
-
-        </ul>
-
-        <div id="content">
-
-          
-          <div class="layout-content-row content-header">
-            <div class="layout-content-col span-9">
-              <h2>Scrolling</h2>
-            </div>
-            <div class="paging-links layout-content-col span-4">
-              <a href="#" class="prev-page-link">Previous</a>
-              <a href="#" class="next-page-link">Next</a>
-            </div>
-          </div>
-          
-
-          
-
-<p>Scrolling allows the user to navigate to content in the overflow using a swipe gesture. The
-scrolling speed is proportional to the speed of the gesture.</p>
-<h2 id="indicator">Scroll Indicator</h2>
-
-<p>Appears during scrolling to indicate what portion of the content is currently in view.</p>
-
-<div class="framed-galaxynexus-land-span-13">
-  <video class="play-on-hover" autoplay>
-    <source src="../static/content/scroll_indicator.mp4" type="video/mp4">
-    <source src="../static/content/scroll_indicator.webm" type="video/webm">
-    <source src="../static/content/scroll_indicator.ogv" type="video/ogg">
-  </video>
-</div>
-<div class="figure-caption">
-  <div class="video-instructions">&nbsp;</div>
-</div>
-
-<h2 id="index-scrolling">Index Scrolling</h2>
-
-<p>In addition to traditional scrolling, a long alphabetical list can also offer index scrolling: a way
-to quickly navigate to the items that begin with a particular letter. With index scrolling, a scroll
-indicator appears even when the user isn't scrolling. Touching or dragging it causes the current
-letter to pop up in a prominent way.</p>
-
-<div class="framed-galaxynexus-land-span-13">
-  <video class="play-on-hover" autoplay>
-    <source src="../static/content/scroll_index.mp4" type="video/mp4">
-    <source src="../static/content/scroll_index.webm" type="video/webm">
-    <source src="../static/content/scroll_index.ogv" type="video/ogg">
-  </video>
-</div>
-<div class="figure-caption">
-  <div class="video-instructions">&nbsp;</div>
-</div>
-
-
-
-          
-          <div class="layout-content-row content-footer">
-            <div class="paging-links layout-content-col span-9">&nbsp;</div>
-            <div class="paging-links layout-content-col span-4">
-              <a href="#" class="prev-page-link">Previous</a>
-              <a href="#" class="next-page-link">Next</a>
-            </div>
-          </div>
-          
-        </div>
-
-      </div>
-
-      <div id="page-footer">
-
-        <p id="copyright">
-          Except as noted, this content is licensed under
-          <a href="http://creativecommons.org/licenses/by/2.5/">
-          Creative Commons Attribution 2.5</a>.<br>
-          For details and restrictions, see the
-          <a href="http://developer.android.com/license.html">Content License</a>.
-        </p>
-
-        <p>
-          <a href="http://www.android.com/terms.html">Site Terms of Service</a> &ndash;
-          <a href="http://www.android.com/privacy.html">Privacy Policy</a> &ndash;
-          <a href="http://www.android.com/branding.html">Brand Guidelines</a>
-        </p>
-
-      </div>
-    </div>
-
-    <script src="../static/jquery-1.6.2.min.js"></script>
-    <script>
-    var SITE_ROOT = '../';
-    </script>
-    <script src="../static/default.js"></script>
-
-
-    <script type="text/javascript">
-    var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
-    document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
-    </script>
-    <script type="text/javascript">
-    var pageTracker = _gat._getTracker("UA-5831155-1");
-    pageTracker._trackPageview();
-    </script>
-  </body>
-</html>
diff --git a/docs/html/design/building-blocks/scrolling.jd b/docs/html/design/building-blocks/scrolling.jd
new file mode 100644
index 0000000..7695157
--- /dev/null
+++ b/docs/html/design/building-blocks/scrolling.jd
@@ -0,0 +1,37 @@
+page.title=Scrolling
+@jd:body
+
+<p>Scrolling allows the user to navigate to content in the overflow using a swipe gesture. The
+scrolling speed is proportional to the speed of the gesture.</p>
+<h2 id="indicator">Scroll Indicator</h2>
+
+<p>Appears during scrolling to indicate what portion of the content is currently in view.</p>
+
+<div class="framed-galaxynexus-land-span-13">
+  <video class="play-on-hover" autoplay>
+    <source src="{@docRoot}design/media/scroll_indicator.mp4" type="video/mp4">
+    <source src="{@docRoot}design/media/scroll_indicator.webm" type="video/webm">
+    <source src="{@docRoot}design/media/scroll_indicator.ogv" type="video/ogg">
+  </video>
+</div>
+<div class="figure-caption">
+  <div class="video-instructions">&nbsp;</div>
+</div>
+
+<h2 id="index-scrolling">Index Scrolling</h2>
+
+<p>In addition to traditional scrolling, a long alphabetical list can also offer index scrolling: a way
+to quickly navigate to the items that begin with a particular letter. With index scrolling, a scroll
+indicator appears even when the user isn't scrolling. Touching or dragging it causes the current
+letter to pop up in a prominent way.</p>
+
+<div class="framed-galaxynexus-land-span-13">
+  <video class="play-on-hover" autoplay>
+    <source src="{@docRoot}design/media/scroll_index.mp4" type="video/mp4">
+    <source src="{@docRoot}design/media/scroll_index.webm" type="video/webm">
+    <source src="{@docRoot}design/media/scroll_index.ogv" type="video/ogg">
+  </video>
+</div>
+<div class="figure-caption">
+  <div class="video-instructions">&nbsp;</div>
+</div>
diff --git a/docs/html/design/building-blocks/seek-bars.html b/docs/html/design/building-blocks/seek-bars.html
deleted file mode 100644
index aef1823..0000000
--- a/docs/html/design/building-blocks/seek-bars.html
+++ /dev/null
@@ -1,194 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-  <head>
-    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
-    <title>
-
-Android Design - Seek Bars and Sliders
-    </title>
-    <link rel="shortcut icon" type="image/x-icon" href="/favicon.ico">
-    <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Roboto:regular,medium,thin,italic,mediumitalic">
-    <link rel="stylesheet" href="../static/yui-3.3.0-reset-min.css">
-    <link rel="stylesheet" href="../static/default.css">
-
-  </head>
-  <body>
-
-    <div id="page-container">
-
-      <div id="page-header"><a href="../index.html">Android Design</a></div>
-
-      <div id="main-row">
-
-        <ul id="nav">
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../index.html">Get Started</a></div>
-            <ul>
-              <li><a href="../get-started/creative-vision.html">Creative Vision</a></li>
-              <li><a href="../get-started/principles.html">Design Principles</a></li>
-              <li><a href="../get-started/ui-overview.html">UI Overview</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../style/index.html">Style</a></div>
-            <ul>
-              <li><a href="../style/devices-displays.html">Devices and Displays</a></li>
-              <li><a href="../style/themes.html">Themes</a></li>
-              <li><a href="../style/touch-feedback.html">Touch Feedback</a></li>
-              <li><a href="../style/metrics-grids.html">Metrics and Grids</a></li>
-              <li><a href="../style/typography.html">Typography</a></li>
-              <li><a href="../style/color.html">Color</a></li>
-              <li><a href="../style/iconography.html">Iconography</a></li>
-              <li><a href="../style/writing.html">Writing Style</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../patterns/index.html">Patterns</a></div>
-            <ul>
-              <li><a href="../patterns/new-4-0.html">New in Android 4.0</a></li>
-              <li><a href="../patterns/gestures.html">Gestures</a></li>
-              <li><a href="../patterns/app-structure.html">App Structure</a></li>
-              <li><a href="../patterns/navigation.html">Navigation</a></li>
-              <li><a href="../patterns/actionbar.html">Action Bar</a></li>
-              <li><a href="../patterns/multi-pane-layouts.html">Multi-pane Layouts</a></li>
-              <li><a href="../patterns/swipe-views.html">Swipe Views</a></li>
-              <li><a href="../patterns/selection.html">Selection</a></li>
-              <li><a href="../patterns/notifications.html">Notifications</a></li>
-              <li><a href="../patterns/compatibility.html">Compatibility</a></li>
-              <li><a href="../patterns/pure-android.html">Pure Android</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../building-blocks/index.html">Building Blocks</a></div>
-            <ul>
-              <li><a href="../building-blocks/tabs.html">Tabs</a></li>
-              <li><a href="../building-blocks/lists.html">Lists</a></li>
-              <li><a href="../building-blocks/grid-lists.html">Grid Lists</a></li>
-              <li><a href="../building-blocks/scrolling.html">Scrolling</a></li>
-              <li><a href="../building-blocks/spinners.html">Spinners</a></li>
-              <li><a href="../building-blocks/buttons.html">Buttons</a></li>
-              <li><a href="../building-blocks/text-fields.html">Text Fields</a></li>
-              <li><a href="../building-blocks/seek-bars.html">Seek Bars</a></li>
-              <li><a href="../building-blocks/progress.html">Progress &amp; Activity</a></li>
-              <li><a href="../building-blocks/switches.html">Switches</a></li>
-              <li><a href="../building-blocks/dialogs.html">Dialogs</a></li>
-              <li><a href="../building-blocks/pickers.html">Pickers</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header empty"><a href="../downloads/index.html">Downloads</a></div>
-          </li>
-
-          <li>
-            <div id="back-dac-section"><a href="../../index.html">Developers</a></div>
-          </li>
-
-        </ul>
-
-        <div id="content">
-
-          
-          <div class="layout-content-row content-header">
-            <div class="layout-content-col span-9">
-              <h2>Seek Bars and Sliders</h2>
-            </div>
-            <div class="paging-links layout-content-col span-4">
-              <a href="#" class="prev-page-link">Previous</a>
-              <a href="#" class="next-page-link">Next</a>
-            </div>
-          </div>
-          
-
-          
-
-<p>Interactive sliders make it possible to select a value from a continuous or discrete range of values
-by moving the slider thumb. The smallest value is to the left, the largest to the right. The
-interactive nature of the slider makes it a great choice for settings that reflect intensity levels,
-such as volume, brightness, or color saturation.</p>
-
-<div class="layout-content-row">
-  <div class="layout-content-col span-9">
-
-    <img src="../static/content/seekbar_example.png">
-
-  </div>
-  <div class="layout-content-col span-4">
-
-<div class="vspace size-2">&nbsp;</div>
-
-<h4>Example</h4>
-<p>Interactive slider to set the ringer volume. The value can either be set through the hardware volume controls or interactively via a gesture.</p>
-
-  </div>
-</div>
-
-
-<div class="layout-content-row">
-  <div class="layout-content-col span-9">
-
-    <img src="../static/content/seekbar_style.png">
-    <div class="figure-caption">
-      Seek bars in Holo Light &amp; Dark
-    </div>
-
-  </div>
-  <div class="layout-content-col span-4">&nbsp;</div>
-</div>
-
-
-
-
-          
-          <div class="layout-content-row content-footer">
-            <div class="paging-links layout-content-col span-9">&nbsp;</div>
-            <div class="paging-links layout-content-col span-4">
-              <a href="#" class="prev-page-link">Previous</a>
-              <a href="#" class="next-page-link">Next</a>
-            </div>
-          </div>
-          
-        </div>
-
-      </div>
-
-      <div id="page-footer">
-
-        <p id="copyright">
-          Except as noted, this content is licensed under
-          <a href="http://creativecommons.org/licenses/by/2.5/">
-          Creative Commons Attribution 2.5</a>.<br>
-          For details and restrictions, see the
-          <a href="http://developer.android.com/license.html">Content License</a>.
-        </p>
-
-        <p>
-          <a href="http://www.android.com/terms.html">Site Terms of Service</a> &ndash;
-          <a href="http://www.android.com/privacy.html">Privacy Policy</a> &ndash;
-          <a href="http://www.android.com/branding.html">Brand Guidelines</a>
-        </p>
-
-      </div>
-    </div>
-
-    <script src="../static/jquery-1.6.2.min.js"></script>
-    <script>
-    var SITE_ROOT = '../';
-    </script>
-    <script src="../static/default.js"></script>
-
-
-    <script type="text/javascript">
-    var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
-    document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
-    </script>
-    <script type="text/javascript">
-    var pageTracker = _gat._getTracker("UA-5831155-1");
-    pageTracker._trackPageview();
-    </script>
-  </body>
-</html>
diff --git a/docs/html/design/building-blocks/seek-bars.jd b/docs/html/design/building-blocks/seek-bars.jd
new file mode 100644
index 0000000..3407ddd
--- /dev/null
+++ b/docs/html/design/building-blocks/seek-bars.jd
@@ -0,0 +1,36 @@
+page.title=Seek Bars and Sliders
+@jd:body
+
+<p>Interactive sliders make it possible to select a value from a continuous or discrete range of values
+by moving the slider thumb. The smallest value is to the left, the largest to the right. The
+interactive nature of the slider makes it a great choice for settings that reflect intensity levels,
+such as volume, brightness, or color saturation.</p>
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-9">
+
+    <img src="{@docRoot}design/media/seekbar_example.png">
+
+  </div>
+  <div class="layout-content-col span-4">
+
+<div class="vspace size-2">&nbsp;</div>
+
+<h4>Example</h4>
+<p>Interactive slider to set the ringer volume. The value can either be set through the hardware volume controls or interactively via a gesture.</p>
+
+  </div>
+</div>
+
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-9">
+
+    <img src="{@docRoot}design/media/seekbar_style.png">
+    <div class="figure-caption">
+      Seek bars in Holo Light &amp; Dark
+    </div>
+
+  </div>
+  <div class="layout-content-col span-4">&nbsp;</div>
+</div>
diff --git a/docs/html/design/building-blocks/spinners.html b/docs/html/design/building-blocks/spinners.html
deleted file mode 100644
index 5ef9d04..0000000
--- a/docs/html/design/building-blocks/spinners.html
+++ /dev/null
@@ -1,194 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-  <head>
-    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
-    <title>
-
-Android Design - Spinners
-    </title>
-    <link rel="shortcut icon" type="image/x-icon" href="/favicon.ico">
-    <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Roboto:regular,medium,thin,italic,mediumitalic">
-    <link rel="stylesheet" href="../static/yui-3.3.0-reset-min.css">
-    <link rel="stylesheet" href="../static/default.css">
-
-  </head>
-  <body>
-
-    <div id="page-container">
-
-      <div id="page-header"><a href="../index.html">Android Design</a></div>
-
-      <div id="main-row">
-
-        <ul id="nav">
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../index.html">Get Started</a></div>
-            <ul>
-              <li><a href="../get-started/creative-vision.html">Creative Vision</a></li>
-              <li><a href="../get-started/principles.html">Design Principles</a></li>
-              <li><a href="../get-started/ui-overview.html">UI Overview</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../style/index.html">Style</a></div>
-            <ul>
-              <li><a href="../style/devices-displays.html">Devices and Displays</a></li>
-              <li><a href="../style/themes.html">Themes</a></li>
-              <li><a href="../style/touch-feedback.html">Touch Feedback</a></li>
-              <li><a href="../style/metrics-grids.html">Metrics and Grids</a></li>
-              <li><a href="../style/typography.html">Typography</a></li>
-              <li><a href="../style/color.html">Color</a></li>
-              <li><a href="../style/iconography.html">Iconography</a></li>
-              <li><a href="../style/writing.html">Writing Style</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../patterns/index.html">Patterns</a></div>
-            <ul>
-              <li><a href="../patterns/new-4-0.html">New in Android 4.0</a></li>
-              <li><a href="../patterns/gestures.html">Gestures</a></li>
-              <li><a href="../patterns/app-structure.html">App Structure</a></li>
-              <li><a href="../patterns/navigation.html">Navigation</a></li>
-              <li><a href="../patterns/actionbar.html">Action Bar</a></li>
-              <li><a href="../patterns/multi-pane-layouts.html">Multi-pane Layouts</a></li>
-              <li><a href="../patterns/swipe-views.html">Swipe Views</a></li>
-              <li><a href="../patterns/selection.html">Selection</a></li>
-              <li><a href="../patterns/notifications.html">Notifications</a></li>
-              <li><a href="../patterns/compatibility.html">Compatibility</a></li>
-              <li><a href="../patterns/pure-android.html">Pure Android</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../building-blocks/index.html">Building Blocks</a></div>
-            <ul>
-              <li><a href="../building-blocks/tabs.html">Tabs</a></li>
-              <li><a href="../building-blocks/lists.html">Lists</a></li>
-              <li><a href="../building-blocks/grid-lists.html">Grid Lists</a></li>
-              <li><a href="../building-blocks/scrolling.html">Scrolling</a></li>
-              <li><a href="../building-blocks/spinners.html">Spinners</a></li>
-              <li><a href="../building-blocks/buttons.html">Buttons</a></li>
-              <li><a href="../building-blocks/text-fields.html">Text Fields</a></li>
-              <li><a href="../building-blocks/seek-bars.html">Seek Bars</a></li>
-              <li><a href="../building-blocks/progress.html">Progress &amp; Activity</a></li>
-              <li><a href="../building-blocks/switches.html">Switches</a></li>
-              <li><a href="../building-blocks/dialogs.html">Dialogs</a></li>
-              <li><a href="../building-blocks/pickers.html">Pickers</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header empty"><a href="../downloads/index.html">Downloads</a></div>
-          </li>
-
-          <li>
-            <div id="back-dac-section"><a href="../../index.html">Developers</a></div>
-          </li>
-
-        </ul>
-
-        <div id="content">
-
-          
-          <div class="layout-content-row content-header">
-            <div class="layout-content-col span-9">
-              <h2>Spinners</h2>
-            </div>
-            <div class="paging-links layout-content-col span-4">
-              <a href="#" class="prev-page-link">Previous</a>
-              <a href="#" class="next-page-link">Next</a>
-            </div>
-          </div>
-          
-
-          
-
-<p>Spinners provide a quick way to select one value from a set. In the default state, a spinner shows
-its currently selected value. Touching the spinner displays a dropdown menu with all other available
-values, from which the user can select a new one.</p>
-
-
-<div class="layout-content-row">
-  <div class="layout-content-col span-6">
-
-    <img src="../static/content/spinners_form.png">
-
-<h4>Spinners in forms</h4>
-<p>Spinners are useful for data picking in forms. They are compact and integrate nicely with other
-components. Use spinners in forms for both simple data input and in combination with other input
-fields. For example, a text field might let you edit an email address for a contact, while its
-associated spinner allows you to select whether it's a Home or Work address.</p>
-
-  </div>
-  <div class="layout-content-col span-7">
-
-    <img src="../static/content/spinners_actionbar.png">
-
-<h4>Spinners in action bars</h4>
-<p>Use spinners in action bars to switch views. For example, Gmail uses a spinner to permit switching
-between accounts or commonly used labels. Spinners are useful when changing the view is important to
-your app, but not necessarily a frequent occurrence. In cases where view switching is frequent, use
-tabs.</p>
-
-  </div>
-</div>
-
-<img src="../static/content/spinners_hololightanddark.png">
-<div class="figure-caption">
-  Spinners in the Holo Dark and Holo Light themes, in various states.
-</div>
-
-
-
-          
-          <div class="layout-content-row content-footer">
-            <div class="paging-links layout-content-col span-9">&nbsp;</div>
-            <div class="paging-links layout-content-col span-4">
-              <a href="#" class="prev-page-link">Previous</a>
-              <a href="#" class="next-page-link">Next</a>
-            </div>
-          </div>
-          
-        </div>
-
-      </div>
-
-      <div id="page-footer">
-
-        <p id="copyright">
-          Except as noted, this content is licensed under
-          <a href="http://creativecommons.org/licenses/by/2.5/">
-          Creative Commons Attribution 2.5</a>.<br>
-          For details and restrictions, see the
-          <a href="http://developer.android.com/license.html">Content License</a>.
-        </p>
-
-        <p>
-          <a href="http://www.android.com/terms.html">Site Terms of Service</a> &ndash;
-          <a href="http://www.android.com/privacy.html">Privacy Policy</a> &ndash;
-          <a href="http://www.android.com/branding.html">Brand Guidelines</a>
-        </p>
-
-      </div>
-    </div>
-
-    <script src="../static/jquery-1.6.2.min.js"></script>
-    <script>
-    var SITE_ROOT = '../';
-    </script>
-    <script src="../static/default.js"></script>
-
-
-    <script type="text/javascript">
-    var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
-    document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
-    </script>
-    <script type="text/javascript">
-    var pageTracker = _gat._getTracker("UA-5831155-1");
-    pageTracker._trackPageview();
-    </script>
-  </body>
-</html>
diff --git a/docs/html/design/building-blocks/spinners.jd b/docs/html/design/building-blocks/spinners.jd
new file mode 100644
index 0000000..621a57c
--- /dev/null
+++ b/docs/html/design/building-blocks/spinners.jd
@@ -0,0 +1,37 @@
+page.title=Spinners
+@jd:body
+
+<p>Spinners provide a quick way to select one value from a set. In the default state, a spinner shows
+its currently selected value. Touching the spinner displays a dropdown menu with all other available
+values, from which the user can select a new one.</p>
+
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-6">
+
+    <img src="{@docRoot}design/media/spinners_form.png">
+
+<h4>Spinners in forms</h4>
+<p>Spinners are useful for data picking in forms. They are compact and integrate nicely with other
+components. Use spinners in forms for both simple data input and in combination with other input
+fields. For example, a text field might let you edit an email address for a contact, while its
+associated spinner allows you to select whether it's a Home or Work address.</p>
+
+  </div>
+  <div class="layout-content-col span-7">
+
+    <img src="{@docRoot}design/media/spinners_actionbar.png">
+
+<h4>Spinners in action bars</h4>
+<p>Use spinners in action bars to switch views. For example, Gmail uses a spinner to permit switching
+between accounts or commonly used labels. Spinners are useful when changing the view is important to
+your app, but not necessarily a frequent occurrence. In cases where view switching is frequent, use
+tabs.</p>
+
+  </div>
+</div>
+
+<img src="{@docRoot}design/media/spinners_hololightanddark.png">
+<div class="figure-caption">
+  Spinners in the Holo Dark and Holo Light themes, in various states.
+</div>
diff --git a/docs/html/design/building-blocks/switches.html b/docs/html/design/building-blocks/switches.html
deleted file mode 100644
index 09af540..0000000
--- a/docs/html/design/building-blocks/switches.html
+++ /dev/null
@@ -1,188 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-  <head>
-    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
-    <title>
-
-Android Design - Switches
-    </title>
-    <link rel="shortcut icon" type="image/x-icon" href="/favicon.ico">
-    <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Roboto:regular,medium,thin,italic,mediumitalic">
-    <link rel="stylesheet" href="../static/yui-3.3.0-reset-min.css">
-    <link rel="stylesheet" href="../static/default.css">
-
-  </head>
-  <body>
-
-    <div id="page-container">
-
-      <div id="page-header"><a href="../index.html">Android Design</a></div>
-
-      <div id="main-row">
-
-        <ul id="nav">
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../index.html">Get Started</a></div>
-            <ul>
-              <li><a href="../get-started/creative-vision.html">Creative Vision</a></li>
-              <li><a href="../get-started/principles.html">Design Principles</a></li>
-              <li><a href="../get-started/ui-overview.html">UI Overview</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../style/index.html">Style</a></div>
-            <ul>
-              <li><a href="../style/devices-displays.html">Devices and Displays</a></li>
-              <li><a href="../style/themes.html">Themes</a></li>
-              <li><a href="../style/touch-feedback.html">Touch Feedback</a></li>
-              <li><a href="../style/metrics-grids.html">Metrics and Grids</a></li>
-              <li><a href="../style/typography.html">Typography</a></li>
-              <li><a href="../style/color.html">Color</a></li>
-              <li><a href="../style/iconography.html">Iconography</a></li>
-              <li><a href="../style/writing.html">Writing Style</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../patterns/index.html">Patterns</a></div>
-            <ul>
-              <li><a href="../patterns/new-4-0.html">New in Android 4.0</a></li>
-              <li><a href="../patterns/gestures.html">Gestures</a></li>
-              <li><a href="../patterns/app-structure.html">App Structure</a></li>
-              <li><a href="../patterns/navigation.html">Navigation</a></li>
-              <li><a href="../patterns/actionbar.html">Action Bar</a></li>
-              <li><a href="../patterns/multi-pane-layouts.html">Multi-pane Layouts</a></li>
-              <li><a href="../patterns/swipe-views.html">Swipe Views</a></li>
-              <li><a href="../patterns/selection.html">Selection</a></li>
-              <li><a href="../patterns/notifications.html">Notifications</a></li>
-              <li><a href="../patterns/compatibility.html">Compatibility</a></li>
-              <li><a href="../patterns/pure-android.html">Pure Android</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../building-blocks/index.html">Building Blocks</a></div>
-            <ul>
-              <li><a href="../building-blocks/tabs.html">Tabs</a></li>
-              <li><a href="../building-blocks/lists.html">Lists</a></li>
-              <li><a href="../building-blocks/grid-lists.html">Grid Lists</a></li>
-              <li><a href="../building-blocks/scrolling.html">Scrolling</a></li>
-              <li><a href="../building-blocks/spinners.html">Spinners</a></li>
-              <li><a href="../building-blocks/buttons.html">Buttons</a></li>
-              <li><a href="../building-blocks/text-fields.html">Text Fields</a></li>
-              <li><a href="../building-blocks/seek-bars.html">Seek Bars</a></li>
-              <li><a href="../building-blocks/progress.html">Progress &amp; Activity</a></li>
-              <li><a href="../building-blocks/switches.html">Switches</a></li>
-              <li><a href="../building-blocks/dialogs.html">Dialogs</a></li>
-              <li><a href="../building-blocks/pickers.html">Pickers</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header empty"><a href="../downloads/index.html">Downloads</a></div>
-          </li>
-
-          <li>
-            <div id="back-dac-section"><a href="../../index.html">Developers</a></div>
-          </li>
-
-        </ul>
-
-        <div id="content">
-
-          
-          <div class="layout-content-row content-header">
-            <div class="layout-content-col span-9">
-              <h2>Switches</h2>
-            </div>
-            <div class="paging-links layout-content-col span-4">
-              <a href="#" class="prev-page-link">Previous</a>
-              <a href="#" class="next-page-link">Next</a>
-            </div>
-          </div>
-          
-
-          
-
-<p>Switches allow the user to select options. There are three kinds of switches: checkboxes, radio
-buttons, and on/off switches.</p>
-<h2 id="checkboxes">Checkboxes</h2>
-
-<p>Checkboxes allow the user to select multiple options from a set. Avoid using a single checkbox to
-turn an option off or on. Instead, use an on/off switch.</p>
-
-<div style="text-align: center">
-  <img src="../static/content/switches_checkboxes.png">
-</div>
-
-<h2 id="radio-buttons">Radio Buttons</h2>
-
-<p>Radio buttons allow the user to select one option from a set. Use radio buttons for exclusive
-selection if you think that the user needs to see all available options side-by-side. Otherwise,
-consider a spinner, which uses less space.</p>
-
-<div style="text-align: center">
-  <img src="../static/content/switches_radios.png">
-</div>
-
-<h2 id="switches">On/off Switches</h2>
-
-<p>On/off switches toggle the state of a single settings option.</p>
-
-<div style="text-align: center">
-  <img src="../static/content/switches_switches.png">
-</div>
-
-
-
-          
-          <div class="layout-content-row content-footer">
-            <div class="paging-links layout-content-col span-9">&nbsp;</div>
-            <div class="paging-links layout-content-col span-4">
-              <a href="#" class="prev-page-link">Previous</a>
-              <a href="#" class="next-page-link">Next</a>
-            </div>
-          </div>
-          
-        </div>
-
-      </div>
-
-      <div id="page-footer">
-
-        <p id="copyright">
-          Except as noted, this content is licensed under
-          <a href="http://creativecommons.org/licenses/by/2.5/">
-          Creative Commons Attribution 2.5</a>.<br>
-          For details and restrictions, see the
-          <a href="http://developer.android.com/license.html">Content License</a>.
-        </p>
-
-        <p>
-          <a href="http://www.android.com/terms.html">Site Terms of Service</a> &ndash;
-          <a href="http://www.android.com/privacy.html">Privacy Policy</a> &ndash;
-          <a href="http://www.android.com/branding.html">Brand Guidelines</a>
-        </p>
-
-      </div>
-    </div>
-
-    <script src="../static/jquery-1.6.2.min.js"></script>
-    <script>
-    var SITE_ROOT = '../';
-    </script>
-    <script src="../static/default.js"></script>
-
-
-    <script type="text/javascript">
-    var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
-    document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
-    </script>
-    <script type="text/javascript">
-    var pageTracker = _gat._getTracker("UA-5831155-1");
-    pageTracker._trackPageview();
-    </script>
-  </body>
-</html>
diff --git a/docs/html/design/building-blocks/switches.jd b/docs/html/design/building-blocks/switches.jd
new file mode 100644
index 0000000..607e0b6
--- /dev/null
+++ b/docs/html/design/building-blocks/switches.jd
@@ -0,0 +1,31 @@
+page.title=Switches
+@jd:body
+
+<p>Switches allow the user to select options. There are three kinds of switches: checkboxes, radio
+buttons, and on/off switches.</p>
+<h2 id="checkboxes">Checkboxes</h2>
+
+<p>Checkboxes allow the user to select multiple options from a set. Avoid using a single checkbox to
+turn an option off or on. Instead, use an on/off switch.</p>
+
+<div style="text-align: center">
+  <img src="{@docRoot}design/media/switches_checkboxes.png">
+</div>
+
+<h2 id="radio-buttons">Radio Buttons</h2>
+
+<p>Radio buttons allow the user to select one option from a set. Use radio buttons for exclusive
+selection if you think that the user needs to see all available options side-by-side. Otherwise,
+consider a spinner, which uses less space.</p>
+
+<div style="text-align: center">
+  <img src="{@docRoot}design/media/switches_radios.png">
+</div>
+
+<h2 id="switches">On/off Switches</h2>
+
+<p>On/off switches toggle the state of a single settings option.</p>
+
+<div style="text-align: center">
+  <img src="{@docRoot}design/media/switches_switches.png">
+</div>
diff --git a/docs/html/design/building-blocks/tabs.html b/docs/html/design/building-blocks/tabs.html
deleted file mode 100644
index d4b0e52..0000000
--- a/docs/html/design/building-blocks/tabs.html
+++ /dev/null
@@ -1,217 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-  <head>
-    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
-    <title>
-
-Android Design - Tabs
-    </title>
-    <link rel="shortcut icon" type="image/x-icon" href="/favicon.ico">
-    <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Roboto:regular,medium,thin,italic,mediumitalic">
-    <link rel="stylesheet" href="../static/yui-3.3.0-reset-min.css">
-    <link rel="stylesheet" href="../static/default.css">
-
-  </head>
-  <body>
-
-    <div id="page-container">
-
-      <div id="page-header"><a href="../index.html">Android Design</a></div>
-
-      <div id="main-row">
-
-        <ul id="nav">
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../index.html">Get Started</a></div>
-            <ul>
-              <li><a href="../get-started/creative-vision.html">Creative Vision</a></li>
-              <li><a href="../get-started/principles.html">Design Principles</a></li>
-              <li><a href="../get-started/ui-overview.html">UI Overview</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../style/index.html">Style</a></div>
-            <ul>
-              <li><a href="../style/devices-displays.html">Devices and Displays</a></li>
-              <li><a href="../style/themes.html">Themes</a></li>
-              <li><a href="../style/touch-feedback.html">Touch Feedback</a></li>
-              <li><a href="../style/metrics-grids.html">Metrics and Grids</a></li>
-              <li><a href="../style/typography.html">Typography</a></li>
-              <li><a href="../style/color.html">Color</a></li>
-              <li><a href="../style/iconography.html">Iconography</a></li>
-              <li><a href="../style/writing.html">Writing Style</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../patterns/index.html">Patterns</a></div>
-            <ul>
-              <li><a href="../patterns/new-4-0.html">New in Android 4.0</a></li>
-              <li><a href="../patterns/gestures.html">Gestures</a></li>
-              <li><a href="../patterns/app-structure.html">App Structure</a></li>
-              <li><a href="../patterns/navigation.html">Navigation</a></li>
-              <li><a href="../patterns/actionbar.html">Action Bar</a></li>
-              <li><a href="../patterns/multi-pane-layouts.html">Multi-pane Layouts</a></li>
-              <li><a href="../patterns/swipe-views.html">Swipe Views</a></li>
-              <li><a href="../patterns/selection.html">Selection</a></li>
-              <li><a href="../patterns/notifications.html">Notifications</a></li>
-              <li><a href="../patterns/compatibility.html">Compatibility</a></li>
-              <li><a href="../patterns/pure-android.html">Pure Android</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../building-blocks/index.html">Building Blocks</a></div>
-            <ul>
-              <li><a href="../building-blocks/tabs.html">Tabs</a></li>
-              <li><a href="../building-blocks/lists.html">Lists</a></li>
-              <li><a href="../building-blocks/grid-lists.html">Grid Lists</a></li>
-              <li><a href="../building-blocks/scrolling.html">Scrolling</a></li>
-              <li><a href="../building-blocks/spinners.html">Spinners</a></li>
-              <li><a href="../building-blocks/buttons.html">Buttons</a></li>
-              <li><a href="../building-blocks/text-fields.html">Text Fields</a></li>
-              <li><a href="../building-blocks/seek-bars.html">Seek Bars</a></li>
-              <li><a href="../building-blocks/progress.html">Progress &amp; Activity</a></li>
-              <li><a href="../building-blocks/switches.html">Switches</a></li>
-              <li><a href="../building-blocks/dialogs.html">Dialogs</a></li>
-              <li><a href="../building-blocks/pickers.html">Pickers</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header empty"><a href="../downloads/index.html">Downloads</a></div>
-          </li>
-
-          <li>
-            <div id="back-dac-section"><a href="../../index.html">Developers</a></div>
-          </li>
-
-        </ul>
-
-        <div id="content">
-
-          
-          <div class="layout-content-row content-header">
-            <div class="layout-content-col span-9">
-              <h2>Tabs</h2>
-            </div>
-            <div class="paging-links layout-content-col span-4">
-              <a href="#" class="prev-page-link">Previous</a>
-              <a href="#" class="next-page-link">Next</a>
-            </div>
-          </div>
-          
-
-          
-
-<img src="../static/content/tabs_overview.png">
-
-<p>Tabs in the action bar make it easy to explore and switch between different views or functional
-aspects of your app, or to browse categorized data sets.</p>
-
-
-<h2 id="scrollable">Scrollable Tabs</h2>
-
-
-<div class="layout-content-row">
-  <div class="layout-content-col span-6">
-
-<p>Scrolling tab controls can contain a larger number of items than a standard tab control. To navigate
-to the next/previous view, swipe left or right.</p>
-
-  </div>
-  <div class="layout-content-col span-7">
-
-    <video width="400" class="with-shadow play-on-hover" autoplay>
-      <source src="../static/content/tabs_scrolly.mp4" type="video/mp4">
-      <source src="../static/content/tabs_scrolly.webm" type="video/webm">
-      <source src="../static/content/tabs_scrolly.ogv" type="video/ogg">
-    </video>
-    <div class="figure-caption">
-      Scrolling tabs in Android Market.
-      <div class="video-instructions">&nbsp;</div>
-    </div>
-
-  </div>
-</div>
-
-
-<h2 id="fixed">Fixed Tabs</h2>
-
-
-<p>Fixed tabs display all items concurrently. To navigate to a different view, touch the tab.</p>
-
-<img src="../static/content/tabs_standard.png">
-<div class="figure-caption">
-  Tabs in Holo Dark &amp; Light.
-</div>
-
-<img src="../static/content/tabs_youtube.png">
-<div class="figure-caption">
-  Tabs in the YouTube app.
-</div>
-
-
-
-<h2 id="stacked">Stacked Tabs</h2>
-
-
-<p>If view navigation is essential to your app, you can break out tabs into a separate action bar. This
-permits fast view switching even on narrower screens.</p>
-
-<img src="../static/content/tabs_stacked.png">
-
-
-
-
-          
-          <div class="layout-content-row content-footer">
-            <div class="paging-links layout-content-col span-9">&nbsp;</div>
-            <div class="paging-links layout-content-col span-4">
-              <a href="#" class="prev-page-link">Previous</a>
-              <a href="#" class="next-page-link">Next</a>
-            </div>
-          </div>
-          
-        </div>
-
-      </div>
-
-      <div id="page-footer">
-
-        <p id="copyright">
-          Except as noted, this content is licensed under
-          <a href="http://creativecommons.org/licenses/by/2.5/">
-          Creative Commons Attribution 2.5</a>.<br>
-          For details and restrictions, see the
-          <a href="http://developer.android.com/license.html">Content License</a>.
-        </p>
-
-        <p>
-          <a href="http://www.android.com/terms.html">Site Terms of Service</a> &ndash;
-          <a href="http://www.android.com/privacy.html">Privacy Policy</a> &ndash;
-          <a href="http://www.android.com/branding.html">Brand Guidelines</a>
-        </p>
-
-      </div>
-    </div>
-
-    <script src="../static/jquery-1.6.2.min.js"></script>
-    <script>
-    var SITE_ROOT = '../';
-    </script>
-    <script src="../static/default.js"></script>
-
-
-    <script type="text/javascript">
-    var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
-    document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
-    </script>
-    <script type="text/javascript">
-    var pageTracker = _gat._getTracker("UA-5831155-1");
-    pageTracker._trackPageview();
-    </script>
-  </body>
-</html>
diff --git a/docs/html/design/building-blocks/tabs.jd b/docs/html/design/building-blocks/tabs.jd
new file mode 100644
index 0000000..2c854d3
--- /dev/null
+++ b/docs/html/design/building-blocks/tabs.jd
@@ -0,0 +1,59 @@
+page.title=Tabs
+@jd:body
+
+<img src="{@docRoot}design/media/tabs_overview.png">
+
+<p>Tabs in the action bar make it easy to explore and switch between different views or functional
+aspects of your app, or to browse categorized data sets.</p>
+
+
+<h2 id="scrollable">Scrollable Tabs</h2>
+
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-6">
+
+<p>Scrolling tab controls can contain a larger number of items than a standard tab control. To navigate
+to the next/previous view, swipe left or right.</p>
+
+  </div>
+  <div class="layout-content-col span-7">
+
+    <video width="400" class="with-shadow play-on-hover" autoplay>
+      <source src="{@docRoot}design/media/tabs_scrolly.mp4" type="video/mp4">
+      <source src="{@docRoot}design/media/tabs_scrolly.webm" type="video/webm">
+      <source src="{@docRoot}design/media/tabs_scrolly.ogv" type="video/ogg">
+    </video>
+    <div class="figure-caption">
+      Scrolling tabs in Google Play.
+      <div class="video-instructions">&nbsp;</div>
+    </div>
+
+  </div>
+</div>
+
+
+<h2 id="fixed">Fixed Tabs</h2>
+
+
+<p>Fixed tabs display all items concurrently. To navigate to a different view, touch the tab.</p>
+
+<img src="{@docRoot}design/media/tabs_standard.png">
+<div class="figure-caption">
+  Tabs in Holo Dark &amp; Light.
+</div>
+
+<img src="{@docRoot}design/media/tabs_youtube.png">
+<div class="figure-caption">
+  Tabs in the YouTube app.
+</div>
+
+
+
+<h2 id="stacked">Stacked Tabs</h2>
+
+
+<p>If view navigation is essential to your app, you can break out tabs into a separate action bar. This
+permits fast view switching even on narrower screens.</p>
+
+<img src="{@docRoot}design/media/tabs_stacked.png">
diff --git a/docs/html/design/building-blocks/text-fields.html b/docs/html/design/building-blocks/text-fields.html
deleted file mode 100644
index b9ec42d..0000000
--- a/docs/html/design/building-blocks/text-fields.html
+++ /dev/null
@@ -1,227 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-  <head>
-    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
-    <title>
-
-Android Design - Text Fields
-    </title>
-    <link rel="shortcut icon" type="image/x-icon" href="/favicon.ico">
-    <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Roboto:regular,medium,thin,italic,mediumitalic">
-    <link rel="stylesheet" href="../static/yui-3.3.0-reset-min.css">
-    <link rel="stylesheet" href="../static/default.css">
-
-  </head>
-  <body>
-
-    <div id="page-container">
-
-      <div id="page-header"><a href="../index.html">Android Design</a></div>
-
-      <div id="main-row">
-
-        <ul id="nav">
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../index.html">Get Started</a></div>
-            <ul>
-              <li><a href="../get-started/creative-vision.html">Creative Vision</a></li>
-              <li><a href="../get-started/principles.html">Design Principles</a></li>
-              <li><a href="../get-started/ui-overview.html">UI Overview</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../style/index.html">Style</a></div>
-            <ul>
-              <li><a href="../style/devices-displays.html">Devices and Displays</a></li>
-              <li><a href="../style/themes.html">Themes</a></li>
-              <li><a href="../style/touch-feedback.html">Touch Feedback</a></li>
-              <li><a href="../style/metrics-grids.html">Metrics and Grids</a></li>
-              <li><a href="../style/typography.html">Typography</a></li>
-              <li><a href="../style/color.html">Color</a></li>
-              <li><a href="../style/iconography.html">Iconography</a></li>
-              <li><a href="../style/writing.html">Writing Style</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../patterns/index.html">Patterns</a></div>
-            <ul>
-              <li><a href="../patterns/new-4-0.html">New in Android 4.0</a></li>
-              <li><a href="../patterns/gestures.html">Gestures</a></li>
-              <li><a href="../patterns/app-structure.html">App Structure</a></li>
-              <li><a href="../patterns/navigation.html">Navigation</a></li>
-              <li><a href="../patterns/actionbar.html">Action Bar</a></li>
-              <li><a href="../patterns/multi-pane-layouts.html">Multi-pane Layouts</a></li>
-              <li><a href="../patterns/swipe-views.html">Swipe Views</a></li>
-              <li><a href="../patterns/selection.html">Selection</a></li>
-              <li><a href="../patterns/notifications.html">Notifications</a></li>
-              <li><a href="../patterns/compatibility.html">Compatibility</a></li>
-              <li><a href="../patterns/pure-android.html">Pure Android</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../building-blocks/index.html">Building Blocks</a></div>
-            <ul>
-              <li><a href="../building-blocks/tabs.html">Tabs</a></li>
-              <li><a href="../building-blocks/lists.html">Lists</a></li>
-              <li><a href="../building-blocks/grid-lists.html">Grid Lists</a></li>
-              <li><a href="../building-blocks/scrolling.html">Scrolling</a></li>
-              <li><a href="../building-blocks/spinners.html">Spinners</a></li>
-              <li><a href="../building-blocks/buttons.html">Buttons</a></li>
-              <li><a href="../building-blocks/text-fields.html">Text Fields</a></li>
-              <li><a href="../building-blocks/seek-bars.html">Seek Bars</a></li>
-              <li><a href="../building-blocks/progress.html">Progress &amp; Activity</a></li>
-              <li><a href="../building-blocks/switches.html">Switches</a></li>
-              <li><a href="../building-blocks/dialogs.html">Dialogs</a></li>
-              <li><a href="../building-blocks/pickers.html">Pickers</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header empty"><a href="../downloads/index.html">Downloads</a></div>
-          </li>
-
-          <li>
-            <div id="back-dac-section"><a href="../../index.html">Developers</a></div>
-          </li>
-
-        </ul>
-
-        <div id="content">
-
-          
-          <div class="layout-content-row content-header">
-            <div class="layout-content-col span-9">
-              <h2>Text Fields</h2>
-            </div>
-            <div class="paging-links layout-content-col span-4">
-              <a href="#" class="prev-page-link">Previous</a>
-              <a href="#" class="next-page-link">Next</a>
-            </div>
-          </div>
-          
-
-          
-
-<p>Text fields allow the user to type text into your app. They can be either single line or multi-line.
-Touching a text field places the cursor and automatically displays the keyboard. In addition to
-typing, text fields allow for a variety of other activities, such as text selection (cut, copy,
-paste) and data lookup via auto-completion.</p>
-
-
-<div class="layout-content-row">
-  <div class="layout-content-col span-12">
-
-    <img src="../static/content/text_input_singlevsmultiline.png">
-
-  </div>
-</div>
-
-<h4>Single line and multi line</h4>
-<p>Single-line fields automatically scroll their content to the left as the text input cursor reaches
-the right edge of the input field. Multi-line text fields automatically break to a new line for
-overflow text and scroll vertically when the cursor reaches the lower edge.</p>
-
-<img src="../static/content/text_input_typesandtypedown.png">
-
-<div class="layout-content-row">
-  <div class="layout-content-col span-6">
-
-<h4>Text field types</h4>
-<p>Text fields can have different types, such as number, message, or email address. The type determines
-what kind of characters are allowed inside the field, and may prompt the virtual keyboard to
-optimize its layout for frequently used characters.</p>
-
-  </div>
-  <div class="layout-content-col span-6">
-
-<h4>Auto-complete text fields</h4>
-<p>Use auto-complete text fields to present real-time completions or search results in popups, so users
-can enter information more accurately and efficiently.</p>
-
-  </div>
-</div>
-
-<h2 id="text-selection">Text Selection</h2>
-
-<p>Users can select any word in a text field with a long press. This action triggers a text selection
-mode that facilitates extending the selection or choosing an action to perform on the selected text.
-Selection mode includes:</p>
-
-<div class="layout-content-row">
-  <div class="layout-content-col span-9">
-
-    <img src="../static/content/text_input_textselection.png">
-
-  </div>
-  <div class="layout-content-col span-4 with-callouts">
-
-<ol>
-<li>
-<h4>Contextual action bar</h4>
-<p>A contextual action bar (CAB) displays the actions available to perform on the selection:
- typically cut, copy, and paste, but apps can insert additional commands as needed.</p>
-</li>
-<li>
-<h4>Selection handles</h4>
-<p>Selection handles can be dragged to select more or less text while remaining in selection mode.</p>
-</li>
-</ol>
-
-  </div>
-</div>
-
-
-
-          
-          <div class="layout-content-row content-footer">
-            <div class="paging-links layout-content-col span-9">&nbsp;</div>
-            <div class="paging-links layout-content-col span-4">
-              <a href="#" class="prev-page-link">Previous</a>
-              <a href="#" class="next-page-link">Next</a>
-            </div>
-          </div>
-          
-        </div>
-
-      </div>
-
-      <div id="page-footer">
-
-        <p id="copyright">
-          Except as noted, this content is licensed under
-          <a href="http://creativecommons.org/licenses/by/2.5/">
-          Creative Commons Attribution 2.5</a>.<br>
-          For details and restrictions, see the
-          <a href="http://developer.android.com/license.html">Content License</a>.
-        </p>
-
-        <p>
-          <a href="http://www.android.com/terms.html">Site Terms of Service</a> &ndash;
-          <a href="http://www.android.com/privacy.html">Privacy Policy</a> &ndash;
-          <a href="http://www.android.com/branding.html">Brand Guidelines</a>
-        </p>
-
-      </div>
-    </div>
-
-    <script src="../static/jquery-1.6.2.min.js"></script>
-    <script>
-    var SITE_ROOT = '../';
-    </script>
-    <script src="../static/default.js"></script>
-
-
-    <script type="text/javascript">
-    var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
-    document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
-    </script>
-    <script type="text/javascript">
-    var pageTracker = _gat._getTracker("UA-5831155-1");
-    pageTracker._trackPageview();
-    </script>
-  </body>
-</html>
diff --git a/docs/html/design/building-blocks/text-fields.jd b/docs/html/design/building-blocks/text-fields.jd
new file mode 100644
index 0000000..1b10420
--- /dev/null
+++ b/docs/html/design/building-blocks/text-fields.jd
@@ -0,0 +1,70 @@
+page.title=Text Fields
+@jd:body
+
+<p>Text fields allow the user to type text into your app. They can be either single line or multi-line.
+Touching a text field places the cursor and automatically displays the keyboard. In addition to
+typing, text fields allow for a variety of other activities, such as text selection (cut, copy,
+paste) and data lookup via auto-completion.</p>
+
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-12">
+
+    <img src="{@docRoot}design/media/text_input_singlevsmultiline.png">
+
+  </div>
+</div>
+
+<h4>Single line and multi line</h4>
+<p>Single-line fields automatically scroll their content to the left as the text input cursor reaches
+the right edge of the input field. Multi-line text fields automatically break to a new line for
+overflow text and scroll vertically when the cursor reaches the lower edge.</p>
+
+<img src="{@docRoot}design/media/text_input_typesandtypedown.png">
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-6">
+
+<h4>Text field types</h4>
+<p>Text fields can have different types, such as number, message, or email address. The type determines
+what kind of characters are allowed inside the field, and may prompt the virtual keyboard to
+optimize its layout for frequently used characters.</p>
+
+  </div>
+  <div class="layout-content-col span-6">
+
+<h4>Auto-complete text fields</h4>
+<p>Use auto-complete text fields to present real-time completions or search results in popups, so users
+can enter information more accurately and efficiently.</p>
+
+  </div>
+</div>
+
+<h2 id="text-selection">Text Selection</h2>
+
+<p>Users can select any word in a text field with a long press. This action triggers a text selection
+mode that facilitates extending the selection or choosing an action to perform on the selected text.
+Selection mode includes:</p>
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-9">
+
+    <img src="{@docRoot}design/media/text_input_textselection.png">
+
+  </div>
+  <div class="layout-content-col span-4 with-callouts">
+
+<ol>
+<li>
+<h4>Contextual action bar</h4>
+<p>A contextual action bar (CAB) displays the actions available to perform on the selection:
+ typically cut, copy, and paste, but apps can insert additional commands as needed.</p>
+</li>
+<li>
+<h4>Selection handles</h4>
+<p>Selection handles can be dragged to select more or less text while remaining in selection mode.</p>
+</li>
+</ol>
+
+  </div>
+</div>
diff --git a/docs/html/design/design_toc.cs b/docs/html/design/design_toc.cs
new file mode 100644
index 0000000..19b58d9
--- /dev/null
+++ b/docs/html/design/design_toc.cs
@@ -0,0 +1,69 @@
+<ul id="nav">
+
+  <li class="nav-section">
+    <div class="nav-section-header"><a href="<?cs var:toroot ?>design/index.html">Get Started</a></div>
+    <ul>
+      <li><a href="<?cs var:toroot ?>design/get-started/creative-vision.html">Creative Vision</a></li>
+      <li><a href="<?cs var:toroot ?>design/get-started/principles.html">Design Principles</a></li>
+      <li><a href="<?cs var:toroot ?>design/get-started/ui-overview.html">UI Overview</a></li>
+    </ul>
+  </li>
+
+  <li class="nav-section">
+    <div class="nav-section-header"><a href="<?cs var:toroot ?>design/style/index.html">Style</a></div>
+    <ul>
+      <li><a href="<?cs var:toroot ?>design/style/devices-displays.html">Devices and Displays</a></li>
+      <li><a href="<?cs var:toroot ?>design/style/themes.html">Themes</a></li>
+      <li><a href="<?cs var:toroot ?>design/style/touch-feedback.html">Touch Feedback</a></li>
+      <li><a href="<?cs var:toroot ?>design/style/metrics-grids.html">Metrics and Grids</a></li>
+      <li><a href="<?cs var:toroot ?>design/style/typography.html">Typography</a></li>
+      <li><a href="<?cs var:toroot ?>design/style/color.html">Color</a></li>
+      <li><a href="<?cs var:toroot ?>design/style/iconography.html">Iconography</a></li>
+      <li><a href="<?cs var:toroot ?>design/style/writing.html">Writing Style</a></li>
+    </ul>
+  </li>
+
+  <li class="nav-section">
+    <div class="nav-section-header"><a href="<?cs var:toroot ?>design/patterns/index.html">Patterns</a></div>
+    <ul>
+      <li><a href="<?cs var:toroot ?>design/patterns/new-4-0.html">New in Android 4.0</a></li>
+      <li><a href="<?cs var:toroot ?>design/patterns/gestures.html">Gestures</a></li>
+      <li><a href="<?cs var:toroot ?>design/patterns/app-structure.html">App Structure</a></li>
+      <li><a href="<?cs var:toroot ?>design/patterns/navigation.html">Navigation</a></li>
+      <li><a href="<?cs var:toroot ?>design/patterns/actionbar.html">Action Bar</a></li>
+      <li><a href="<?cs var:toroot ?>design/patterns/multi-pane-layouts.html">Multi-pane Layouts</a></li>
+      <li><a href="<?cs var:toroot ?>design/patterns/swipe-views.html">Swipe Views</a></li>
+      <li><a href="<?cs var:toroot ?>design/patterns/selection.html">Selection</a></li>
+      <li><a href="<?cs var:toroot ?>design/patterns/notifications.html">Notifications</a></li>
+      <li><a href="<?cs var:toroot ?>design/patterns/compatibility.html">Compatibility</a></li>
+      <li><a href="<?cs var:toroot ?>design/patterns/pure-android.html">Pure Android</a></li>
+    </ul>
+  </li>
+
+  <li class="nav-section">
+    <div class="nav-section-header"><a href="<?cs var:toroot ?>design/building-blocks/index.html">Building Blocks</a></div>
+    <ul>
+      <li><a href="<?cs var:toroot ?>design/building-blocks/tabs.html">Tabs</a></li>
+      <li><a href="<?cs var:toroot ?>design/building-blocks/lists.html">Lists</a></li>
+      <li><a href="<?cs var:toroot ?>design/building-blocks/grid-lists.html">Grid Lists</a></li>
+      <li><a href="<?cs var:toroot ?>design/building-blocks/scrolling.html">Scrolling</a></li>
+      <li><a href="<?cs var:toroot ?>design/building-blocks/spinners.html">Spinners</a></li>
+      <li><a href="<?cs var:toroot ?>design/building-blocks/buttons.html">Buttons</a></li>
+      <li><a href="<?cs var:toroot ?>design/building-blocks/text-fields.html">Text Fields</a></li>
+      <li><a href="<?cs var:toroot ?>design/building-blocks/seek-bars.html">Seek Bars</a></li>
+      <li><a href="<?cs var:toroot ?>design/building-blocks/progress.html">Progress &amp; Activity</a></li>
+      <li><a href="<?cs var:toroot ?>design/building-blocks/switches.html">Switches</a></li>
+      <li><a href="<?cs var:toroot ?>design/building-blocks/dialogs.html">Dialogs</a></li>
+      <li><a href="<?cs var:toroot ?>design/building-blocks/pickers.html">Pickers</a></li>
+    </ul>
+  </li>
+
+  <li class="nav-section">
+    <div class="nav-section-header empty"><a href="<?cs var:toroot ?>design/downloads/index.html">Downloads</a></div>
+  </li>
+
+  <li>
+    <div id="back-dac-section"><a href="<?cs var:toroot ?>index.html">Developers</a></div>
+  </li>
+
+</ul>
\ No newline at end of file
diff --git a/docs/html/design/downloads/index.html b/docs/html/design/downloads/index.html
deleted file mode 100644
index f910b29..0000000
--- a/docs/html/design/downloads/index.html
+++ /dev/null
@@ -1,278 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-  <head>
-    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
-    <title>
-
-Android Design - Downloads
-    </title>
-    <link rel="shortcut icon" type="image/x-icon" href="/favicon.ico">
-    <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Roboto:regular,medium,thin,italic,mediumitalic">
-    <link rel="stylesheet" href="../static/yui-3.3.0-reset-min.css">
-    <link rel="stylesheet" href="../static/default.css">
-
-  </head>
-  <body>
-
-    <div id="page-container">
-
-      <div id="page-header"><a href="../index.html">Android Design</a></div>
-
-      <div id="main-row">
-
-        <ul id="nav">
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../index.html">Get Started</a></div>
-            <ul>
-              <li><a href="../get-started/creative-vision.html">Creative Vision</a></li>
-              <li><a href="../get-started/principles.html">Design Principles</a></li>
-              <li><a href="../get-started/ui-overview.html">UI Overview</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../style/index.html">Style</a></div>
-            <ul>
-              <li><a href="../style/devices-displays.html">Devices and Displays</a></li>
-              <li><a href="../style/themes.html">Themes</a></li>
-              <li><a href="../style/touch-feedback.html">Touch Feedback</a></li>
-              <li><a href="../style/metrics-grids.html">Metrics and Grids</a></li>
-              <li><a href="../style/typography.html">Typography</a></li>
-              <li><a href="../style/color.html">Color</a></li>
-              <li><a href="../style/iconography.html">Iconography</a></li>
-              <li><a href="../style/writing.html">Writing Style</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../patterns/index.html">Patterns</a></div>
-            <ul>
-              <li><a href="../patterns/new-4-0.html">New in Android 4.0</a></li>
-              <li><a href="../patterns/gestures.html">Gestures</a></li>
-              <li><a href="../patterns/app-structure.html">App Structure</a></li>
-              <li><a href="../patterns/navigation.html">Navigation</a></li>
-              <li><a href="../patterns/actionbar.html">Action Bar</a></li>
-              <li><a href="../patterns/multi-pane-layouts.html">Multi-pane Layouts</a></li>
-              <li><a href="../patterns/swipe-views.html">Swipe Views</a></li>
-              <li><a href="../patterns/selection.html">Selection</a></li>
-              <li><a href="../patterns/notifications.html">Notifications</a></li>
-              <li><a href="../patterns/compatibility.html">Compatibility</a></li>
-              <li><a href="../patterns/pure-android.html">Pure Android</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../building-blocks/index.html">Building Blocks</a></div>
-            <ul>
-              <li><a href="../building-blocks/tabs.html">Tabs</a></li>
-              <li><a href="../building-blocks/lists.html">Lists</a></li>
-              <li><a href="../building-blocks/grid-lists.html">Grid Lists</a></li>
-              <li><a href="../building-blocks/scrolling.html">Scrolling</a></li>
-              <li><a href="../building-blocks/spinners.html">Spinners</a></li>
-              <li><a href="../building-blocks/buttons.html">Buttons</a></li>
-              <li><a href="../building-blocks/text-fields.html">Text Fields</a></li>
-              <li><a href="../building-blocks/seek-bars.html">Seek Bars</a></li>
-              <li><a href="../building-blocks/progress.html">Progress &amp; Activity</a></li>
-              <li><a href="../building-blocks/switches.html">Switches</a></li>
-              <li><a href="../building-blocks/dialogs.html">Dialogs</a></li>
-              <li><a href="../building-blocks/pickers.html">Pickers</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header empty"><a href="../downloads/index.html">Downloads</a></div>
-          </li>
-
-          <li>
-            <div id="back-dac-section"><a href="../../index.html">Developers</a></div>
-          </li>
-
-        </ul>
-
-        <div id="content">
-
-          
-          <div class="layout-content-row content-header">
-            <div class="layout-content-col span-9">
-              <h2>Downloads</h2>
-            </div>
-            <div class="paging-links layout-content-col span-4">
-              <a href="#" class="prev-page-link">Previous</a>
-              <a href="#" class="next-page-link">Next</a>
-            </div>
-          </div>
-          
-
-          
-
-<div class="layout-content-row">
-  <div class="layout-content-col span-9">
-
-<p>Want everything? We've bundled all the downloads available on Android Design into a single ZIP file.
-You can also download individual files listed below.</p>
-<p>You may use these materials without restriction in your apps and to develop your apps.</p>
-
-  </div>
-  <div class="layout-content-col span-4">
-
-<p>
-  <a class="download-button" href="https://dl-ssl.google.com/android/design/Android_Design_Downloads_20120229.zip">Download All</a>
-</p>
-
-  </div>
-</div>
-
-<h2 id="stencils">Stencils and Sources</h2>
-
-<div class="layout-content-row">
-  <div class="layout-content-col span-5">
-
-<p>Drag and drop your way to beautifully designed Ice Cream Sandwich apps. The stencils feature the
-rich typography, colors, interactive controls, and icons found throughout Android 4.0, along with
-phone and tablet outlines to frame your creations. Source files for icons and controls are also
-available.</p>
-
-  </div>
-  <div class="layout-content-col span-4">
-
-    <img src="../static/content/downloads_stencils.png">
-
-  </div>
-  <div class="layout-content-col span-4">
-
-<p>
-  <a class="download-button" href="https://dl-ssl.google.com/android/design/Android_Design_Fireworks_Stencil_20120229.png">Adobe&reg; Fireworks&reg; PNG Stencil</a>
-  <a class="download-button" href="https://dl-ssl.google.com/android/design/Android_Design_OmniGraffle_Stencil_20120229.graffle">Omni&reg; OmniGraffle&reg; Stencil</a>
-  <a class="download-button" href="https://dl-ssl.google.com/android/design/Android_Design_Holo_Widgets_20120229.zip">Adobe&reg; Photoshop&reg; Sources</a>
-</p>
-
-  </div>
-</div>
-
-<h2 id="action-bar-icon-pack">Action Bar Icon Pack</h2>
-
-<div class="layout-content-row">
-  <div class="layout-content-col span-5">
-
-<p>Action bar icons are graphic buttons that represent the most important actions people can take
-within your app. <a href="../style/iconography.html">More on Action Bar Iconography</a></p>
-<p>The download package includes icons that are scaled for various screen densities and suitable for
-use with the Holo Light and Holo Dark themes. The package also includes unstyled icons that you can
-modify to match your theme, plus source files.</p>
-
-  </div>
-  <div class="layout-content-col span-4">
-
-    <img src="../static/content/iconography_actionbar_style.png">
-
-  </div>
-  <div class="layout-content-col span-4">
-
-<p>
-  <a class="download-button" href="https://dl-ssl.google.com/android/design/Android_Design_Icons_20120229.zip">Action Bar Icon Pack</a>
-</p>
-
-  </div>
-</div>
-
-<h2 id="style">Style</h2>
-
-<div class="layout-content-row">
-  <div class="layout-content-col span-5">
-
-<h4>Roboto</h4>
-<p>Ice Cream Sandwich introduced a new type family named Roboto, created specifically for the
-requirements of UI and high-resolution screens.</p>
-<p><a href="../style/typography.html#actionbar">More on Roboto</a></p>
-
-  </div>
-  <div class="layout-content-col span-4">
-
-    <img src="../static/content/downloads_roboto_specimen_preview.png">
-
-  </div>
-  <div class="layout-content-col span-4">
-
-<p>
-  <a class="download-button" href="https://dl-ssl.google.com/android/design/Roboto_Hinted_20111129.zip">Roboto</a>
-  <a class="download-button" href="https://dl-ssl.google.com/android/design/Roboto_Specimen_Book_20111129.pdf">Specimen Book</a>
-</p>
-
-  </div>
-</div>
-
-<div class="layout-content-row">
-  <div class="layout-content-col span-5">
-
-<h4>Color</h4>
-<p>Blue is the standard accent color in Android's color palette. Each color has a corresponding darker
-shade that can be used as a complement when needed.</p>
-<p><a href="../style/color.html">More on Color</a></p>
-
-  </div>
-  <div class="layout-content-col span-4">
-
-    <img src="../static/content/downloads_color_swatches.png">
-
-  </div>
-  <div class="layout-content-col span-4">
-
-<p>
-  <a class="download-button" href="https://dl-ssl.google.com/android/design/Android_Design_Color_Swatches_20120229.zip">Color Swatches</a>
-</p>
-
-  </div>
-</div>
-
-
-
-          
-          <div class="layout-content-row content-footer">
-            <div class="paging-links layout-content-col span-9">&nbsp;</div>
-            <div class="paging-links layout-content-col span-4">
-              <a href="#" class="prev-page-link">Previous</a>
-              <a href="#" class="next-page-link">Next</a>
-            </div>
-          </div>
-          
-        </div>
-
-      </div>
-
-      <div id="page-footer">
-
-        <p id="copyright">
-          Except as noted, this content is licensed under
-          <a href="http://creativecommons.org/licenses/by/2.5/">
-          Creative Commons Attribution 2.5</a>.<br>
-          For details and restrictions, see the
-          <a href="http://developer.android.com/license.html">Content License</a>.
-        </p>
-
-        <p>
-          <a href="http://www.android.com/terms.html">Site Terms of Service</a> &ndash;
-          <a href="http://www.android.com/privacy.html">Privacy Policy</a> &ndash;
-          <a href="http://www.android.com/branding.html">Brand Guidelines</a>
-        </p>
-
-      </div>
-    </div>
-
-    <script src="../static/jquery-1.6.2.min.js"></script>
-    <script>
-    var SITE_ROOT = '../';
-    </script>
-    <script src="../static/default.js"></script>
-
-
-    <script type="text/javascript">
-    var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
-    document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
-    </script>
-    <script type="text/javascript">
-    var pageTracker = _gat._getTracker("UA-5831155-1");
-    pageTracker._trackPageview();
-    </script>
-  </body>
-</html>
diff --git a/docs/html/design/downloads/index.jd b/docs/html/design/downloads/index.jd
new file mode 100644
index 0000000..618c44b
--- /dev/null
+++ b/docs/html/design/downloads/index.jd
@@ -0,0 +1,121 @@
+page.title=Downloads
+@jd:body
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-9">
+
+<p>Want everything? We've bundled all the downloads available on Android Design into a single ZIP file.
+You can also download individual files listed below.</p>
+<p>You may use these materials without restriction in your apps and to develop your apps.</p>
+
+  </div>
+  <div class="layout-content-col span-4">
+
+<p>
+  <a class="download-button" href="https://dl-ssl.google.com/android/design/Android_Design_Downloads_20120229.zip">Download All</a>
+</p>
+
+  </div>
+</div>
+
+<h2 id="stencils">Stencils and Sources</h2>
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-5">
+
+<p>Drag and drop your way to beautifully designed Ice Cream Sandwich apps. The stencils feature the
+rich typography, colors, interactive controls, and icons found throughout Android 4.0, along with
+phone and tablet outlines to frame your creations. Source files for icons and controls are also
+available.</p>
+
+  </div>
+  <div class="layout-content-col span-4">
+
+    <img src="{@docRoot}design/media/downloads_stencils.png">
+
+  </div>
+  <div class="layout-content-col span-4">
+
+<p>
+  <a class="download-button" href="https://dl-ssl.google.com/android/design/Android_Design_Fireworks_Stencil_20120229.png">Adobe&reg; Fireworks&reg; PNG Stencil</a>
+  <a class="download-button" href="https://dl-ssl.google.com/android/design/Android_Design_OmniGraffle_Stencil_20120229.graffle">Omni&reg; OmniGraffle&reg; Stencil</a>
+  <a class="download-button" href="https://dl-ssl.google.com/android/design/Android_Design_Holo_Widgets_20120229.zip">Adobe&reg; Photoshop&reg; Sources</a>
+</p>
+
+  </div>
+</div>
+
+<h2 id="action-bar-icon-pack">Action Bar Icon Pack</h2>
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-5">
+
+<p>Action bar icons are graphic buttons that represent the most important actions people can take
+within your app. <a href="{@docRoot}design/style/iconography.html">More on Action Bar Iconography</a></p>
+<p>The download package includes icons that are scaled for various screen densities and suitable for
+use with the Holo Light and Holo Dark themes. The package also includes unstyled icons that you can
+modify to match your theme, plus source files.</p>
+
+  </div>
+  <div class="layout-content-col span-4">
+
+    <img src="{@docRoot}design/media/iconography_actionbar_style.png">
+
+  </div>
+  <div class="layout-content-col span-4">
+
+<p>
+  <a class="download-button" href="https://dl-ssl.google.com/android/design/Android_Design_Icons_20120229.zip">Action Bar Icon Pack</a>
+</p>
+
+  </div>
+</div>
+
+<h2 id="style">Style</h2>
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-5">
+
+<h4>Roboto</h4>
+<p>Ice Cream Sandwich introduced a new type family named Roboto, created specifically for the
+requirements of UI and high-resolution screens.</p>
+<p><a href="{@docRoot}design/style/typography.html#actionbar">More on Roboto</a></p>
+
+  </div>
+  <div class="layout-content-col span-4">
+
+    <img src="{@docRoot}design/media/downloads_roboto_specimen_preview.png">
+
+  </div>
+  <div class="layout-content-col span-4">
+
+<p>
+  <a class="download-button" href="https://dl-ssl.google.com/android/design/Roboto_Hinted_20111129.zip">Roboto</a>
+  <a class="download-button" href="https://dl-ssl.google.com/android/design/Roboto_Specimen_Book_20111129.pdf">Specimen Book</a>
+</p>
+
+  </div>
+</div>
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-5">
+
+<h4>Color</h4>
+<p>Blue is the standard accent color in Android's color palette. Each color has a corresponding darker
+shade that can be used as a complement when needed.</p>
+<p><a href="{@docRoot}design/style/color.html">More on Color</a></p>
+
+  </div>
+  <div class="layout-content-col span-4">
+
+    <img src="{@docRoot}design/media/downloads_color_swatches.png">
+
+  </div>
+  <div class="layout-content-col span-4">
+
+<p>
+  <a class="download-button" href="https://dl-ssl.google.com/android/design/Android_Design_Color_Swatches_20120229.zip">Color Swatches</a>
+</p>
+
+  </div>
+</div>
diff --git a/docs/html/design/get-started/creative-vision.html b/docs/html/design/get-started/creative-vision.html
deleted file mode 100644
index 154f8d0..0000000
--- a/docs/html/design/get-started/creative-vision.html
+++ /dev/null
@@ -1,205 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-  <head>
-    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
-    <title>
-
-Android Design - Creative Vision
-    </title>
-    <link rel="shortcut icon" type="image/x-icon" href="/favicon.ico">
-    <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Roboto:regular,medium,thin,italic,mediumitalic">
-    <link rel="stylesheet" href="../static/yui-3.3.0-reset-min.css">
-    <link rel="stylesheet" href="../static/default.css">
-
-  </head>
-  <body>
-
-    <div id="page-container">
-
-      <div id="page-header"><a href="../index.html">Android Design</a></div>
-
-      <div id="main-row">
-
-        <ul id="nav">
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../index.html">Get Started</a></div>
-            <ul>
-              <li><a href="../get-started/creative-vision.html">Creative Vision</a></li>
-              <li><a href="../get-started/principles.html">Design Principles</a></li>
-              <li><a href="../get-started/ui-overview.html">UI Overview</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../style/index.html">Style</a></div>
-            <ul>
-              <li><a href="../style/devices-displays.html">Devices and Displays</a></li>
-              <li><a href="../style/themes.html">Themes</a></li>
-              <li><a href="../style/touch-feedback.html">Touch Feedback</a></li>
-              <li><a href="../style/metrics-grids.html">Metrics and Grids</a></li>
-              <li><a href="../style/typography.html">Typography</a></li>
-              <li><a href="../style/color.html">Color</a></li>
-              <li><a href="../style/iconography.html">Iconography</a></li>
-              <li><a href="../style/writing.html">Writing Style</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../patterns/index.html">Patterns</a></div>
-            <ul>
-              <li><a href="../patterns/new-4-0.html">New in Android 4.0</a></li>
-              <li><a href="../patterns/gestures.html">Gestures</a></li>
-              <li><a href="../patterns/app-structure.html">App Structure</a></li>
-              <li><a href="../patterns/navigation.html">Navigation</a></li>
-              <li><a href="../patterns/actionbar.html">Action Bar</a></li>
-              <li><a href="../patterns/multi-pane-layouts.html">Multi-pane Layouts</a></li>
-              <li><a href="../patterns/swipe-views.html">Swipe Views</a></li>
-              <li><a href="../patterns/selection.html">Selection</a></li>
-              <li><a href="../patterns/notifications.html">Notifications</a></li>
-              <li><a href="../patterns/compatibility.html">Compatibility</a></li>
-              <li><a href="../patterns/pure-android.html">Pure Android</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../building-blocks/index.html">Building Blocks</a></div>
-            <ul>
-              <li><a href="../building-blocks/tabs.html">Tabs</a></li>
-              <li><a href="../building-blocks/lists.html">Lists</a></li>
-              <li><a href="../building-blocks/grid-lists.html">Grid Lists</a></li>
-              <li><a href="../building-blocks/scrolling.html">Scrolling</a></li>
-              <li><a href="../building-blocks/spinners.html">Spinners</a></li>
-              <li><a href="../building-blocks/buttons.html">Buttons</a></li>
-              <li><a href="../building-blocks/text-fields.html">Text Fields</a></li>
-              <li><a href="../building-blocks/seek-bars.html">Seek Bars</a></li>
-              <li><a href="../building-blocks/progress.html">Progress &amp; Activity</a></li>
-              <li><a href="../building-blocks/switches.html">Switches</a></li>
-              <li><a href="../building-blocks/dialogs.html">Dialogs</a></li>
-              <li><a href="../building-blocks/pickers.html">Pickers</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header empty"><a href="../downloads/index.html">Downloads</a></div>
-          </li>
-
-          <li>
-            <div id="back-dac-section"><a href="../../index.html">Developers</a></div>
-          </li>
-
-        </ul>
-
-        <div id="content">
-
-          
-          <div class="layout-content-row content-header">
-            <div class="layout-content-col span-9">
-              <h2>Creative Vision</h2>
-            </div>
-            <div class="paging-links layout-content-col span-4">
-              <a href="#" class="prev-page-link">Previous</a>
-              <a href="#" class="next-page-link">Next</a>
-            </div>
-          </div>
-          
-
-          
-
-<img src="../static/content/creative_vision_main.png">
-
-<div class="vspace size-1">&nbsp;</div>
-
-<p>Ice Cream Sandwich (Android 4.0) marks a major milestone for Android design. We touched nearly every
-pixel of the system as we expanded the new design approaches introduced in Honeycomb tablets to all
-types of mobile devices. Starting with the most basic elements, we introduced a new font, Roboto,
-designed for high-resolution displays. Other big changes include framework-level action bars on
-phones and support for new phones without physical buttons.</p>
-<p>We focused the design work with three overarching goals for our core apps and the system at large.
-As you design apps to work with Android, consider these goals:</p>
-
-<div class="vspace size-1">&nbsp;</div>
-
-<div class="layout-content-row">
-  <div class="layout-content-col span-4">
-
-<h4>Enchant me</h4>
-<p>Beauty is more than skin deep. Android apps are sleek and aesthetically pleasing on multiple levels.
-Transitions are fast and clear; layout and typography are crisp and meaningful. App icons are works
-of art in their own right. Just like a well-made tool, your app should strive to combine beauty,
-simplicity and purpose to create a magical experience that is effortless and powerful.</p>
-
-  </div>
-  <div class="layout-content-col span-5">
-
-<h4>Simplify my life</h4>
-<p>Android apps make life easier and are easy to understand. When people use your app for the first
-time, they should intuitively grasp the most important features. The design work doesn't stop at the
-first use, though. Android apps remove ongoing chores like file management and syncing. Simple tasks
-never require complex procedures, and complex tasks are tailored to the human hand and mind. People
-of all ages and cultures feel firmly in control, and are never overwhelmed by too many choices or
-irrelevant flash.</p>
-
-  </div>
-  <div class="layout-content-col span-4">
-
-<h4>Make me amazing</h4>
-<p>It's not enough to make an app that is easy to use. Android apps empower people to try new things
-and to use apps in inventive new ways. Android lets people combine applications into new workflows
-through multitasking, notifications, and sharing across apps. At the same time, your app should feel
-personal, giving people access to superb technology with clarity and grace.</p>
-
-  </div>
-</div>
-
-
-
-          
-          <div class="layout-content-row content-footer">
-            <div class="paging-links layout-content-col span-9">&nbsp;</div>
-            <div class="paging-links layout-content-col span-4">
-              <a href="#" class="prev-page-link">Previous</a>
-              <a href="#" class="next-page-link">Next</a>
-            </div>
-          </div>
-          
-        </div>
-
-      </div>
-
-      <div id="page-footer">
-
-        <p id="copyright">
-          Except as noted, this content is licensed under
-          <a href="http://creativecommons.org/licenses/by/2.5/">
-          Creative Commons Attribution 2.5</a>.<br>
-          For details and restrictions, see the
-          <a href="http://developer.android.com/license.html">Content License</a>.
-        </p>
-
-        <p>
-          <a href="http://www.android.com/terms.html">Site Terms of Service</a> &ndash;
-          <a href="http://www.android.com/privacy.html">Privacy Policy</a> &ndash;
-          <a href="http://www.android.com/branding.html">Brand Guidelines</a>
-        </p>
-
-      </div>
-    </div>
-
-    <script src="../static/jquery-1.6.2.min.js"></script>
-    <script>
-    var SITE_ROOT = '../';
-    </script>
-    <script src="../static/default.js"></script>
-
-
-    <script type="text/javascript">
-    var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
-    document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
-    </script>
-    <script type="text/javascript">
-    var pageTracker = _gat._getTracker("UA-5831155-1");
-    pageTracker._trackPageview();
-    </script>
-  </body>
-</html>
diff --git a/docs/html/design/get-started/creative-vision.jd b/docs/html/design/get-started/creative-vision.jd
new file mode 100644
index 0000000..792b97d
--- /dev/null
+++ b/docs/html/design/get-started/creative-vision.jd
@@ -0,0 +1,48 @@
+page.title=Creative Vision
+@jd:body
+
+<img src="{@docRoot}design/media/creative_vision_main.png">
+
+<div class="vspace size-1">&nbsp;</div>
+
+<p>Ice Cream Sandwich (Android 4.0) marks a major milestone for Android design. We touched nearly every
+pixel of the system as we expanded the new design approaches introduced in Honeycomb tablets to all
+types of mobile devices. Starting with the most basic elements, we introduced a new font, Roboto,
+designed for high-resolution displays. Other big changes include framework-level action bars on
+phones and support for new phones without physical buttons.</p>
+<p>We focused the design work with three overarching goals for our core apps and the system at large.
+As you design apps to work with Android, consider these goals:</p>
+
+<div class="vspace size-1">&nbsp;</div>
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-4">
+
+<h4>Enchant me</h4>
+<p>Beauty is more than skin deep. Android apps are sleek and aesthetically pleasing on multiple levels.
+Transitions are fast and clear; layout and typography are crisp and meaningful. App icons are works
+of art in their own right. Just like a well-made tool, your app should strive to combine beauty,
+simplicity and purpose to create a magical experience that is effortless and powerful.</p>
+
+  </div>
+  <div class="layout-content-col span-5">
+
+<h4>Simplify my life</h4>
+<p>Android apps make life easier and are easy to understand. When people use your app for the first
+time, they should intuitively grasp the most important features. The design work doesn't stop at the
+first use, though. Android apps remove ongoing chores like file management and syncing. Simple tasks
+never require complex procedures, and complex tasks are tailored to the human hand and mind. People
+of all ages and cultures feel firmly in control, and are never overwhelmed by too many choices or
+irrelevant flash.</p>
+
+  </div>
+  <div class="layout-content-col span-4">
+
+<h4>Make me amazing</h4>
+<p>It's not enough to make an app that is easy to use. Android apps empower people to try new things
+and to use apps in inventive new ways. Android lets people combine applications into new workflows
+through multitasking, notifications, and sharing across apps. At the same time, your app should feel
+personal, giving people access to superb technology with clarity and grace.</p>
+
+  </div>
+</div>
diff --git a/docs/html/design/get-started/principles.html b/docs/html/design/get-started/principles.html
deleted file mode 100644
index f10a90d..0000000
--- a/docs/html/design/get-started/principles.html
+++ /dev/null
@@ -1,457 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-  <head>
-    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
-    <title>
-
-Android Design - Design Principles
-    </title>
-    <link rel="shortcut icon" type="image/x-icon" href="/favicon.ico">
-    <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Roboto:regular,medium,thin,italic,mediumitalic">
-    <link rel="stylesheet" href="../static/yui-3.3.0-reset-min.css">
-    <link rel="stylesheet" href="../static/default.css">
-
-  </head>
-  <body>
-
-    <div id="page-container">
-
-      <div id="page-header"><a href="../index.html">Android Design</a></div>
-
-      <div id="main-row">
-
-        <ul id="nav">
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../index.html">Get Started</a></div>
-            <ul>
-              <li><a href="../get-started/creative-vision.html">Creative Vision</a></li>
-              <li><a href="../get-started/principles.html">Design Principles</a></li>
-              <li><a href="../get-started/ui-overview.html">UI Overview</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../style/index.html">Style</a></div>
-            <ul>
-              <li><a href="../style/devices-displays.html">Devices and Displays</a></li>
-              <li><a href="../style/themes.html">Themes</a></li>
-              <li><a href="../style/touch-feedback.html">Touch Feedback</a></li>
-              <li><a href="../style/metrics-grids.html">Metrics and Grids</a></li>
-              <li><a href="../style/typography.html">Typography</a></li>
-              <li><a href="../style/color.html">Color</a></li>
-              <li><a href="../style/iconography.html">Iconography</a></li>
-              <li><a href="../style/writing.html">Writing Style</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../patterns/index.html">Patterns</a></div>
-            <ul>
-              <li><a href="../patterns/new-4-0.html">New in Android 4.0</a></li>
-              <li><a href="../patterns/gestures.html">Gestures</a></li>
-              <li><a href="../patterns/app-structure.html">App Structure</a></li>
-              <li><a href="../patterns/navigation.html">Navigation</a></li>
-              <li><a href="../patterns/actionbar.html">Action Bar</a></li>
-              <li><a href="../patterns/multi-pane-layouts.html">Multi-pane Layouts</a></li>
-              <li><a href="../patterns/swipe-views.html">Swipe Views</a></li>
-              <li><a href="../patterns/selection.html">Selection</a></li>
-              <li><a href="../patterns/notifications.html">Notifications</a></li>
-              <li><a href="../patterns/compatibility.html">Compatibility</a></li>
-              <li><a href="../patterns/pure-android.html">Pure Android</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../building-blocks/index.html">Building Blocks</a></div>
-            <ul>
-              <li><a href="../building-blocks/tabs.html">Tabs</a></li>
-              <li><a href="../building-blocks/lists.html">Lists</a></li>
-              <li><a href="../building-blocks/grid-lists.html">Grid Lists</a></li>
-              <li><a href="../building-blocks/scrolling.html">Scrolling</a></li>
-              <li><a href="../building-blocks/spinners.html">Spinners</a></li>
-              <li><a href="../building-blocks/buttons.html">Buttons</a></li>
-              <li><a href="../building-blocks/text-fields.html">Text Fields</a></li>
-              <li><a href="../building-blocks/seek-bars.html">Seek Bars</a></li>
-              <li><a href="../building-blocks/progress.html">Progress &amp; Activity</a></li>
-              <li><a href="../building-blocks/switches.html">Switches</a></li>
-              <li><a href="../building-blocks/dialogs.html">Dialogs</a></li>
-              <li><a href="../building-blocks/pickers.html">Pickers</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header empty"><a href="../downloads/index.html">Downloads</a></div>
-          </li>
-
-          <li>
-            <div id="back-dac-section"><a href="../../index.html">Developers</a></div>
-          </li>
-
-        </ul>
-
-        <div id="content">
-
-          
-          <div class="layout-content-row content-header">
-            <div class="layout-content-col span-9">
-              <h2>Design Principles</h2>
-            </div>
-            <div class="paging-links layout-content-col span-4">
-              <a href="#" class="prev-page-link">Previous</a>
-              <a href="#" class="next-page-link">Next</a>
-            </div>
-          </div>
-          
-
-          
-
-<p>These design principles were developed by and for the Android User Experience Team to keep users'
-best interests in mind. Consider them as you apply your own creativity and design thinking. Deviate
-with purpose.</p>
-
-<h2 id="enchant-me">Enchant Me</h2>
-
-<div class="layout-content-row">
-  <div class="layout-content-col span-7">
-
-<h4>Delight me in surprising ways</h4>
-<p>A beautiful surface, a carefully-placed animation, or a well-timed sound effect is a joy to
-experience. Subtle effects contribute to a feeling of effortlessness and a sense that a powerful
-force is at hand.</p>
-
-  </div>
-  <div class="layout-content-col span-6">
-
-    <img src="../static/content/principles_delight.png">
-
-  </div>
-</div>
-
-<div class="vspace size-2">&nbsp;</div>
-
-<div class="layout-content-row">
-  <div class="layout-content-col span-7">
-
-<h4>Real objects are more fun than buttons and menus</h4>
-<p>Allow people to directly touch and manipulate objects in your app. It reduces the cognitive effort
-needed to perform a task while making it more emotionally satisfying.</p>
-
-  </div>
-  <div class="layout-content-col span-6">
-
-    <img src="../static/content/principles_real_objects.png">
-
-  </div>
-</div>
-
-<div class="vspace size-2">&nbsp;</div>
-
-<div class="layout-content-row">
-  <div class="layout-content-col span-7">
-
-<h4>Let me make it mine</h4>
-<p>People love to add personal touches because it helps them feel at home and in control. Provide
-sensible, beautiful defaults, but also consider fun, optional customizations that don't hinder
-primary tasks.</p>
-
-  </div>
-  <div class="layout-content-col span-6">
-
-    <img src="../static/content/principles_make_it_mine.png">
-
-  </div>
-</div>
-
-<div class="vspace size-2">&nbsp;</div>
-
-<div class="layout-content-row">
-  <div class="layout-content-col span-7">
-
-<h4>Get to know me</h4>
-<p>Learn peoples' preferences over time. Rather than asking them to make the same choices over and
-over, place previous choices within easy reach.</p>
-
-  </div>
-  <div class="layout-content-col span-6">
-
-    <img src="../static/content/principles_get_to_know_me.png">
-
-  </div>
-</div>
-
-<h2 id="simplify-my-life">Simplify My Life</h2>
-
-<div class="layout-content-row">
-  <div class="layout-content-col span-7">
-
-<h4>Keep it brief</h4>
-<p>Use short phrases with simple words. People are likely to skip sentences if they're long.</p>
-
-  </div>
-  <div class="layout-content-col span-6">
-
-    <img src="../static/content/principles_keep_it_brief.png">
-
-  </div>
-</div>
-
-<div class="vspace size-2">&nbsp;</div>
-
-<div class="layout-content-row">
-  <div class="layout-content-col span-7">
-
-<h4>Pictures are faster than words</h4>
-<p>Consider using pictures to explain ideas. They get people's attention and can be much more efficient
-than words.</p>
-
-  </div>
-  <div class="layout-content-col span-6">
-
-    <img src="../static/content/principles_pictures.png">
-
-  </div>
-</div>
-
-<div class="vspace size-2">&nbsp;</div>
-
-<div class="layout-content-row">
-  <div class="layout-content-col span-7">
-
-<h4>Decide for me but let me have the final say</h4>
-<p>Take your best guess and act rather than asking first. Too many choices and decisions make people
-unhappy. Just in case you get it wrong, allow for 'undo'.</p>
-
-  </div>
-  <div class="layout-content-col span-6">
-
-    <img src="../static/content/principles_decide_for_me.png">
-
-  </div>
-</div>
-
-<div class="vspace size-2">&nbsp;</div>
-
-<div class="layout-content-row">
-  <div class="layout-content-col span-7">
-
-<h4>Only show what I need when I need it</h4>
-<p>People get overwhelmed when they see too much at once. Break tasks and information into small,
-digestible chunks. Hide options that aren't essential at the moment, and teach people as they go.</p>
-
-  </div>
-  <div class="layout-content-col span-6">
-
-    <img src="../static/content/principles_information_when_need_it.png">
-
-  </div>
-</div>
-
-<div class="vspace size-2">&nbsp;</div>
-
-<div class="layout-content-row">
-  <div class="layout-content-col span-7">
-
-<h4>I should always know where I am</h4>
-<p>Give people confidence that they know their way around. Make places in your app look distinct and
-use transitions to show relationships among screens. Provide feedback on tasks in progress.</p>
-
-  </div>
-  <div class="layout-content-col span-6">
-
-    <img src="../static/content/principles_navigation.png">
-
-  </div>
-</div>
-
-<div class="vspace size-2">&nbsp;</div>
-
-<div class="layout-content-row">
-  <div class="layout-content-col span-7">
-
-<h4>Never lose my stuff</h4>
-<p>Save what people took time to create and let them access it from anywhere. Remember settings,
-personal touches, and creations across phones, tablets, and computers. It makes upgrading the
-easiest thing in the world.</p>
-
-  </div>
-  <div class="layout-content-col span-6">
-
-    <img src="../static/content/principles_never_lose_stuff.png">
-
-  </div>
-</div>
-
-<div class="vspace size-2">&nbsp;</div>
-
-<div class="layout-content-row">
-  <div class="layout-content-col span-7">
-
-<h4>If it looks the same, it should act the same</h4>
-<p>Help people discern functional differences by making them visually distinct rather than subtle.
-Avoid modes, which are places that look similar but act differently on the same input.</p>
-
-  </div>
-  <div class="layout-content-col span-6">
-
-    <img src="../static/content/principles_looks_same.png">
-
-  </div>
-</div>
-
-<div class="vspace size-2">&nbsp;</div>
-
-<div class="layout-content-row">
-  <div class="layout-content-col span-7">
-
-<h4>Only interrupt me if it's important</h4>
-<p>Like a good personal assistant, shield people from unimportant minutiae. People want to stay
-focused, and unless it's critical and time-sensitive, an interruption can be taxing and frustrating.</p>
-
-  </div>
-  <div class="layout-content-col span-6">
-
-    <img src="../static/content/principles_important_interruption.png">
-
-  </div>
-</div>
-
-<h2 id="make-me-amazing">Make Me Amazing</h2>
-
-<div class="layout-content-row">
-  <div class="layout-content-col span-7">
-
-<h4>Give me tricks that work everywhere</h4>
-<p>People feel great when they figure things out for themselves. Make your app easier to learn by
-leveraging visual patterns and muscle memory from other Android apps. For example, the swipe gesture
-may be a good navigational shortcut.</p>
-
-  </div>
-  <div class="layout-content-col span-6">
-
-    <img src="../static/content/principles_tricks.png">
-
-  </div>
-</div>
-
-<div class="vspace size-2">&nbsp;</div>
-
-<div class="layout-content-row">
-  <div class="layout-content-col span-7">
-
-<h4>It's not my fault</h4>
-<p>Be gentle in how you prompt people to make corrections. They want to feel smart when they use your
-app. If something goes wrong, give clear recovery instructions but spare them the technical details.
-If you can fix it behind the scenes, even better.</p>
-
-  </div>
-  <div class="layout-content-col span-6">
-
-    <img src="../static/content/principles_error.png">
-
-  </div>
-</div>
-
-<div class="vspace size-2">&nbsp;</div>
-
-<div class="layout-content-row">
-  <div class="layout-content-col span-7">
-
-<h4>Sprinkle encouragement</h4>
-<p>Break complex tasks into smaller steps that can be easily accomplished. Give feedback on actions,
-even if it's just a subtle glow.</p>
-
-  </div>
-  <div class="layout-content-col span-6">
-
-    <img src="../static/content/principles_sprinkle_encouragement.png">
-
-  </div>
-</div>
-
-<div class="vspace size-2">&nbsp;</div>
-
-<div class="layout-content-row">
-  <div class="layout-content-col span-7">
-
-<h4>Do the heavy lifting for me</h4>
-<p>Make novices feel like experts by enabling them to do things they never thought they could. For
-example, shortcuts that combine multiple photo effects can make amateur photographs look amazing in
-only a few steps.</p>
-
-  </div>
-  <div class="layout-content-col span-6">
-
-    <img src="../static/content/principles_heavy_lifting.png">
-
-  </div>
-</div>
-
-<div class="vspace size-2">&nbsp;</div>
-
-<div class="layout-content-row">
-  <div class="layout-content-col span-7">
-
-<h4>Make important things fast</h4>
-<p>Not all actions are equal. Decide what's most important in your app and make it easy to find and
-fast to use, like the shutter button in a camera, or the pause button in a music player.</p>
-
-  </div>
-  <div class="layout-content-col span-6">
-
-    <img src="../static/content/principles_make_important_fast.png">
-
-  </div>
-</div>
-
-
-
-          
-          <div class="layout-content-row content-footer">
-            <div class="paging-links layout-content-col span-9">&nbsp;</div>
-            <div class="paging-links layout-content-col span-4">
-              <a href="#" class="prev-page-link">Previous</a>
-              <a href="#" class="next-page-link">Next</a>
-            </div>
-          </div>
-          
-        </div>
-
-      </div>
-
-      <div id="page-footer">
-
-        <p id="copyright">
-          Except as noted, this content is licensed under
-          <a href="http://creativecommons.org/licenses/by/2.5/">
-          Creative Commons Attribution 2.5</a>.<br>
-          For details and restrictions, see the
-          <a href="http://developer.android.com/license.html">Content License</a>.
-        </p>
-
-        <p>
-          <a href="http://www.android.com/terms.html">Site Terms of Service</a> &ndash;
-          <a href="http://www.android.com/privacy.html">Privacy Policy</a> &ndash;
-          <a href="http://www.android.com/branding.html">Brand Guidelines</a>
-        </p>
-
-      </div>
-    </div>
-
-    <script src="../static/jquery-1.6.2.min.js"></script>
-    <script>
-    var SITE_ROOT = '../';
-    </script>
-    <script src="../static/default.js"></script>
-
-
-    <script type="text/javascript">
-    var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
-    document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
-    </script>
-    <script type="text/javascript">
-    var pageTracker = _gat._getTracker("UA-5831155-1");
-    pageTracker._trackPageview();
-    </script>
-  </body>
-</html>
diff --git a/docs/html/design/get-started/principles.jd b/docs/html/design/get-started/principles.jd
new file mode 100644
index 0000000..8f5b446
--- /dev/null
+++ b/docs/html/design/get-started/principles.jd
@@ -0,0 +1,300 @@
+page.title=Design Principles
+@jd:body
+
+<p>These design principles were developed by and for the Android User Experience Team to keep users'
+best interests in mind. Consider them as you apply your own creativity and design thinking. Deviate
+with purpose.</p>
+
+<h2 id="enchant-me">Enchant Me</h2>
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-7">
+
+<h4>Delight me in surprising ways</h4>
+<p>A beautiful surface, a carefully-placed animation, or a well-timed sound effect is a joy to
+experience. Subtle effects contribute to a feeling of effortlessness and a sense that a powerful
+force is at hand.</p>
+
+  </div>
+  <div class="layout-content-col span-6">
+
+    <img src="{@docRoot}design/media/principles_delight.png">
+
+  </div>
+</div>
+
+<div class="vspace size-2">&nbsp;</div>
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-7">
+
+<h4>Real objects are more fun than buttons and menus</h4>
+<p>Allow people to directly touch and manipulate objects in your app. It reduces the cognitive effort
+needed to perform a task while making it more emotionally satisfying.</p>
+
+  </div>
+  <div class="layout-content-col span-6">
+
+    <img src="{@docRoot}design/media/principles_real_objects.png">
+
+  </div>
+</div>
+
+<div class="vspace size-2">&nbsp;</div>
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-7">
+
+<h4>Let me make it mine</h4>
+<p>People love to add personal touches because it helps them feel at home and in control. Provide
+sensible, beautiful defaults, but also consider fun, optional customizations that don't hinder
+primary tasks.</p>
+
+  </div>
+  <div class="layout-content-col span-6">
+
+    <img src="{@docRoot}design/media/principles_make_it_mine.png">
+
+  </div>
+</div>
+
+<div class="vspace size-2">&nbsp;</div>
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-7">
+
+<h4>Get to know me</h4>
+<p>Learn peoples' preferences over time. Rather than asking them to make the same choices over and
+over, place previous choices within easy reach.</p>
+
+  </div>
+  <div class="layout-content-col span-6">
+
+    <img src="{@docRoot}design/media/principles_get_to_know_me.png">
+
+  </div>
+</div>
+
+<h2 id="simplify-my-life">Simplify My Life</h2>
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-7">
+
+<h4>Keep it brief</h4>
+<p>Use short phrases with simple words. People are likely to skip sentences if they're long.</p>
+
+  </div>
+  <div class="layout-content-col span-6">
+
+    <img src="{@docRoot}design/media/principles_keep_it_brief.png">
+
+  </div>
+</div>
+
+<div class="vspace size-2">&nbsp;</div>
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-7">
+
+<h4>Pictures are faster than words</h4>
+<p>Consider using pictures to explain ideas. They get people's attention and can be much more efficient
+than words.</p>
+
+  </div>
+  <div class="layout-content-col span-6">
+
+    <img src="{@docRoot}design/media/principles_pictures.png">
+
+  </div>
+</div>
+
+<div class="vspace size-2">&nbsp;</div>
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-7">
+
+<h4>Decide for me but let me have the final say</h4>
+<p>Take your best guess and act rather than asking first. Too many choices and decisions make people
+unhappy. Just in case you get it wrong, allow for 'undo'.</p>
+
+  </div>
+  <div class="layout-content-col span-6">
+
+    <img src="{@docRoot}design/media/principles_decide_for_me.png">
+
+  </div>
+</div>
+
+<div class="vspace size-2">&nbsp;</div>
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-7">
+
+<h4>Only show what I need when I need it</h4>
+<p>People get overwhelmed when they see too much at once. Break tasks and information into small,
+digestible chunks. Hide options that aren't essential at the moment, and teach people as they go.</p>
+
+  </div>
+  <div class="layout-content-col span-6">
+
+    <img src="{@docRoot}design/media/principles_information_when_need_it.png">
+
+  </div>
+</div>
+
+<div class="vspace size-2">&nbsp;</div>
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-7">
+
+<h4>I should always know where I am</h4>
+<p>Give people confidence that they know their way around. Make places in your app look distinct and
+use transitions to show relationships among screens. Provide feedback on tasks in progress.</p>
+
+  </div>
+  <div class="layout-content-col span-6">
+
+    <img src="{@docRoot}design/media/principles_navigation.png">
+
+  </div>
+</div>
+
+<div class="vspace size-2">&nbsp;</div>
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-7">
+
+<h4>Never lose my stuff</h4>
+<p>Save what people took time to create and let them access it from anywhere. Remember settings,
+personal touches, and creations across phones, tablets, and computers. It makes upgrading the
+easiest thing in the world.</p>
+
+  </div>
+  <div class="layout-content-col span-6">
+
+    <img src="{@docRoot}design/media/principles_never_lose_stuff.png">
+
+  </div>
+</div>
+
+<div class="vspace size-2">&nbsp;</div>
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-7">
+
+<h4>If it looks the same, it should act the same</h4>
+<p>Help people discern functional differences by making them visually distinct rather than subtle.
+Avoid modes, which are places that look similar but act differently on the same input.</p>
+
+  </div>
+  <div class="layout-content-col span-6">
+
+    <img src="{@docRoot}design/media/principles_looks_same.png">
+
+  </div>
+</div>
+
+<div class="vspace size-2">&nbsp;</div>
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-7">
+
+<h4>Only interrupt me if it's important</h4>
+<p>Like a good personal assistant, shield people from unimportant minutiae. People want to stay
+focused, and unless it's critical and time-sensitive, an interruption can be taxing and frustrating.</p>
+
+  </div>
+  <div class="layout-content-col span-6">
+
+    <img src="{@docRoot}design/media/principles_important_interruption.png">
+
+  </div>
+</div>
+
+<h2 id="make-me-amazing">Make Me Amazing</h2>
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-7">
+
+<h4>Give me tricks that work everywhere</h4>
+<p>People feel great when they figure things out for themselves. Make your app easier to learn by
+leveraging visual patterns and muscle memory from other Android apps. For example, the swipe gesture
+may be a good navigational shortcut.</p>
+
+  </div>
+  <div class="layout-content-col span-6">
+
+    <img src="{@docRoot}design/media/principles_tricks.png">
+
+  </div>
+</div>
+
+<div class="vspace size-2">&nbsp;</div>
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-7">
+
+<h4>It's not my fault</h4>
+<p>Be gentle in how you prompt people to make corrections. They want to feel smart when they use your
+app. If something goes wrong, give clear recovery instructions but spare them the technical details.
+If you can fix it behind the scenes, even better.</p>
+
+  </div>
+  <div class="layout-content-col span-6">
+
+    <img src="{@docRoot}design/media/principles_error.png">
+
+  </div>
+</div>
+
+<div class="vspace size-2">&nbsp;</div>
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-7">
+
+<h4>Sprinkle encouragement</h4>
+<p>Break complex tasks into smaller steps that can be easily accomplished. Give feedback on actions,
+even if it's just a subtle glow.</p>
+
+  </div>
+  <div class="layout-content-col span-6">
+
+    <img src="{@docRoot}design/media/principles_sprinkle_encouragement.png">
+
+  </div>
+</div>
+
+<div class="vspace size-2">&nbsp;</div>
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-7">
+
+<h4>Do the heavy lifting for me</h4>
+<p>Make novices feel like experts by enabling them to do things they never thought they could. For
+example, shortcuts that combine multiple photo effects can make amateur photographs look amazing in
+only a few steps.</p>
+
+  </div>
+  <div class="layout-content-col span-6">
+
+    <img src="{@docRoot}design/media/principles_heavy_lifting.png">
+
+  </div>
+</div>
+
+<div class="vspace size-2">&nbsp;</div>
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-7">
+
+<h4>Make important things fast</h4>
+<p>Not all actions are equal. Decide what's most important in your app and make it easy to find and
+fast to use, like the shutter button in a camera, or the pause button in a music player.</p>
+
+  </div>
+  <div class="layout-content-col span-6">
+
+    <img src="{@docRoot}design/media/principles_make_important_fast.png">
+
+  </div>
+</div>
diff --git a/docs/html/design/get-started/ui-overview.html b/docs/html/design/get-started/ui-overview.html
deleted file mode 100644
index a4881d5..0000000
--- a/docs/html/design/get-started/ui-overview.html
+++ /dev/null
@@ -1,306 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-  <head>
-    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
-    <title>
-
-Android Design - UI Overview
-    </title>
-    <link rel="shortcut icon" type="image/x-icon" href="/favicon.ico">
-    <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Roboto:regular,medium,thin,italic,mediumitalic">
-    <link rel="stylesheet" href="../static/yui-3.3.0-reset-min.css">
-    <link rel="stylesheet" href="../static/default.css">
-
-  </head>
-  <body>
-
-    <div id="page-container">
-
-      <div id="page-header"><a href="../index.html">Android Design</a></div>
-
-      <div id="main-row">
-
-        <ul id="nav">
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../index.html">Get Started</a></div>
-            <ul>
-              <li><a href="../get-started/creative-vision.html">Creative Vision</a></li>
-              <li><a href="../get-started/principles.html">Design Principles</a></li>
-              <li><a href="../get-started/ui-overview.html">UI Overview</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../style/index.html">Style</a></div>
-            <ul>
-              <li><a href="../style/devices-displays.html">Devices and Displays</a></li>
-              <li><a href="../style/themes.html">Themes</a></li>
-              <li><a href="../style/touch-feedback.html">Touch Feedback</a></li>
-              <li><a href="../style/metrics-grids.html">Metrics and Grids</a></li>
-              <li><a href="../style/typography.html">Typography</a></li>
-              <li><a href="../style/color.html">Color</a></li>
-              <li><a href="../style/iconography.html">Iconography</a></li>
-              <li><a href="../style/writing.html">Writing Style</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../patterns/index.html">Patterns</a></div>
-            <ul>
-              <li><a href="../patterns/new-4-0.html">New in Android 4.0</a></li>
-              <li><a href="../patterns/gestures.html">Gestures</a></li>
-              <li><a href="../patterns/app-structure.html">App Structure</a></li>
-              <li><a href="../patterns/navigation.html">Navigation</a></li>
-              <li><a href="../patterns/actionbar.html">Action Bar</a></li>
-              <li><a href="../patterns/multi-pane-layouts.html">Multi-pane Layouts</a></li>
-              <li><a href="../patterns/swipe-views.html">Swipe Views</a></li>
-              <li><a href="../patterns/selection.html">Selection</a></li>
-              <li><a href="../patterns/notifications.html">Notifications</a></li>
-              <li><a href="../patterns/compatibility.html">Compatibility</a></li>
-              <li><a href="../patterns/pure-android.html">Pure Android</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../building-blocks/index.html">Building Blocks</a></div>
-            <ul>
-              <li><a href="../building-blocks/tabs.html">Tabs</a></li>
-              <li><a href="../building-blocks/lists.html">Lists</a></li>
-              <li><a href="../building-blocks/grid-lists.html">Grid Lists</a></li>
-              <li><a href="../building-blocks/scrolling.html">Scrolling</a></li>
-              <li><a href="../building-blocks/spinners.html">Spinners</a></li>
-              <li><a href="../building-blocks/buttons.html">Buttons</a></li>
-              <li><a href="../building-blocks/text-fields.html">Text Fields</a></li>
-              <li><a href="../building-blocks/seek-bars.html">Seek Bars</a></li>
-              <li><a href="../building-blocks/progress.html">Progress &amp; Activity</a></li>
-              <li><a href="../building-blocks/switches.html">Switches</a></li>
-              <li><a href="../building-blocks/dialogs.html">Dialogs</a></li>
-              <li><a href="../building-blocks/pickers.html">Pickers</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header empty"><a href="../downloads/index.html">Downloads</a></div>
-          </li>
-
-          <li>
-            <div id="back-dac-section"><a href="../../index.html">Developers</a></div>
-          </li>
-
-        </ul>
-
-        <div id="content">
-
-          
-          <div class="layout-content-row content-header">
-            <div class="layout-content-col span-9">
-              <h2>UI Overview</h2>
-            </div>
-            <div class="paging-links layout-content-col span-4">
-              <a href="#" class="prev-page-link">Previous</a>
-              <a href="#" class="next-page-link">Next</a>
-            </div>
-          </div>
-          
-
-          
-
-<p>Android's system UI provides the framework on top of which you build your app. Important aspects
-include the Home screen experience, global device navigation, and notifications.</p>
-<p>Your app will play an important part in keeping the overall Android experience consistent and
-enjoyable to use. At the end of this chapter we introduce the main elements for achieving this goal
-in your app.</p>
-<p>Read on for a quick overview of the most important aspects of the Android user interface.</p>
-
-<h2 id="home-all-apps-recents">Home, All Apps, and Recents</h2>
-
-<div class="vspace size-1">&nbsp;</div>
-
-<div class="layout-content-row">
-  <div class="layout-content-col span-4">
-
-    <img src="../static/content/ui_overview_home_screen.png">
-
-<h4>Home screen</h4>
-<p>Home is a customizable space that houses app shortcuts, folders and widgets. Navigate between
-different home screen panels by swiping left and right.</p>
-<p>The Favorites Tray at the bottom always keeps your most important shortcuts and folders in view
-regardless of which panel is currently showing.</p>
-<p>Access the entire collection of apps and widgets by touching the All Apps button at the center of
-the Favorites Tray.</p>
-
-  </div>
-  <div class="layout-content-col span-4">
-
-    <img src="../static/content/ui_overview_all_apps.png">
-
-<h4>All apps screen</h4>
-<p>The All Apps screen lets you browse the entire set of apps and widgets that are installed on your
-device.</p>
-<p>Users can drag an app or widget icon from the All Apps screen and place it in any empty location on
-any Home screen.</p>
-
-  </div>
-  <div class="layout-content-col span-4">
-
-    <img src="../static/content/ui_overview_recents.png">
-
-<h4>Recents screen</h4>
-<p>Recents provides an efficient way of switching between recently used applications. It provides a
-clear navigation path between multiple ongoing tasks.</p>
-<p>The Recents button at the right side of the navigation bar displays the apps that the user has
-interacted with most recently. They are organized in reverse chronological order with the most
-recently used app at the bottom.</p>
-<p>Switch to an app by touching it. Remove an item by swiping left or right.</p>
-
-  </div>
-</div>
-
-<h2 id="system-bars">System Bars</h2>
-
-<p>The system bars are screen areas dedicated to the display of notifications, communication of device
-status, and device navigation. Typically the system bars are displayed concurrently with your app.
-Apps that display immersive content, such as movies or images, can temporarily hide the system bars
-to allow the user to enjoy full screen content without distraction.</p>
-
-<img src="../static/content/ui_overview_system_ui.png">
-
-<div class="with-callouts">
-
-<ol>
-<li>
-<h4>Status Bar</h4>
-<p>Displays pending notifications on the left and status, such as time, battery level, or signal
-  strength, on the right. Swipe down from the status bar to show notification details.</p>
-</li>
-<li>
-<h4>Navigation Bar</h4>
-<p>New for phones in Android 4.0, the navigation bar is present only on devices that don't have
-  the traditional hardware keys. It houses the device navigation controls Back, Home, and
-  Recents, and also displays a menu for apps written for Android 2.3 or earlier.</p>
-</li>
-<li>
-<h4>Combined Bar</h4>
-<p>On tablet form factors the status and navigation bars are combined into a single bar at the
-  bottom of the screen.</p>
-</li>
-</ol>
-
-</div>
-
-<h2 id="notifications">Notifications</h2>
-
-<p>Notifications are brief messages that users can access at any time from the status bar. They
-provide updates, reminders, or information that's important, but not critical enough to warrant
-interrupting the user. Open the notifications drawer by swiping down on the status bar. Touching a
-notification opens the associated app. <a href="../patterns/notifications.html">More on Notifications</a></p>
-
-<div class="layout-content-row">
-  <div class="layout-content-col span-4">
-
-    <img src="../static/content/ui_overview_notifications.png">
-
-  </div>
-  <div class="layout-content-col span-9">
-
-    <img src="../static/content/notifications_dismiss.png">
-
-<p>Most notifications have a one-line title and a one-line message. The recommended layout for a
-notification includes two lines. If necessary, you can add a third line. Timestamps are optional.</p>
-<p>Swiping a notification right or left removes it from the notification drawer.</p>
-
-  </div>
-</div>
-
-
-<h2 id="app">Common App UI</h2>
-
-
-<div class="layout-content-row">
-  <div class="layout-content-col span-7">
-
-    <img src="../static/content/ui_overview_app_ui.png">
-
-  </div>
-  <div class="layout-content-col span-6 with-callouts">
-
-<p>A typical Android app consists of action bars and the app content area.</p>
-<ol>
-<li>
-<h4>Main Action Bar</h4>
-<p>The command and control center for your app. The main action bar includes elements for
-  navigating your app's hierarchy and views, and also surfaces the most important actions.</p>
-<p><a href="../patterns/actionbar.html">More on the Action Bar</a></p>
-</li>
-<li>
-<h4>View Control</h4>
-<p>Allows users to switch between the different views that your app provides. Views typically
-  consist of different arrangements of your data or different functional aspects of your app.</p>
-</li>
-<li>
-<h4>Content Area</h4>
-<p>The space where the content of your app is displayed.</p>
-</li>
-<li>
-<h4>Split Action Bar</h4>
-<p>Split action bars provide a way to distribute actions across additional bars located below
-  the main action bar or at the bottom of the screen. In this example, a split action bar moves
-  important actions that won't fit in the main bar to the bottom.</p>
-</li>
-</ol>
-
-  </div>
-</div>
-
-
-
-          
-          <div class="layout-content-row content-footer">
-            <div class="paging-links layout-content-col span-9">&nbsp;</div>
-            <div class="paging-links layout-content-col span-4">
-              <a href="#" class="prev-page-link">Previous</a>
-              <a href="#" class="next-page-link">Next</a>
-            </div>
-          </div>
-          
-        </div>
-
-      </div>
-
-      <div id="page-footer">
-
-        <p id="copyright">
-          Except as noted, this content is licensed under
-          <a href="http://creativecommons.org/licenses/by/2.5/">
-          Creative Commons Attribution 2.5</a>.<br>
-          For details and restrictions, see the
-          <a href="http://developer.android.com/license.html">Content License</a>.
-        </p>
-
-        <p>
-          <a href="http://www.android.com/terms.html">Site Terms of Service</a> &ndash;
-          <a href="http://www.android.com/privacy.html">Privacy Policy</a> &ndash;
-          <a href="http://www.android.com/branding.html">Brand Guidelines</a>
-        </p>
-
-      </div>
-    </div>
-
-    <script src="../static/jquery-1.6.2.min.js"></script>
-    <script>
-    var SITE_ROOT = '../';
-    </script>
-    <script src="../static/default.js"></script>
-
-
-    <script type="text/javascript">
-    var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
-    document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
-    </script>
-    <script type="text/javascript">
-    var pageTracker = _gat._getTracker("UA-5831155-1");
-    pageTracker._trackPageview();
-    </script>
-  </body>
-</html>
diff --git a/docs/html/design/get-started/ui-overview.jd b/docs/html/design/get-started/ui-overview.jd
new file mode 100644
index 0000000..34cdd06
--- /dev/null
+++ b/docs/html/design/get-started/ui-overview.jd
@@ -0,0 +1,149 @@
+page.title=UI Overview
+@jd:body
+
+<p>Android's system UI provides the framework on top of which you build your app. Important aspects
+include the Home screen experience, global device navigation, and notifications.</p>
+<p>Your app will play an important part in keeping the overall Android experience consistent and
+enjoyable to use. At the end of this chapter we introduce the main elements for achieving this goal
+in your app.</p>
+<p>Read on for a quick overview of the most important aspects of the Android user interface.</p>
+
+<h2 id="home-all-apps-recents">Home, All Apps, and Recents</h2>
+
+<div class="vspace size-1">&nbsp;</div>
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-4">
+
+    <img src="{@docRoot}design/media/ui_overview_home_screen.png">
+
+<h4>Home screen</h4>
+<p>Home is a customizable space that houses app shortcuts, folders and widgets. Navigate between
+different home screen panels by swiping left and right.</p>
+<p>The Favorites Tray at the bottom always keeps your most important shortcuts and folders in view
+regardless of which panel is currently showing.</p>
+<p>Access the entire collection of apps and widgets by touching the All Apps button at the center of
+the Favorites Tray.</p>
+
+  </div>
+  <div class="layout-content-col span-4">
+
+    <img src="{@docRoot}design/media/ui_overview_all_apps.png">
+
+<h4>All apps screen</h4>
+<p>The All Apps screen lets you browse the entire set of apps and widgets that are installed on your
+device.</p>
+<p>Users can drag an app or widget icon from the All Apps screen and place it in any empty location on
+any Home screen.</p>
+
+  </div>
+  <div class="layout-content-col span-4">
+
+    <img src="{@docRoot}design/media/ui_overview_recents.png">
+
+<h4>Recents screen</h4>
+<p>Recents provides an efficient way of switching between recently used applications. It provides a
+clear navigation path between multiple ongoing tasks.</p>
+<p>The Recents button at the right side of the navigation bar displays the apps that the user has
+interacted with most recently. They are organized in reverse chronological order with the most
+recently used app at the bottom.</p>
+<p>Switch to an app by touching it. Remove an item by swiping left or right.</p>
+
+  </div>
+</div>
+
+<h2 id="system-bars">System Bars</h2>
+
+<p>The system bars are screen areas dedicated to the display of notifications, communication of device
+status, and device navigation. Typically the system bars are displayed concurrently with your app.
+Apps that display immersive content, such as movies or images, can temporarily hide the system bars
+to allow the user to enjoy full screen content without distraction.</p>
+
+<img src="{@docRoot}design/media/ui_overview_system_ui.png">
+
+<div class="with-callouts">
+
+<ol>
+<li>
+<h4>Status Bar</h4>
+<p>Displays pending notifications on the left and status, such as time, battery level, or signal
+  strength, on the right. Swipe down from the status bar to show notification details.</p>
+</li>
+<li>
+<h4>Navigation Bar</h4>
+<p>New for phones in Android 4.0, the navigation bar is present only on devices that don't have
+  the traditional hardware keys. It houses the device navigation controls Back, Home, and
+  Recents, and also displays a menu for apps written for Android 2.3 or earlier.</p>
+</li>
+<li>
+<h4>Combined Bar</h4>
+<p>On tablet form factors the status and navigation bars are combined into a single bar at the
+  bottom of the screen.</p>
+</li>
+</ol>
+
+</div>
+
+<h2 id="notifications">Notifications</h2>
+
+<p>Notifications are brief messages that users can access at any time from the status bar. They
+provide updates, reminders, or information that's important, but not critical enough to warrant
+interrupting the user. Open the notifications drawer by swiping down on the status bar. Touching a
+notification opens the associated app. <a href="{@docRoot}design/patterns/notifications.html">More on Notifications</a></p>
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-4">
+
+    <img src="{@docRoot}design/media/ui_overview_notifications.png">
+
+  </div>
+  <div class="layout-content-col span-9">
+
+    <img src="{@docRoot}design/media/notifications_dismiss.png">
+
+<p>Most notifications have a one-line title and a one-line message. The recommended layout for a
+notification includes two lines. If necessary, you can add a third line. Timestamps are optional.</p>
+<p>Swiping a notification right or left removes it from the notification drawer.</p>
+
+  </div>
+</div>
+
+
+<h2 id="app">Common App UI</h2>
+
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-7">
+
+    <img src="{@docRoot}design/media/ui_overview_app_ui.png">
+
+  </div>
+  <div class="layout-content-col span-6 with-callouts">
+
+<p>A typical Android app consists of action bars and the app content area.</p>
+<ol>
+<li>
+<h4>Main Action Bar</h4>
+<p>The command and control center for your app. The main action bar includes elements for
+  navigating your app's hierarchy and views, and also surfaces the most important actions.</p>
+<p><a href="{@docRoot}design/patterns/actionbar.html">More on the Action Bar</a></p>
+</li>
+<li>
+<h4>View Control</h4>
+<p>Allows users to switch between the different views that your app provides. Views typically
+  consist of different arrangements of your data or different functional aspects of your app.</p>
+</li>
+<li>
+<h4>Content Area</h4>
+<p>The space where the content of your app is displayed.</p>
+</li>
+<li>
+<h4>Split Action Bar</h4>
+<p>Split action bars provide a way to distribute actions across additional bars located below
+  the main action bar or at the bottom of the screen. In this example, a split action bar moves
+  important actions that won't fit in the main bar to the bottom.</p>
+</li>
+</ol>
+
+  </div>
+</div>
diff --git a/docs/html/design/index.html b/docs/html/design/index.html
deleted file mode 100644
index 8583aa4..0000000
--- a/docs/html/design/index.html
+++ /dev/null
@@ -1,168 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-  <head>
-    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
-    <title>
-
-Android Design - Welcome
-    </title>
-    <link rel="shortcut icon" type="image/x-icon" href="/favicon.ico">
-    <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Roboto:regular,medium,thin,italic,mediumitalic">
-    <link rel="stylesheet" href="static/yui-3.3.0-reset-min.css">
-    <link rel="stylesheet" href="static/default.css">
-
-<style>
-#landing-graphic-container {
-  position: relative;
-}
-
-#text-overlay {
-  position: absolute;
-  left: 10px;
-  top: 472px;
-  width: 280px;
-}
-</style>
-
-  </head>
-  <body>
-
-    <div id="page-container">
-
-      <div id="page-header"><a href="index.html">Android Design</a></div>
-
-      <div id="main-row">
-
-        <ul id="nav">
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="index.html">Get Started</a></div>
-            <ul>
-              <li><a href="get-started/creative-vision.html">Creative Vision</a></li>
-              <li><a href="get-started/principles.html">Design Principles</a></li>
-              <li><a href="get-started/ui-overview.html">UI Overview</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="style/index.html">Style</a></div>
-            <ul>
-              <li><a href="style/devices-displays.html">Devices and Displays</a></li>
-              <li><a href="style/themes.html">Themes</a></li>
-              <li><a href="style/touch-feedback.html">Touch Feedback</a></li>
-              <li><a href="style/metrics-grids.html">Metrics and Grids</a></li>
-              <li><a href="style/typography.html">Typography</a></li>
-              <li><a href="style/color.html">Color</a></li>
-              <li><a href="style/iconography.html">Iconography</a></li>
-              <li><a href="style/writing.html">Writing Style</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="patterns/index.html">Patterns</a></div>
-            <ul>
-              <li><a href="patterns/new-4-0.html">New in Android 4.0</a></li>
-              <li><a href="patterns/gestures.html">Gestures</a></li>
-              <li><a href="patterns/app-structure.html">App Structure</a></li>
-              <li><a href="patterns/navigation.html">Navigation</a></li>
-              <li><a href="patterns/actionbar.html">Action Bar</a></li>
-              <li><a href="patterns/multi-pane-layouts.html">Multi-pane Layouts</a></li>
-              <li><a href="patterns/swipe-views.html">Swipe Views</a></li>
-              <li><a href="patterns/selection.html">Selection</a></li>
-              <li><a href="patterns/notifications.html">Notifications</a></li>
-              <li><a href="patterns/compatibility.html">Compatibility</a></li>
-              <li><a href="patterns/pure-android.html">Pure Android</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="building-blocks/index.html">Building Blocks</a></div>
-            <ul>
-              <li><a href="building-blocks/tabs.html">Tabs</a></li>
-              <li><a href="building-blocks/lists.html">Lists</a></li>
-              <li><a href="building-blocks/grid-lists.html">Grid Lists</a></li>
-              <li><a href="building-blocks/scrolling.html">Scrolling</a></li>
-              <li><a href="building-blocks/spinners.html">Spinners</a></li>
-              <li><a href="building-blocks/buttons.html">Buttons</a></li>
-              <li><a href="building-blocks/text-fields.html">Text Fields</a></li>
-              <li><a href="building-blocks/seek-bars.html">Seek Bars</a></li>
-              <li><a href="building-blocks/progress.html">Progress &amp; Activity</a></li>
-              <li><a href="building-blocks/switches.html">Switches</a></li>
-              <li><a href="building-blocks/dialogs.html">Dialogs</a></li>
-              <li><a href="building-blocks/pickers.html">Pickers</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header empty"><a href="downloads/index.html">Downloads</a></div>
-          </li>
-
-          <li>
-            <div id="back-dac-section"><a href="../index.html">Developers</a></div>
-          </li>
-
-        </ul>
-
-        <div id="content">
-
-          
-
-
-          
-
-<div id="landing-graphic-container">
-  <div id="text-overlay">
-    Welcome to <strong>Android Design</strong>, your place for learning how to design exceptional Android apps.
-    <br><br>
-    <a href="get-started/creative-vision.html" class="landing-page-link">Creative Vision</a>
-  </div>
-
-  <a href="get-started/creative-vision.html">
-    <img src="static/content/index_landing_page.png">
-  </a>
-</div>
-
-
-
-          
-
-        </div>
-
-      </div>
-
-      <div id="page-footer">
-
-        <p id="copyright">
-          Except as noted, this content is licensed under
-          <a href="http://creativecommons.org/licenses/by/2.5/">
-          Creative Commons Attribution 2.5</a>.<br>
-          For details and restrictions, see the
-          <a href="http://developer.android.com/license.html">Content License</a>.
-        </p>
-
-        <p>
-          <a href="http://www.android.com/terms.html">Site Terms of Service</a> &ndash;
-          <a href="http://www.android.com/privacy.html">Privacy Policy</a> &ndash;
-          <a href="http://www.android.com/branding.html">Brand Guidelines</a>
-        </p>
-
-      </div>
-    </div>
-
-    <script src="static/jquery-1.6.2.min.js"></script>
-    <script>
-    var SITE_ROOT = '';
-    </script>
-    <script src="static/default.js"></script>
-
-
-    <script type="text/javascript">
-    var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
-    document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
-    </script>
-    <script type="text/javascript">
-    var pageTracker = _gat._getTracker("UA-5831155-1");
-    pageTracker._trackPageview();
-    </script>
-  </body>
-</html>
diff --git a/docs/html/design/index.jd b/docs/html/design/index.jd
new file mode 100644
index 0000000..d404aa6
--- /dev/null
+++ b/docs/html/design/index.jd
@@ -0,0 +1,29 @@
+page.title=
+header.hide=1
+footer.hide=1
+@jd:body
+
+<style>
+#landing-graphic-container {
+  position: relative;
+}
+
+#text-overlay {
+  position: absolute;
+  left: 10px;
+  top: 472px;
+  width: 280px;
+}
+</style>
+
+<div id="landing-graphic-container">
+  <div id="text-overlay">
+    Welcome to <strong>Android Design</strong>, your place for learning how to design exceptional Android apps.
+    <br><br>
+    <a href="{@docRoot}design/get-started/creative-vision.html" class="landing-page-link">Creative Vision</a>
+  </div>
+
+  <a href="{@docRoot}design/get-started/creative-vision.html">
+    <img src="{@docRoot}design/media/index_landing_page.png">
+  </a>
+</div>
diff --git a/docs/html/design/static/content/action_bar_basics.png b/docs/html/design/media/action_bar_basics.png
similarity index 100%
rename from docs/html/design/static/content/action_bar_basics.png
rename to docs/html/design/media/action_bar_basics.png
Binary files differ
diff --git a/docs/html/design/static/content/action_bar_cab.png b/docs/html/design/media/action_bar_cab.png
similarity index 100%
rename from docs/html/design/static/content/action_bar_cab.png
rename to docs/html/design/media/action_bar_cab.png
Binary files differ
diff --git a/docs/html/design/static/content/action_bar_pattern_action_icons.png b/docs/html/design/media/action_bar_pattern_action_icons.png
similarity index 100%
rename from docs/html/design/static/content/action_bar_pattern_action_icons.png
rename to docs/html/design/media/action_bar_pattern_action_icons.png
Binary files differ
diff --git a/docs/html/design/static/content/action_bar_pattern_considerations.png b/docs/html/design/media/action_bar_pattern_considerations.png
similarity index 100%
rename from docs/html/design/static/content/action_bar_pattern_considerations.png
rename to docs/html/design/media/action_bar_pattern_considerations.png
Binary files differ
diff --git a/docs/html/design/static/content/action_bar_pattern_default_tabs.png b/docs/html/design/media/action_bar_pattern_default_tabs.png
similarity index 100%
rename from docs/html/design/static/content/action_bar_pattern_default_tabs.png
rename to docs/html/design/media/action_bar_pattern_default_tabs.png
Binary files differ
diff --git a/docs/html/design/static/content/action_bar_pattern_overflow.png b/docs/html/design/media/action_bar_pattern_overflow.png
similarity index 100%
rename from docs/html/design/static/content/action_bar_pattern_overflow.png
rename to docs/html/design/media/action_bar_pattern_overflow.png
Binary files differ
diff --git a/docs/html/design/static/content/action_bar_pattern_overview.png b/docs/html/design/media/action_bar_pattern_overview.png
similarity index 100%
rename from docs/html/design/static/content/action_bar_pattern_overview.png
rename to docs/html/design/media/action_bar_pattern_overview.png
Binary files differ
diff --git a/docs/html/design/static/content/action_bar_pattern_rotation.png b/docs/html/design/media/action_bar_pattern_rotation.png
similarity index 100%
rename from docs/html/design/static/content/action_bar_pattern_rotation.png
rename to docs/html/design/media/action_bar_pattern_rotation.png
Binary files differ
diff --git a/docs/html/design/static/content/action_bar_pattern_share_pack.png b/docs/html/design/media/action_bar_pattern_share_pack.png
similarity index 100%
rename from docs/html/design/static/content/action_bar_pattern_share_pack.png
rename to docs/html/design/media/action_bar_pattern_share_pack.png
Binary files differ
diff --git a/docs/html/design/static/content/action_bar_pattern_spinner.png b/docs/html/design/media/action_bar_pattern_spinner.png
similarity index 100%
rename from docs/html/design/static/content/action_bar_pattern_spinner.png
rename to docs/html/design/media/action_bar_pattern_spinner.png
Binary files differ
diff --git a/docs/html/design/static/content/action_bar_pattern_table.png b/docs/html/design/media/action_bar_pattern_table.png
similarity index 100%
rename from docs/html/design/static/content/action_bar_pattern_table.png
rename to docs/html/design/media/action_bar_pattern_table.png
Binary files differ
diff --git a/docs/html/design/static/content/action_bar_pattern_up_app_icon.png b/docs/html/design/media/action_bar_pattern_up_app_icon.png
similarity index 100%
rename from docs/html/design/static/content/action_bar_pattern_up_app_icon.png
rename to docs/html/design/media/action_bar_pattern_up_app_icon.png
Binary files differ
diff --git a/docs/html/design/static/content/app_structure_book_detail_page_flip.png b/docs/html/design/media/app_structure_book_detail_page_flip.png
similarity index 100%
rename from docs/html/design/static/content/app_structure_book_detail_page_flip.png
rename to docs/html/design/media/app_structure_book_detail_page_flip.png
Binary files differ
diff --git a/docs/html/design/static/content/app_structure_fixedtabs.png b/docs/html/design/media/app_structure_fixedtabs.png
similarity index 100%
rename from docs/html/design/static/content/app_structure_fixedtabs.png
rename to docs/html/design/media/app_structure_fixedtabs.png
Binary files differ
diff --git a/docs/html/design/static/content/app_structure_gallery_filmstrip.png b/docs/html/design/media/app_structure_gallery_filmstrip.png
similarity index 100%
rename from docs/html/design/static/content/app_structure_gallery_filmstrip.png
rename to docs/html/design/media/app_structure_gallery_filmstrip.png
Binary files differ
diff --git a/docs/html/design/static/content/app_structure_gmail.png b/docs/html/design/media/app_structure_gmail.png
similarity index 100%
rename from docs/html/design/static/content/app_structure_gmail.png
rename to docs/html/design/media/app_structure_gmail.png
Binary files differ
diff --git a/docs/html/design/static/content/app_structure_gmail_swipe.png b/docs/html/design/media/app_structure_gmail_swipe.png
similarity index 100%
rename from docs/html/design/static/content/app_structure_gmail_swipe.png
rename to docs/html/design/media/app_structure_gmail_swipe.png
Binary files differ
diff --git a/docs/html/design/static/content/app_structure_market.png b/docs/html/design/media/app_structure_market.png
similarity index 100%
rename from docs/html/design/static/content/app_structure_market.png
rename to docs/html/design/media/app_structure_market.png
Binary files differ
diff --git a/docs/html/design/static/content/app_structure_music_lndscp.png b/docs/html/design/media/app_structure_music_lndscp.png
similarity index 100%
rename from docs/html/design/static/content/app_structure_music_lndscp.png
rename to docs/html/design/media/app_structure_music_lndscp.png
Binary files differ
diff --git a/docs/html/design/static/content/app_structure_overview.png b/docs/html/design/media/app_structure_overview.png
similarity index 100%
rename from docs/html/design/static/content/app_structure_overview.png
rename to docs/html/design/media/app_structure_overview.png
Binary files differ
diff --git a/docs/html/design/static/content/app_structure_people_detail.png b/docs/html/design/media/app_structure_people_detail.png
similarity index 100%
rename from docs/html/design/static/content/app_structure_people_detail.png
rename to docs/html/design/media/app_structure_people_detail.png
Binary files differ
diff --git a/docs/html/design/static/content/app_structure_scrolltabs.png b/docs/html/design/media/app_structure_scrolltabs.png
similarity index 100%
rename from docs/html/design/static/content/app_structure_scrolltabs.png
rename to docs/html/design/media/app_structure_scrolltabs.png
Binary files differ
diff --git a/docs/html/design/static/content/app_structure_shortcut_on_item.png b/docs/html/design/media/app_structure_shortcut_on_item.png
similarity index 100%
rename from docs/html/design/static/content/app_structure_shortcut_on_item.png
rename to docs/html/design/media/app_structure_shortcut_on_item.png
Binary files differ
diff --git a/docs/html/design/static/content/building_blocks_landing.png b/docs/html/design/media/building_blocks_landing.png
similarity index 100%
rename from docs/html/design/static/content/building_blocks_landing.png
rename to docs/html/design/media/building_blocks_landing.png
Binary files differ
diff --git a/docs/html/design/static/content/buttons_basic.png b/docs/html/design/media/buttons_basic.png
similarity index 100%
rename from docs/html/design/static/content/buttons_basic.png
rename to docs/html/design/media/buttons_basic.png
Binary files differ
diff --git a/docs/html/design/static/content/buttons_borderless.png b/docs/html/design/media/buttons_borderless.png
similarity index 100%
rename from docs/html/design/static/content/buttons_borderless.png
rename to docs/html/design/media/buttons_borderless.png
Binary files differ
diff --git a/docs/html/design/static/content/buttons_default_small.png b/docs/html/design/media/buttons_default_small.png
similarity index 100%
rename from docs/html/design/static/content/buttons_default_small.png
rename to docs/html/design/media/buttons_default_small.png
Binary files differ
diff --git a/docs/html/design/static/content/color_spectrum.png b/docs/html/design/media/color_spectrum.png
similarity index 100%
rename from docs/html/design/static/content/color_spectrum.png
rename to docs/html/design/media/color_spectrum.png
Binary files differ
diff --git a/docs/html/design/static/content/compatibility_legacy_apps.png b/docs/html/design/media/compatibility_legacy_apps.png
similarity index 100%
rename from docs/html/design/static/content/compatibility_legacy_apps.png
rename to docs/html/design/media/compatibility_legacy_apps.png
Binary files differ
diff --git a/docs/html/design/static/content/compatibility_physical_buttons.png b/docs/html/design/media/compatibility_physical_buttons.png
similarity index 100%
rename from docs/html/design/static/content/compatibility_physical_buttons.png
rename to docs/html/design/media/compatibility_physical_buttons.png
Binary files differ
diff --git a/docs/html/design/static/content/compatibility_virtual_nav.png b/docs/html/design/media/compatibility_virtual_nav.png
similarity index 100%
rename from docs/html/design/static/content/compatibility_virtual_nav.png
rename to docs/html/design/media/compatibility_virtual_nav.png
Binary files differ
diff --git a/docs/html/design/static/content/creative_vision_main.png b/docs/html/design/media/creative_vision_main.png
similarity index 100%
rename from docs/html/design/static/content/creative_vision_main.png
rename to docs/html/design/media/creative_vision_main.png
Binary files differ
diff --git a/docs/html/design/static/content/design_elements_landing.png b/docs/html/design/media/design_elements_landing.png
similarity index 100%
rename from docs/html/design/static/content/design_elements_landing.png
rename to docs/html/design/media/design_elements_landing.png
Binary files differ
diff --git a/docs/html/design/static/content/devices_displays_density.png b/docs/html/design/media/devices_displays_density.png
similarity index 100%
rename from docs/html/design/static/content/devices_displays_density.png
rename to docs/html/design/media/devices_displays_density.png
Binary files differ
diff --git a/docs/html/design/static/content/devices_displays_main.png b/docs/html/design/media/devices_displays_main.png
similarity index 100%
rename from docs/html/design/static/content/devices_displays_main.png
rename to docs/html/design/media/devices_displays_main.png
Binary files differ
diff --git a/docs/html/design/static/content/dialogs_examples.png b/docs/html/design/media/dialogs_examples.png
similarity index 100%
rename from docs/html/design/static/content/dialogs_examples.png
rename to docs/html/design/media/dialogs_examples.png
Binary files differ
diff --git a/docs/html/design/static/content/dialogs_main.png b/docs/html/design/media/dialogs_main.png
similarity index 100%
rename from docs/html/design/static/content/dialogs_main.png
rename to docs/html/design/media/dialogs_main.png
Binary files differ
diff --git a/docs/html/design/static/content/dialogs_popups_example.png b/docs/html/design/media/dialogs_popups_example.png
similarity index 100%
rename from docs/html/design/static/content/dialogs_popups_example.png
rename to docs/html/design/media/dialogs_popups_example.png
Binary files differ
diff --git a/docs/html/design/static/content/dialogs_toasts.png b/docs/html/design/media/dialogs_toasts.png
similarity index 100%
rename from docs/html/design/static/content/dialogs_toasts.png
rename to docs/html/design/media/dialogs_toasts.png
Binary files differ
diff --git a/docs/html/design/static/content/dialogs_w_no_title.png b/docs/html/design/media/dialogs_w_no_title.png
similarity index 100%
rename from docs/html/design/static/content/dialogs_w_no_title.png
rename to docs/html/design/media/dialogs_w_no_title.png
Binary files differ
diff --git a/docs/html/design/static/content/dialogs_w_title.png b/docs/html/design/media/dialogs_w_title.png
similarity index 100%
rename from docs/html/design/static/content/dialogs_w_title.png
rename to docs/html/design/media/dialogs_w_title.png
Binary files differ
diff --git a/docs/html/design/static/content/downloads_color_swatches.png b/docs/html/design/media/downloads_color_swatches.png
similarity index 100%
rename from docs/html/design/static/content/downloads_color_swatches.png
rename to docs/html/design/media/downloads_color_swatches.png
Binary files differ
diff --git a/docs/html/design/static/content/downloads_roboto_specimen_preview.png b/docs/html/design/media/downloads_roboto_specimen_preview.png
similarity index 100%
rename from docs/html/design/static/content/downloads_roboto_specimen_preview.png
rename to docs/html/design/media/downloads_roboto_specimen_preview.png
Binary files differ
diff --git a/docs/html/design/static/content/downloads_stencils.png b/docs/html/design/media/downloads_stencils.png
similarity index 100%
rename from docs/html/design/static/content/downloads_stencils.png
rename to docs/html/design/media/downloads_stencils.png
Binary files differ
diff --git a/docs/html/design/static/content/gesture_doubletouch.png b/docs/html/design/media/gesture_doubletouch.png
similarity index 100%
rename from docs/html/design/static/content/gesture_doubletouch.png
rename to docs/html/design/media/gesture_doubletouch.png
Binary files differ
diff --git a/docs/html/design/static/content/gesture_drag.png b/docs/html/design/media/gesture_drag.png
similarity index 100%
rename from docs/html/design/static/content/gesture_drag.png
rename to docs/html/design/media/gesture_drag.png
Binary files differ
diff --git a/docs/html/design/static/content/gesture_longtouch.png b/docs/html/design/media/gesture_longtouch.png
similarity index 100%
rename from docs/html/design/static/content/gesture_longtouch.png
rename to docs/html/design/media/gesture_longtouch.png
Binary files differ
diff --git a/docs/html/design/static/content/gesture_pinchclose.png b/docs/html/design/media/gesture_pinchclose.png
similarity index 100%
rename from docs/html/design/static/content/gesture_pinchclose.png
rename to docs/html/design/media/gesture_pinchclose.png
Binary files differ
diff --git a/docs/html/design/static/content/gesture_pinchopen.png b/docs/html/design/media/gesture_pinchopen.png
similarity index 100%
rename from docs/html/design/static/content/gesture_pinchopen.png
rename to docs/html/design/media/gesture_pinchopen.png
Binary files differ
diff --git a/docs/html/design/static/content/gesture_swipe.png b/docs/html/design/media/gesture_swipe.png
similarity index 100%
rename from docs/html/design/static/content/gesture_swipe.png
rename to docs/html/design/media/gesture_swipe.png
Binary files differ
diff --git a/docs/html/design/static/content/gesture_touch.png b/docs/html/design/media/gesture_touch.png
similarity index 100%
rename from docs/html/design/static/content/gesture_touch.png
rename to docs/html/design/media/gesture_touch.png
Binary files differ
diff --git a/docs/html/design/static/content/gridview_example.png b/docs/html/design/media/gridview_example.png
similarity index 100%
rename from docs/html/design/static/content/gridview_example.png
rename to docs/html/design/media/gridview_example.png
Binary files differ
diff --git a/docs/html/design/static/content/gridview_horizontal.png b/docs/html/design/media/gridview_horizontal.png
similarity index 100%
rename from docs/html/design/static/content/gridview_horizontal.png
rename to docs/html/design/media/gridview_horizontal.png
Binary files differ
diff --git a/docs/html/design/static/content/gridview_overview.png b/docs/html/design/media/gridview_overview.png
similarity index 100%
rename from docs/html/design/static/content/gridview_overview.png
rename to docs/html/design/media/gridview_overview.png
Binary files differ
diff --git a/docs/html/design/static/content/gridview_style.png b/docs/html/design/media/gridview_style.png
similarity index 100%
rename from docs/html/design/static/content/gridview_style.png
rename to docs/html/design/media/gridview_style.png
Binary files differ
diff --git a/docs/html/design/static/content/gridview_vertical.png b/docs/html/design/media/gridview_vertical.png
similarity index 100%
rename from docs/html/design/static/content/gridview_vertical.png
rename to docs/html/design/media/gridview_vertical.png
Binary files differ
diff --git a/docs/html/design/static/content/iconography_actionbar_colors.png b/docs/html/design/media/iconography_actionbar_colors.png
similarity index 100%
rename from docs/html/design/static/content/iconography_actionbar_colors.png
rename to docs/html/design/media/iconography_actionbar_colors.png
Binary files differ
diff --git a/docs/html/design/static/content/iconography_actionbar_focal.png b/docs/html/design/media/iconography_actionbar_focal.png
similarity index 100%
rename from docs/html/design/static/content/iconography_actionbar_focal.png
rename to docs/html/design/media/iconography_actionbar_focal.png
Binary files differ
diff --git a/docs/html/design/static/content/iconography_actionbar_size.png b/docs/html/design/media/iconography_actionbar_size.png
similarity index 100%
rename from docs/html/design/static/content/iconography_actionbar_size.png
rename to docs/html/design/media/iconography_actionbar_size.png
Binary files differ
diff --git a/docs/html/design/static/content/iconography_actionbar_style.png b/docs/html/design/media/iconography_actionbar_style.png
similarity index 100%
rename from docs/html/design/static/content/iconography_actionbar_style.png
rename to docs/html/design/media/iconography_actionbar_style.png
Binary files differ
diff --git a/docs/html/design/static/content/iconography_launcher_example.png b/docs/html/design/media/iconography_launcher_example.png
similarity index 100%
rename from docs/html/design/static/content/iconography_launcher_example.png
rename to docs/html/design/media/iconography_launcher_example.png
Binary files differ
diff --git a/docs/html/design/static/content/iconography_launcher_example2.png b/docs/html/design/media/iconography_launcher_example2.png
similarity index 100%
rename from docs/html/design/static/content/iconography_launcher_example2.png
rename to docs/html/design/media/iconography_launcher_example2.png
Binary files differ
diff --git a/docs/html/design/static/content/iconography_launcher_focal.png b/docs/html/design/media/iconography_launcher_focal.png
similarity index 100%
rename from docs/html/design/static/content/iconography_launcher_focal.png
rename to docs/html/design/media/iconography_launcher_focal.png
Binary files differ
diff --git a/docs/html/design/static/content/iconography_launcher_size.png b/docs/html/design/media/iconography_launcher_size.png
similarity index 100%
rename from docs/html/design/static/content/iconography_launcher_size.png
rename to docs/html/design/media/iconography_launcher_size.png
Binary files differ
diff --git a/docs/html/design/static/content/iconography_launcher_style.png b/docs/html/design/media/iconography_launcher_style.png
similarity index 100%
rename from docs/html/design/static/content/iconography_launcher_style.png
rename to docs/html/design/media/iconography_launcher_style.png
Binary files differ
diff --git a/docs/html/design/static/content/iconography_notification_example.png b/docs/html/design/media/iconography_notification_example.png
similarity index 100%
rename from docs/html/design/static/content/iconography_notification_example.png
rename to docs/html/design/media/iconography_notification_example.png
Binary files differ
diff --git a/docs/html/design/static/content/iconography_notification_focal.png b/docs/html/design/media/iconography_notification_focal.png
similarity index 100%
rename from docs/html/design/static/content/iconography_notification_focal.png
rename to docs/html/design/media/iconography_notification_focal.png
Binary files differ
diff --git a/docs/html/design/static/content/iconography_notification_size.png b/docs/html/design/media/iconography_notification_size.png
similarity index 100%
rename from docs/html/design/static/content/iconography_notification_size.png
rename to docs/html/design/media/iconography_notification_size.png
Binary files differ
diff --git a/docs/html/design/static/content/iconography_notification_style.png b/docs/html/design/media/iconography_notification_style.png
similarity index 100%
rename from docs/html/design/static/content/iconography_notification_style.png
rename to docs/html/design/media/iconography_notification_style.png
Binary files differ
diff --git a/docs/html/design/static/content/iconography_overview.png b/docs/html/design/media/iconography_overview.png
similarity index 100%
rename from docs/html/design/static/content/iconography_overview.png
rename to docs/html/design/media/iconography_overview.png
Binary files differ
diff --git a/docs/html/design/static/content/iconography_small_colors.png b/docs/html/design/media/iconography_small_colors.png
similarity index 100%
rename from docs/html/design/static/content/iconography_small_colors.png
rename to docs/html/design/media/iconography_small_colors.png
Binary files differ
diff --git a/docs/html/design/static/content/iconography_small_example.png b/docs/html/design/media/iconography_small_example.png
similarity index 100%
rename from docs/html/design/static/content/iconography_small_example.png
rename to docs/html/design/media/iconography_small_example.png
Binary files differ
diff --git a/docs/html/design/static/content/iconography_small_focal.png b/docs/html/design/media/iconography_small_focal.png
similarity index 100%
rename from docs/html/design/static/content/iconography_small_focal.png
rename to docs/html/design/media/iconography_small_focal.png
Binary files differ
diff --git a/docs/html/design/static/content/iconography_small_size.png b/docs/html/design/media/iconography_small_size.png
similarity index 100%
rename from docs/html/design/static/content/iconography_small_size.png
rename to docs/html/design/media/iconography_small_size.png
Binary files differ
diff --git a/docs/html/design/static/content/iconography_small_style.png b/docs/html/design/media/iconography_small_style.png
similarity index 100%
rename from docs/html/design/static/content/iconography_small_style.png
rename to docs/html/design/media/iconography_small_style.png
Binary files differ
diff --git a/docs/html/design/static/content/index_landing_page.png b/docs/html/design/media/index_landing_page.png
similarity index 100%
rename from docs/html/design/static/content/index_landing_page.png
rename to docs/html/design/media/index_landing_page.png
Binary files differ
diff --git a/docs/html/design/static/content/lists_main.png b/docs/html/design/media/lists_main.png
similarity index 100%
rename from docs/html/design/static/content/lists_main.png
rename to docs/html/design/media/lists_main.png
Binary files differ
diff --git a/docs/html/design/static/content/metrics_48.png b/docs/html/design/media/metrics_48.png
similarity index 100%
rename from docs/html/design/static/content/metrics_48.png
rename to docs/html/design/media/metrics_48.png
Binary files differ
diff --git a/docs/html/design/static/content/metrics_closeup.png b/docs/html/design/media/metrics_closeup.png
similarity index 100%
rename from docs/html/design/static/content/metrics_closeup.png
rename to docs/html/design/media/metrics_closeup.png
Binary files differ
diff --git a/docs/html/design/static/content/metrics_diagram.png b/docs/html/design/media/metrics_diagram.png
similarity index 100%
rename from docs/html/design/static/content/metrics_diagram.png
rename to docs/html/design/media/metrics_diagram.png
Binary files differ
diff --git a/docs/html/design/static/content/metrics_forms.png b/docs/html/design/media/metrics_forms.png
similarity index 100%
rename from docs/html/design/static/content/metrics_forms.png
rename to docs/html/design/media/metrics_forms.png
Binary files differ
diff --git a/docs/html/design/static/content/migrating_icons.png b/docs/html/design/media/migrating_icons.png
similarity index 100%
rename from docs/html/design/static/content/migrating_icons.png
rename to docs/html/design/media/migrating_icons.png
Binary files differ
diff --git a/docs/html/design/static/content/migrating_ios_dialers.png b/docs/html/design/media/migrating_ios_dialers.png
similarity index 100%
rename from docs/html/design/static/content/migrating_ios_dialers.png
rename to docs/html/design/media/migrating_ios_dialers.png
Binary files differ
diff --git a/docs/html/design/static/content/migrating_ios_galleries.png b/docs/html/design/media/migrating_ios_galleries.png
similarity index 100%
rename from docs/html/design/static/content/migrating_ios_galleries.png
rename to docs/html/design/media/migrating_ios_galleries.png
Binary files differ
diff --git a/docs/html/design/static/content/migrating_ios_settings.png b/docs/html/design/media/migrating_ios_settings.png
similarity index 100%
rename from docs/html/design/static/content/migrating_ios_settings.png
rename to docs/html/design/media/migrating_ios_settings.png
Binary files differ
diff --git a/docs/html/design/static/content/migrating_ui_elements.png b/docs/html/design/media/migrating_ui_elements.png
similarity index 100%
rename from docs/html/design/static/content/migrating_ui_elements.png
rename to docs/html/design/media/migrating_ui_elements.png
Binary files differ
diff --git a/docs/html/design/static/content/misc_full_galaxynexus_blank_land_span13.png b/docs/html/design/media/misc_full_galaxynexus_blank_land_span13.png
similarity index 100%
rename from docs/html/design/static/content/misc_full_galaxynexus_blank_land_span13.png
rename to docs/html/design/media/misc_full_galaxynexus_blank_land_span13.png
Binary files differ
diff --git a/docs/html/design/static/content/misc_full_galaxynexus_blank_port_span5.png b/docs/html/design/media/misc_full_galaxynexus_blank_port_span5.png
similarity index 100%
rename from docs/html/design/static/content/misc_full_galaxynexus_blank_port_span5.png
rename to docs/html/design/media/misc_full_galaxynexus_blank_port_span5.png
Binary files differ
diff --git a/docs/html/design/static/content/misc_full_galaxynexus_blank_port_span9.png b/docs/html/design/media/misc_full_galaxynexus_blank_port_span9.png
similarity index 100%
rename from docs/html/design/static/content/misc_full_galaxynexus_blank_port_span9.png
rename to docs/html/design/media/misc_full_galaxynexus_blank_port_span9.png
Binary files differ
diff --git a/docs/html/design/static/content/multipane_expand.png b/docs/html/design/media/multipane_expand.png
similarity index 100%
rename from docs/html/design/static/content/multipane_expand.png
rename to docs/html/design/media/multipane_expand.png
Binary files differ
diff --git a/docs/html/design/static/content/multipane_show.png b/docs/html/design/media/multipane_show.png
similarity index 100%
rename from docs/html/design/static/content/multipane_show.png
rename to docs/html/design/media/multipane_show.png
Binary files differ
diff --git a/docs/html/design/static/content/multipane_stack.png b/docs/html/design/media/multipane_stack.png
similarity index 100%
rename from docs/html/design/static/content/multipane_stack.png
rename to docs/html/design/media/multipane_stack.png
Binary files differ
diff --git a/docs/html/design/static/content/multipane_stretch.png b/docs/html/design/media/multipane_stretch.png
similarity index 100%
rename from docs/html/design/static/content/multipane_stretch.png
rename to docs/html/design/media/multipane_stretch.png
Binary files differ
diff --git a/docs/html/design/static/content/multipane_view_tablet.png b/docs/html/design/media/multipane_view_tablet.png
similarity index 100%
rename from docs/html/design/static/content/multipane_view_tablet.png
rename to docs/html/design/media/multipane_view_tablet.png
Binary files differ
diff --git a/docs/html/design/static/content/multipane_views.png b/docs/html/design/media/multipane_views.png
similarity index 100%
rename from docs/html/design/static/content/multipane_views.png
rename to docs/html/design/media/multipane_views.png
Binary files differ
diff --git a/docs/html/design/static/content/navigation_between_siblings_gmail.png b/docs/html/design/media/navigation_between_siblings_gmail.png
similarity index 100%
rename from docs/html/design/static/content/navigation_between_siblings_gmail.png
rename to docs/html/design/media/navigation_between_siblings_gmail.png
Binary files differ
diff --git a/docs/html/design/static/content/navigation_between_siblings_market1.png b/docs/html/design/media/navigation_between_siblings_market1.png
similarity index 100%
rename from docs/html/design/static/content/navigation_between_siblings_market1.png
rename to docs/html/design/media/navigation_between_siblings_market1.png
Binary files differ
diff --git a/docs/html/design/static/content/navigation_between_siblings_market2.png b/docs/html/design/media/navigation_between_siblings_market2.png
similarity index 100%
rename from docs/html/design/static/content/navigation_between_siblings_market2.png
rename to docs/html/design/media/navigation_between_siblings_market2.png
Binary files differ
diff --git a/docs/html/design/static/content/navigation_from_outside_back.png b/docs/html/design/media/navigation_from_outside_back.png
similarity index 100%
rename from docs/html/design/static/content/navigation_from_outside_back.png
rename to docs/html/design/media/navigation_from_outside_back.png
Binary files differ
diff --git a/docs/html/design/static/content/navigation_from_outside_up.png b/docs/html/design/media/navigation_from_outside_up.png
similarity index 100%
rename from docs/html/design/static/content/navigation_from_outside_up.png
rename to docs/html/design/media/navigation_from_outside_up.png
Binary files differ
diff --git a/docs/html/design/static/content/navigation_up_vs_back_gmail.png b/docs/html/design/media/navigation_up_vs_back_gmail.png
similarity index 100%
rename from docs/html/design/static/content/navigation_up_vs_back_gmail.png
rename to docs/html/design/media/navigation_up_vs_back_gmail.png
Binary files differ
diff --git a/docs/html/design/static/content/navigation_with_back_and_up.png b/docs/html/design/media/navigation_with_back_and_up.png
similarity index 100%
rename from docs/html/design/static/content/navigation_with_back_and_up.png
rename to docs/html/design/media/navigation_with_back_and_up.png
Binary files differ
diff --git a/docs/html/design/static/content/notifications_dismiss.png b/docs/html/design/media/notifications_dismiss.png
similarity index 100%
rename from docs/html/design/static/content/notifications_dismiss.png
rename to docs/html/design/media/notifications_dismiss.png
Binary files differ
diff --git a/docs/html/design/static/content/notifications_pattern_additional_fail.png b/docs/html/design/media/notifications_pattern_additional_fail.png
similarity index 100%
rename from docs/html/design/static/content/notifications_pattern_additional_fail.png
rename to docs/html/design/media/notifications_pattern_additional_fail.png
Binary files differ
diff --git a/docs/html/design/static/content/notifications_pattern_additional_win.png b/docs/html/design/media/notifications_pattern_additional_win.png
similarity index 100%
rename from docs/html/design/static/content/notifications_pattern_additional_win.png
rename to docs/html/design/media/notifications_pattern_additional_win.png
Binary files differ
diff --git a/docs/html/design/static/content/notifications_pattern_anatomy.png b/docs/html/design/media/notifications_pattern_anatomy.png
similarity index 100%
rename from docs/html/design/static/content/notifications_pattern_anatomy.png
rename to docs/html/design/media/notifications_pattern_anatomy.png
Binary files differ
diff --git a/docs/html/design/static/content/notifications_pattern_dialog_toast.png b/docs/html/design/media/notifications_pattern_dialog_toast.png
similarity index 100%
rename from docs/html/design/static/content/notifications_pattern_dialog_toast.png
rename to docs/html/design/media/notifications_pattern_dialog_toast.png
Binary files differ
diff --git a/docs/html/design/static/content/notifications_pattern_ongoing_music.png b/docs/html/design/media/notifications_pattern_ongoing_music.png
similarity index 100%
rename from docs/html/design/static/content/notifications_pattern_ongoing_music.png
rename to docs/html/design/media/notifications_pattern_ongoing_music.png
Binary files differ
diff --git a/docs/html/design/static/content/notifications_pattern_phone_icons.png b/docs/html/design/media/notifications_pattern_phone_icons.png
similarity index 100%
rename from docs/html/design/static/content/notifications_pattern_phone_icons.png
rename to docs/html/design/media/notifications_pattern_phone_icons.png
Binary files differ
diff --git a/docs/html/design/static/content/notifications_pattern_phone_ticker.png b/docs/html/design/media/notifications_pattern_phone_ticker.png
similarity index 100%
rename from docs/html/design/static/content/notifications_pattern_phone_ticker.png
rename to docs/html/design/media/notifications_pattern_phone_ticker.png
Binary files differ
diff --git a/docs/html/design/static/content/notifications_pattern_real_time_people.png b/docs/html/design/media/notifications_pattern_real_time_people.png
similarity index 100%
rename from docs/html/design/static/content/notifications_pattern_real_time_people.png
rename to docs/html/design/media/notifications_pattern_real_time_people.png
Binary files differ
diff --git a/docs/html/design/static/content/notifications_pattern_social_fail.png b/docs/html/design/media/notifications_pattern_social_fail.png
similarity index 100%
rename from docs/html/design/static/content/notifications_pattern_social_fail.png
rename to docs/html/design/media/notifications_pattern_social_fail.png
Binary files differ
diff --git a/docs/html/design/static/content/notifications_pattern_tablet.png b/docs/html/design/media/notifications_pattern_tablet.png
similarity index 100%
rename from docs/html/design/static/content/notifications_pattern_tablet.png
rename to docs/html/design/media/notifications_pattern_tablet.png
Binary files differ
diff --git a/docs/html/design/static/content/patterns_landing.png b/docs/html/design/media/patterns_landing.png
similarity index 100%
rename from docs/html/design/static/content/patterns_landing.png
rename to docs/html/design/media/patterns_landing.png
Binary files differ
diff --git a/docs/html/design/static/content/picker_datetime.png b/docs/html/design/media/picker_datetime.png
similarity index 100%
rename from docs/html/design/static/content/picker_datetime.png
rename to docs/html/design/media/picker_datetime.png
Binary files differ
diff --git a/docs/html/design/static/content/picker_space.png b/docs/html/design/media/picker_space.png
similarity index 100%
rename from docs/html/design/static/content/picker_space.png
rename to docs/html/design/media/picker_space.png
Binary files differ
diff --git a/docs/html/design/static/content/principles_decide_for_me.png b/docs/html/design/media/principles_decide_for_me.png
similarity index 100%
rename from docs/html/design/static/content/principles_decide_for_me.png
rename to docs/html/design/media/principles_decide_for_me.png
Binary files differ
diff --git a/docs/html/design/static/content/principles_delight.png b/docs/html/design/media/principles_delight.png
similarity index 100%
rename from docs/html/design/static/content/principles_delight.png
rename to docs/html/design/media/principles_delight.png
Binary files differ
diff --git a/docs/html/design/static/content/principles_error.png b/docs/html/design/media/principles_error.png
similarity index 100%
rename from docs/html/design/static/content/principles_error.png
rename to docs/html/design/media/principles_error.png
Binary files differ
diff --git a/docs/html/design/static/content/principles_get_to_know_me.png b/docs/html/design/media/principles_get_to_know_me.png
similarity index 100%
rename from docs/html/design/static/content/principles_get_to_know_me.png
rename to docs/html/design/media/principles_get_to_know_me.png
Binary files differ
diff --git a/docs/html/design/static/content/principles_heavy_lifting.png b/docs/html/design/media/principles_heavy_lifting.png
similarity index 100%
rename from docs/html/design/static/content/principles_heavy_lifting.png
rename to docs/html/design/media/principles_heavy_lifting.png
Binary files differ
diff --git a/docs/html/design/static/content/principles_important_interruption.png b/docs/html/design/media/principles_important_interruption.png
similarity index 100%
rename from docs/html/design/static/content/principles_important_interruption.png
rename to docs/html/design/media/principles_important_interruption.png
Binary files differ
diff --git a/docs/html/design/static/content/principles_information_when_need_it.png b/docs/html/design/media/principles_information_when_need_it.png
similarity index 100%
rename from docs/html/design/static/content/principles_information_when_need_it.png
rename to docs/html/design/media/principles_information_when_need_it.png
Binary files differ
diff --git a/docs/html/design/static/content/principles_keep_it_brief.png b/docs/html/design/media/principles_keep_it_brief.png
similarity index 100%
rename from docs/html/design/static/content/principles_keep_it_brief.png
rename to docs/html/design/media/principles_keep_it_brief.png
Binary files differ
diff --git a/docs/html/design/static/content/principles_looks_same.png b/docs/html/design/media/principles_looks_same.png
similarity index 100%
rename from docs/html/design/static/content/principles_looks_same.png
rename to docs/html/design/media/principles_looks_same.png
Binary files differ
diff --git a/docs/html/design/static/content/principles_make_important_fast.png b/docs/html/design/media/principles_make_important_fast.png
similarity index 100%
rename from docs/html/design/static/content/principles_make_important_fast.png
rename to docs/html/design/media/principles_make_important_fast.png
Binary files differ
diff --git a/docs/html/design/static/content/principles_make_it_mine.png b/docs/html/design/media/principles_make_it_mine.png
similarity index 100%
rename from docs/html/design/static/content/principles_make_it_mine.png
rename to docs/html/design/media/principles_make_it_mine.png
Binary files differ
diff --git a/docs/html/design/static/content/principles_navigation.png b/docs/html/design/media/principles_navigation.png
similarity index 100%
rename from docs/html/design/static/content/principles_navigation.png
rename to docs/html/design/media/principles_navigation.png
Binary files differ
diff --git a/docs/html/design/static/content/principles_never_lose_stuff.png b/docs/html/design/media/principles_never_lose_stuff.png
similarity index 100%
rename from docs/html/design/static/content/principles_never_lose_stuff.png
rename to docs/html/design/media/principles_never_lose_stuff.png
Binary files differ
diff --git a/docs/html/design/static/content/principles_pictures.png b/docs/html/design/media/principles_pictures.png
similarity index 100%
rename from docs/html/design/static/content/principles_pictures.png
rename to docs/html/design/media/principles_pictures.png
Binary files differ
diff --git a/docs/html/design/static/content/principles_real_objects.png b/docs/html/design/media/principles_real_objects.png
similarity index 100%
rename from docs/html/design/static/content/principles_real_objects.png
rename to docs/html/design/media/principles_real_objects.png
Binary files differ
diff --git a/docs/html/design/static/content/principles_sprinkle_encouragement.png b/docs/html/design/media/principles_sprinkle_encouragement.png
similarity index 100%
rename from docs/html/design/static/content/principles_sprinkle_encouragement.png
rename to docs/html/design/media/principles_sprinkle_encouragement.png
Binary files differ
diff --git a/docs/html/design/static/content/principles_tricks.png b/docs/html/design/media/principles_tricks.png
similarity index 100%
rename from docs/html/design/static/content/principles_tricks.png
rename to docs/html/design/media/principles_tricks.png
Binary files differ
diff --git a/docs/html/design/static/content/progress_activity.png b/docs/html/design/media/progress_activity.png
similarity index 100%
rename from docs/html/design/static/content/progress_activity.png
rename to docs/html/design/media/progress_activity.png
Binary files differ
diff --git a/docs/html/design/static/content/progress_activity2.png b/docs/html/design/media/progress_activity2.png
similarity index 100%
rename from docs/html/design/static/content/progress_activity2.png
rename to docs/html/design/media/progress_activity2.png
Binary files differ
diff --git a/docs/html/design/static/content/progress_download.png b/docs/html/design/media/progress_download.png
similarity index 100%
rename from docs/html/design/static/content/progress_download.png
rename to docs/html/design/media/progress_download.png
Binary files differ
diff --git a/docs/html/design/static/content/progress_themes.png b/docs/html/design/media/progress_themes.png
similarity index 100%
rename from docs/html/design/static/content/progress_themes.png
rename to docs/html/design/media/progress_themes.png
Binary files differ
diff --git a/docs/html/design/static/content/scroll_index.mp4 b/docs/html/design/media/scroll_index.mp4
similarity index 100%
rename from docs/html/design/static/content/scroll_index.mp4
rename to docs/html/design/media/scroll_index.mp4
Binary files differ
diff --git a/docs/html/design/static/content/scroll_index.ogv b/docs/html/design/media/scroll_index.ogv
similarity index 100%
rename from docs/html/design/static/content/scroll_index.ogv
rename to docs/html/design/media/scroll_index.ogv
Binary files differ
diff --git a/docs/html/design/static/content/scroll_index.webm b/docs/html/design/media/scroll_index.webm
similarity index 100%
rename from docs/html/design/static/content/scroll_index.webm
rename to docs/html/design/media/scroll_index.webm
Binary files differ
diff --git a/docs/html/design/static/content/scroll_indicator.mp4 b/docs/html/design/media/scroll_indicator.mp4
similarity index 100%
rename from docs/html/design/static/content/scroll_indicator.mp4
rename to docs/html/design/media/scroll_indicator.mp4
Binary files differ
diff --git a/docs/html/design/static/content/scroll_indicator.ogv b/docs/html/design/media/scroll_indicator.ogv
similarity index 100%
rename from docs/html/design/static/content/scroll_indicator.ogv
rename to docs/html/design/media/scroll_indicator.ogv
Binary files differ
diff --git a/docs/html/design/static/content/scroll_indicator.webm b/docs/html/design/media/scroll_indicator.webm
similarity index 100%
rename from docs/html/design/static/content/scroll_indicator.webm
rename to docs/html/design/media/scroll_indicator.webm
Binary files differ
diff --git a/docs/html/design/static/content/seekbar_example.png b/docs/html/design/media/seekbar_example.png
similarity index 100%
rename from docs/html/design/static/content/seekbar_example.png
rename to docs/html/design/media/seekbar_example.png
Binary files differ
diff --git a/docs/html/design/static/content/seekbar_style.png b/docs/html/design/media/seekbar_style.png
similarity index 100%
rename from docs/html/design/static/content/seekbar_style.png
rename to docs/html/design/media/seekbar_style.png
Binary files differ
diff --git a/docs/html/design/static/content/selection_adjusting_actions.png b/docs/html/design/media/selection_adjusting_actions.png
similarity index 100%
rename from docs/html/design/static/content/selection_adjusting_actions.png
rename to docs/html/design/media/selection_adjusting_actions.png
Binary files differ
diff --git a/docs/html/design/static/content/selection_cab_big.png b/docs/html/design/media/selection_cab_big.png
similarity index 100%
rename from docs/html/design/static/content/selection_cab_big.png
rename to docs/html/design/media/selection_cab_big.png
Binary files differ
diff --git a/docs/html/design/static/content/selection_cab_example.png b/docs/html/design/media/selection_cab_example.png
similarity index 100%
rename from docs/html/design/static/content/selection_cab_example.png
rename to docs/html/design/media/selection_cab_example.png
Binary files differ
diff --git a/docs/html/design/static/content/selection_context_menu.png b/docs/html/design/media/selection_context_menu.png
similarity index 100%
rename from docs/html/design/static/content/selection_context_menu.png
rename to docs/html/design/media/selection_context_menu.png
Binary files differ
diff --git a/docs/html/design/static/content/spinners_actionbar.png b/docs/html/design/media/spinners_actionbar.png
similarity index 100%
rename from docs/html/design/static/content/spinners_actionbar.png
rename to docs/html/design/media/spinners_actionbar.png
Binary files differ
diff --git a/docs/html/design/static/content/spinners_form.png b/docs/html/design/media/spinners_form.png
similarity index 100%
rename from docs/html/design/static/content/spinners_form.png
rename to docs/html/design/media/spinners_form.png
Binary files differ
diff --git a/docs/html/design/static/content/spinners_hololightanddark.png b/docs/html/design/media/spinners_hololightanddark.png
similarity index 100%
rename from docs/html/design/static/content/spinners_hololightanddark.png
rename to docs/html/design/media/spinners_hololightanddark.png
Binary files differ
diff --git a/docs/html/design/static/content/swipe_tabs.mp4 b/docs/html/design/media/swipe_tabs.mp4
similarity index 100%
rename from docs/html/design/static/content/swipe_tabs.mp4
rename to docs/html/design/media/swipe_tabs.mp4
Binary files differ
diff --git a/docs/html/design/static/content/swipe_tabs.ogv b/docs/html/design/media/swipe_tabs.ogv
similarity index 100%
rename from docs/html/design/static/content/swipe_tabs.ogv
rename to docs/html/design/media/swipe_tabs.ogv
Binary files differ
diff --git a/docs/html/design/static/content/swipe_tabs.png b/docs/html/design/media/swipe_tabs.png
similarity index 100%
rename from docs/html/design/static/content/swipe_tabs.png
rename to docs/html/design/media/swipe_tabs.png
Binary files differ
diff --git a/docs/html/design/static/content/swipe_tabs.webm b/docs/html/design/media/swipe_tabs.webm
similarity index 100%
rename from docs/html/design/static/content/swipe_tabs.webm
rename to docs/html/design/media/swipe_tabs.webm
Binary files differ
diff --git a/docs/html/design/static/content/swipe_views.png b/docs/html/design/media/swipe_views.png
similarity index 100%
rename from docs/html/design/static/content/swipe_views.png
rename to docs/html/design/media/swipe_views.png
Binary files differ
diff --git a/docs/html/design/static/content/swipe_views2.png b/docs/html/design/media/swipe_views2.png
similarity index 100%
rename from docs/html/design/static/content/swipe_views2.png
rename to docs/html/design/media/swipe_views2.png
Binary files differ
diff --git a/docs/html/design/static/content/switches_checkboxes.png b/docs/html/design/media/switches_checkboxes.png
similarity index 100%
rename from docs/html/design/static/content/switches_checkboxes.png
rename to docs/html/design/media/switches_checkboxes.png
Binary files differ
diff --git a/docs/html/design/static/content/switches_radios.png b/docs/html/design/media/switches_radios.png
similarity index 100%
rename from docs/html/design/static/content/switches_radios.png
rename to docs/html/design/media/switches_radios.png
Binary files differ
diff --git a/docs/html/design/static/content/switches_switches.png b/docs/html/design/media/switches_switches.png
similarity index 100%
rename from docs/html/design/static/content/switches_switches.png
rename to docs/html/design/media/switches_switches.png
Binary files differ
diff --git a/docs/html/design/static/content/system_ui_landing.png b/docs/html/design/media/system_ui_landing.png
similarity index 100%
rename from docs/html/design/static/content/system_ui_landing.png
rename to docs/html/design/media/system_ui_landing.png
Binary files differ
diff --git a/docs/html/design/static/content/tabs_overview.png b/docs/html/design/media/tabs_overview.png
similarity index 100%
rename from docs/html/design/static/content/tabs_overview.png
rename to docs/html/design/media/tabs_overview.png
Binary files differ
diff --git a/docs/html/design/static/content/tabs_scrolly.mp4 b/docs/html/design/media/tabs_scrolly.mp4
similarity index 100%
rename from docs/html/design/static/content/tabs_scrolly.mp4
rename to docs/html/design/media/tabs_scrolly.mp4
Binary files differ
diff --git a/docs/html/design/static/content/tabs_scrolly.ogv b/docs/html/design/media/tabs_scrolly.ogv
similarity index 100%
rename from docs/html/design/static/content/tabs_scrolly.ogv
rename to docs/html/design/media/tabs_scrolly.ogv
Binary files differ
diff --git a/docs/html/design/static/content/tabs_scrolly.webm b/docs/html/design/media/tabs_scrolly.webm
similarity index 100%
rename from docs/html/design/static/content/tabs_scrolly.webm
rename to docs/html/design/media/tabs_scrolly.webm
Binary files differ
diff --git a/docs/html/design/static/content/tabs_stacked.png b/docs/html/design/media/tabs_stacked.png
similarity index 100%
rename from docs/html/design/static/content/tabs_stacked.png
rename to docs/html/design/media/tabs_stacked.png
Binary files differ
diff --git a/docs/html/design/static/content/tabs_standard.png b/docs/html/design/media/tabs_standard.png
similarity index 100%
rename from docs/html/design/static/content/tabs_standard.png
rename to docs/html/design/media/tabs_standard.png
Binary files differ
diff --git a/docs/html/design/static/content/tabs_youtube.png b/docs/html/design/media/tabs_youtube.png
similarity index 100%
rename from docs/html/design/static/content/tabs_youtube.png
rename to docs/html/design/media/tabs_youtube.png
Binary files differ
diff --git a/docs/html/design/static/content/text_input_holodarkandlight.png b/docs/html/design/media/text_input_holodarkandlight.png
similarity index 100%
rename from docs/html/design/static/content/text_input_holodarkandlight.png
rename to docs/html/design/media/text_input_holodarkandlight.png
Binary files differ
diff --git a/docs/html/design/static/content/text_input_singlevsmultiline.png b/docs/html/design/media/text_input_singlevsmultiline.png
similarity index 100%
rename from docs/html/design/static/content/text_input_singlevsmultiline.png
rename to docs/html/design/media/text_input_singlevsmultiline.png
Binary files differ
diff --git a/docs/html/design/static/content/text_input_textselection.png b/docs/html/design/media/text_input_textselection.png
similarity index 100%
rename from docs/html/design/static/content/text_input_textselection.png
rename to docs/html/design/media/text_input_textselection.png
Binary files differ
diff --git a/docs/html/design/static/content/text_input_typesandtypedown.png b/docs/html/design/media/text_input_typesandtypedown.png
similarity index 100%
rename from docs/html/design/static/content/text_input_typesandtypedown.png
rename to docs/html/design/media/text_input_typesandtypedown.png
Binary files differ
diff --git a/docs/html/design/static/content/themes_holo_dark.png b/docs/html/design/media/themes_holo_dark.png
similarity index 100%
rename from docs/html/design/static/content/themes_holo_dark.png
rename to docs/html/design/media/themes_holo_dark.png
Binary files differ
diff --git a/docs/html/design/static/content/themes_holo_inverse.png b/docs/html/design/media/themes_holo_inverse.png
similarity index 100%
rename from docs/html/design/static/content/themes_holo_inverse.png
rename to docs/html/design/media/themes_holo_inverse.png
Binary files differ
diff --git a/docs/html/design/static/content/themes_holo_light.png b/docs/html/design/media/themes_holo_light.png
similarity index 100%
rename from docs/html/design/static/content/themes_holo_light.png
rename to docs/html/design/media/themes_holo_light.png
Binary files differ
diff --git a/docs/html/design/static/content/touch_feedback_communication.png b/docs/html/design/media/touch_feedback_communication.png
similarity index 100%
rename from docs/html/design/static/content/touch_feedback_communication.png
rename to docs/html/design/media/touch_feedback_communication.png
Binary files differ
diff --git a/docs/html/design/static/content/touch_feedback_manipulation.png b/docs/html/design/media/touch_feedback_manipulation.png
similarity index 100%
rename from docs/html/design/static/content/touch_feedback_manipulation.png
rename to docs/html/design/media/touch_feedback_manipulation.png
Binary files differ
diff --git a/docs/html/design/static/content/touch_feedback_reaction_response.png b/docs/html/design/media/touch_feedback_reaction_response.png
similarity index 100%
rename from docs/html/design/static/content/touch_feedback_reaction_response.png
rename to docs/html/design/media/touch_feedback_reaction_response.png
Binary files differ
diff --git a/docs/html/design/static/content/touch_feedback_states.png b/docs/html/design/media/touch_feedback_states.png
similarity index 100%
rename from docs/html/design/static/content/touch_feedback_states.png
rename to docs/html/design/media/touch_feedback_states.png
Binary files differ
diff --git a/docs/html/design/static/content/typography_alphas.png b/docs/html/design/media/typography_alphas.png
similarity index 100%
rename from docs/html/design/static/content/typography_alphas.png
rename to docs/html/design/media/typography_alphas.png
Binary files differ
diff --git a/docs/html/design/static/content/typography_defaults.png b/docs/html/design/media/typography_defaults.png
similarity index 100%
rename from docs/html/design/static/content/typography_defaults.png
rename to docs/html/design/media/typography_defaults.png
Binary files differ
diff --git a/docs/html/design/static/content/typography_main.png b/docs/html/design/media/typography_main.png
similarity index 100%
rename from docs/html/design/static/content/typography_main.png
rename to docs/html/design/media/typography_main.png
Binary files differ
diff --git a/docs/html/design/static/content/typography_sizes.png b/docs/html/design/media/typography_sizes.png
similarity index 100%
rename from docs/html/design/static/content/typography_sizes.png
rename to docs/html/design/media/typography_sizes.png
Binary files differ
diff --git a/docs/html/design/static/content/ui_overview_all_apps.png b/docs/html/design/media/ui_overview_all_apps.png
similarity index 100%
rename from docs/html/design/static/content/ui_overview_all_apps.png
rename to docs/html/design/media/ui_overview_all_apps.png
Binary files differ
diff --git a/docs/html/design/static/content/ui_overview_app_ui.png b/docs/html/design/media/ui_overview_app_ui.png
similarity index 100%
rename from docs/html/design/static/content/ui_overview_app_ui.png
rename to docs/html/design/media/ui_overview_app_ui.png
Binary files differ
diff --git a/docs/html/design/static/content/ui_overview_home_screen.png b/docs/html/design/media/ui_overview_home_screen.png
similarity index 100%
rename from docs/html/design/static/content/ui_overview_home_screen.png
rename to docs/html/design/media/ui_overview_home_screen.png
Binary files differ
diff --git a/docs/html/design/static/content/ui_overview_notifications.png b/docs/html/design/media/ui_overview_notifications.png
similarity index 100%
rename from docs/html/design/static/content/ui_overview_notifications.png
rename to docs/html/design/media/ui_overview_notifications.png
Binary files differ
diff --git a/docs/html/design/static/content/ui_overview_recents.png b/docs/html/design/media/ui_overview_recents.png
similarity index 100%
rename from docs/html/design/static/content/ui_overview_recents.png
rename to docs/html/design/media/ui_overview_recents.png
Binary files differ
diff --git a/docs/html/design/static/content/ui_overview_system_ui.png b/docs/html/design/media/ui_overview_system_ui.png
similarity index 100%
rename from docs/html/design/static/content/ui_overview_system_ui.png
rename to docs/html/design/media/ui_overview_system_ui.png
Binary files differ
diff --git a/docs/html/design/static/content/whats_new_action_bar.png b/docs/html/design/media/whats_new_action_bar.png
similarity index 100%
rename from docs/html/design/static/content/whats_new_action_bar.png
rename to docs/html/design/media/whats_new_action_bar.png
Binary files differ
diff --git a/docs/html/design/static/content/whats_new_multipanel.png b/docs/html/design/media/whats_new_multipanel.png
similarity index 100%
rename from docs/html/design/static/content/whats_new_multipanel.png
rename to docs/html/design/media/whats_new_multipanel.png
Binary files differ
diff --git a/docs/html/design/static/content/whats_new_multiselect.png b/docs/html/design/media/whats_new_multiselect.png
similarity index 100%
rename from docs/html/design/static/content/whats_new_multiselect.png
rename to docs/html/design/media/whats_new_multiselect.png
Binary files differ
diff --git a/docs/html/design/static/content/whats_new_nav_bar.png b/docs/html/design/media/whats_new_nav_bar.png
similarity index 100%
rename from docs/html/design/static/content/whats_new_nav_bar.png
rename to docs/html/design/media/whats_new_nav_bar.png
Binary files differ
diff --git a/docs/html/design/patterns/actionbar.html b/docs/html/design/patterns/actionbar.jd
similarity index 62%
rename from docs/html/design/patterns/actionbar.html
rename to docs/html/design/patterns/actionbar.jd
index 1566d04..9e3f48c 100644
--- a/docs/html/design/patterns/actionbar.html
+++ b/docs/html/design/patterns/actionbar.jd
@@ -1,112 +1,7 @@
-<!DOCTYPE html>
-<html lang="en">
-  <head>
-    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
-    <title>
+page.title=Action Bar
+@jd:body
 
-Android Design - Action Bar
-    </title>
-    <link rel="shortcut icon" type="image/x-icon" href="/favicon.ico">
-    <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Roboto:regular,medium,thin,italic,mediumitalic">
-    <link rel="stylesheet" href="../static/yui-3.3.0-reset-min.css">
-    <link rel="stylesheet" href="../static/default.css">
-
-  </head>
-  <body>
-
-    <div id="page-container">
-
-      <div id="page-header"><a href="../index.html">Android Design</a></div>
-
-      <div id="main-row">
-
-        <ul id="nav">
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../index.html">Get Started</a></div>
-            <ul>
-              <li><a href="../get-started/creative-vision.html">Creative Vision</a></li>
-              <li><a href="../get-started/principles.html">Design Principles</a></li>
-              <li><a href="../get-started/ui-overview.html">UI Overview</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../style/index.html">Style</a></div>
-            <ul>
-              <li><a href="../style/devices-displays.html">Devices and Displays</a></li>
-              <li><a href="../style/themes.html">Themes</a></li>
-              <li><a href="../style/touch-feedback.html">Touch Feedback</a></li>
-              <li><a href="../style/metrics-grids.html">Metrics and Grids</a></li>
-              <li><a href="../style/typography.html">Typography</a></li>
-              <li><a href="../style/color.html">Color</a></li>
-              <li><a href="../style/iconography.html">Iconography</a></li>
-              <li><a href="../style/writing.html">Writing Style</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../patterns/index.html">Patterns</a></div>
-            <ul>
-              <li><a href="../patterns/new-4-0.html">New in Android 4.0</a></li>
-              <li><a href="../patterns/gestures.html">Gestures</a></li>
-              <li><a href="../patterns/app-structure.html">App Structure</a></li>
-              <li><a href="../patterns/navigation.html">Navigation</a></li>
-              <li><a href="../patterns/actionbar.html">Action Bar</a></li>
-              <li><a href="../patterns/multi-pane-layouts.html">Multi-pane Layouts</a></li>
-              <li><a href="../patterns/swipe-views.html">Swipe Views</a></li>
-              <li><a href="../patterns/selection.html">Selection</a></li>
-              <li><a href="../patterns/notifications.html">Notifications</a></li>
-              <li><a href="../patterns/compatibility.html">Compatibility</a></li>
-              <li><a href="../patterns/pure-android.html">Pure Android</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../building-blocks/index.html">Building Blocks</a></div>
-            <ul>
-              <li><a href="../building-blocks/tabs.html">Tabs</a></li>
-              <li><a href="../building-blocks/lists.html">Lists</a></li>
-              <li><a href="../building-blocks/grid-lists.html">Grid Lists</a></li>
-              <li><a href="../building-blocks/scrolling.html">Scrolling</a></li>
-              <li><a href="../building-blocks/spinners.html">Spinners</a></li>
-              <li><a href="../building-blocks/buttons.html">Buttons</a></li>
-              <li><a href="../building-blocks/text-fields.html">Text Fields</a></li>
-              <li><a href="../building-blocks/seek-bars.html">Seek Bars</a></li>
-              <li><a href="../building-blocks/progress.html">Progress &amp; Activity</a></li>
-              <li><a href="../building-blocks/switches.html">Switches</a></li>
-              <li><a href="../building-blocks/dialogs.html">Dialogs</a></li>
-              <li><a href="../building-blocks/pickers.html">Pickers</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header empty"><a href="../downloads/index.html">Downloads</a></div>
-          </li>
-
-          <li>
-            <div id="back-dac-section"><a href="../../index.html">Developers</a></div>
-          </li>
-
-        </ul>
-
-        <div id="content">
-
-          
-          <div class="layout-content-row content-header">
-            <div class="layout-content-col span-9">
-              <h2>Action Bar</h2>
-            </div>
-            <div class="paging-links layout-content-col span-4">
-              <a href="#" class="prev-page-link">Previous</a>
-              <a href="#" class="next-page-link">Next</a>
-            </div>
-          </div>
-          
-
-          
-
-<img src="../static/content/action_bar_pattern_overview.png">
+<img src="{@docRoot}design/media/action_bar_pattern_overview.png">
 
 <p>The <em>action bar</em> is arguably the most important structural element of an Android app. It's a
 dedicated piece of real estate at the top of each screen that is generally persistent throughout the
@@ -125,7 +20,7 @@
 <h2 id="organization">General Organization</h2>
 
 <p>The action bar is split into four different functional areas that apply to most apps.</p>
-<img src="../static/content/action_bar_basics.png">
+<img src="{@docRoot}design/media/action_bar_basics.png">
 
 <div class="layout-content-row">
   <div class="layout-content-col span-7 with-callouts">
@@ -138,10 +33,10 @@
 if you wish.
 Important: If the app is currently not displaying the top-level screen, be sure to display the Up
 caret to the left of the app icon, so the user can navigate up the hierarchy. For more discussion of
-Up navigation, see the <a href="../patterns/navigation.html">Navigation</a> pattern.
+Up navigation, see the <a href="{@docRoot}design/patterns/navigation.html">Navigation</a> pattern.
 
 <div class="figure">
-  <img src="../static/content/action_bar_pattern_up_app_icon.png">
+  <img src="{@docRoot}design/media/action_bar_pattern_up_app_icon.png">
   <div class="figure-caption">
     App icon with and without "up" affordance.
   </div>
@@ -195,7 +90,7 @@
 <p>You can adapt to such changes by using <em>split action bars</em>, which allow you to distribute action bar
 content across multiple bars located below the main action bar or at the bottom of the screen.</p>
 
-<img src="../static/content/action_bar_pattern_rotation.png">
+<img src="{@docRoot}design/media/action_bar_pattern_rotation.png">
 <div class="figure-caption">
   Split action bar showing action buttons at the bottom of the screen in vertical orientation.
 </div>
@@ -221,7 +116,7 @@
   </div>
   <div class="layout-content-col span-3">
 
-    <img src="../static/content/action_bar_pattern_considerations.png">
+    <img src="{@docRoot}design/media/action_bar_pattern_considerations.png">
 
   </div>
 </div>
@@ -232,7 +127,7 @@
 duration of a particular sub-task. CABs are most typically used for tasks that involve acting on
 selected data or text.</p>
 
-<img src="../static/content/action_bar_cab.png">
+<img src="{@docRoot}design/media/action_bar_cab.png">
 <div class="figure-caption">
   Contextual action bar shown in Browser and Gmail
 </div>
@@ -255,7 +150,7 @@
 <p><em>Tabs</em> display app views concurrently and make it easy to explore and switch between them. Use tabs
 if you expect your users to switch views frequently.</p>
 
-<img src="../static/content/tabs_youtube.png">
+<img src="{@docRoot}design/media/tabs_youtube.png">
 
 <p>There are two types of tabs: fixed and scrollable.</p>
 
@@ -276,12 +171,12 @@
   <div class="layout-content-col span-7">
 
     <video width="400" class="with-shadow play-on-hover" autoplay>
-      <source src="../static/content/tabs_scrolly.mp4" type="video/mp4">
-      <source src="../static/content/tabs_scrolly.webm" type="video/webm">
-      <source src="../static/content/tabs_scrolly.ogv" type="video/ogg">
+      <source src="{@docRoot}design/media/tabs_scrolly.mp4" type="video/mp4">
+      <source src="{@docRoot}design/media/tabs_scrolly.webm" type="video/webm">
+      <source src="{@docRoot}design/media/tabs_scrolly.ogv" type="video/ogg">
     </video>
     <div class="figure-caption">
-      Scrolling tabs in Android Market.
+      Scrolling tabs in Google Play.
       <div class="video-instructions">&nbsp;</div>
     </div>
 
@@ -298,7 +193,7 @@
   </div>
   <div class="layout-content-col span-7">
 
-    <img src="../static/content/action_bar_pattern_default_tabs.png">
+    <img src="{@docRoot}design/media/action_bar_pattern_default_tabs.png">
     <div class="figure-caption">
       Default fixed tabs shown in Holo Dark &amp; Light.
     </div>
@@ -320,7 +215,7 @@
   </div>
   <div class="layout-content-col span-7">
 
-    <img src="../static/content/action_bar_pattern_spinner.png">
+    <img src="{@docRoot}design/media/action_bar_pattern_spinner.png">
     <div class="figure-caption">
       Action bar spinner from Calendar application.
     </div>
@@ -336,7 +231,7 @@
 are available. If an action is unavailable in the current context, hide it. Do not show it as
 disabled.</p>
 
-<img src="../static/content/action_bar_pattern_action_icons.png">
+<img src="{@docRoot}design/media/action_bar_pattern_action_icons.png">
 <div class="figure-caption">
   A sampling of action buttons used throughout the Gmail application.
 </div>
@@ -403,7 +298,7 @@
   </div>
   <div class="layout-content-col span-7">
 
-    <img src="../static/content/action_bar_pattern_overflow.png">
+    <img src="{@docRoot}design/media/action_bar_pattern_overflow.png">
     <div class="figure-caption">
       Action overflow is pinned to the right side.
     </div>
@@ -427,7 +322,7 @@
 </li>
 </ul>
 
-<img src="../static/content/action_bar_pattern_table.png">
+<img src="{@docRoot}design/media/action_bar_pattern_table.png">
 <div class="figure-caption">
   In the above table "o" denotes an action bar item and "=" an overflow icon.
 </div>
@@ -438,7 +333,7 @@
 displaying the most recently used sharing service next to a spinner button that contains other
 sharing options.</p>
 
-<img src="../static/content/action_bar_pattern_share_pack.png">
+<img src="{@docRoot}design/media/action_bar_pattern_share_pack.png">
 <div class="figure-caption">
   The Gallery app's share action provider with extended spinner for additional sharing options.
 </div>
@@ -457,55 +352,3 @@
 Examples are the number of unread messages in a messaging inbox view or the Now Playing information
 in a music player. Carefully plan which important information you would like to display and
 structure your action bars accordingly.</p>
-
-
-
-          
-          <div class="layout-content-row content-footer">
-            <div class="paging-links layout-content-col span-9">&nbsp;</div>
-            <div class="paging-links layout-content-col span-4">
-              <a href="#" class="prev-page-link">Previous</a>
-              <a href="#" class="next-page-link">Next</a>
-            </div>
-          </div>
-          
-        </div>
-
-      </div>
-
-      <div id="page-footer">
-
-        <p id="copyright">
-          Except as noted, this content is licensed under
-          <a href="http://creativecommons.org/licenses/by/2.5/">
-          Creative Commons Attribution 2.5</a>.<br>
-          For details and restrictions, see the
-          <a href="http://developer.android.com/license.html">Content License</a>.
-        </p>
-
-        <p>
-          <a href="http://www.android.com/terms.html">Site Terms of Service</a> &ndash;
-          <a href="http://www.android.com/privacy.html">Privacy Policy</a> &ndash;
-          <a href="http://www.android.com/branding.html">Brand Guidelines</a>
-        </p>
-
-      </div>
-    </div>
-
-    <script src="../static/jquery-1.6.2.min.js"></script>
-    <script>
-    var SITE_ROOT = '../';
-    </script>
-    <script src="../static/default.js"></script>
-
-
-    <script type="text/javascript">
-    var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
-    document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
-    </script>
-    <script type="text/javascript">
-    var pageTracker = _gat._getTracker("UA-5831155-1");
-    pageTracker._trackPageview();
-    </script>
-  </body>
-</html>
diff --git a/docs/html/design/patterns/app-structure.html b/docs/html/design/patterns/app-structure.html
deleted file mode 100644
index 1b48280..0000000
--- a/docs/html/design/patterns/app-structure.html
+++ /dev/null
@@ -1,411 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-  <head>
-    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
-    <title>
-
-Android Design - Application Structure
-    </title>
-    <link rel="shortcut icon" type="image/x-icon" href="/favicon.ico">
-    <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Roboto:regular,medium,thin,italic,mediumitalic">
-    <link rel="stylesheet" href="../static/yui-3.3.0-reset-min.css">
-    <link rel="stylesheet" href="../static/default.css">
-
-  </head>
-  <body>
-
-    <div id="page-container">
-
-      <div id="page-header"><a href="../index.html">Android Design</a></div>
-
-      <div id="main-row">
-
-        <ul id="nav">
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../index.html">Get Started</a></div>
-            <ul>
-              <li><a href="../get-started/creative-vision.html">Creative Vision</a></li>
-              <li><a href="../get-started/principles.html">Design Principles</a></li>
-              <li><a href="../get-started/ui-overview.html">UI Overview</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../style/index.html">Style</a></div>
-            <ul>
-              <li><a href="../style/devices-displays.html">Devices and Displays</a></li>
-              <li><a href="../style/themes.html">Themes</a></li>
-              <li><a href="../style/touch-feedback.html">Touch Feedback</a></li>
-              <li><a href="../style/metrics-grids.html">Metrics and Grids</a></li>
-              <li><a href="../style/typography.html">Typography</a></li>
-              <li><a href="../style/color.html">Color</a></li>
-              <li><a href="../style/iconography.html">Iconography</a></li>
-              <li><a href="../style/writing.html">Writing Style</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../patterns/index.html">Patterns</a></div>
-            <ul>
-              <li><a href="../patterns/new-4-0.html">New in Android 4.0</a></li>
-              <li><a href="../patterns/gestures.html">Gestures</a></li>
-              <li><a href="../patterns/app-structure.html">App Structure</a></li>
-              <li><a href="../patterns/navigation.html">Navigation</a></li>
-              <li><a href="../patterns/actionbar.html">Action Bar</a></li>
-              <li><a href="../patterns/multi-pane-layouts.html">Multi-pane Layouts</a></li>
-              <li><a href="../patterns/swipe-views.html">Swipe Views</a></li>
-              <li><a href="../patterns/selection.html">Selection</a></li>
-              <li><a href="../patterns/notifications.html">Notifications</a></li>
-              <li><a href="../patterns/compatibility.html">Compatibility</a></li>
-              <li><a href="../patterns/pure-android.html">Pure Android</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../building-blocks/index.html">Building Blocks</a></div>
-            <ul>
-              <li><a href="../building-blocks/tabs.html">Tabs</a></li>
-              <li><a href="../building-blocks/lists.html">Lists</a></li>
-              <li><a href="../building-blocks/grid-lists.html">Grid Lists</a></li>
-              <li><a href="../building-blocks/scrolling.html">Scrolling</a></li>
-              <li><a href="../building-blocks/spinners.html">Spinners</a></li>
-              <li><a href="../building-blocks/buttons.html">Buttons</a></li>
-              <li><a href="../building-blocks/text-fields.html">Text Fields</a></li>
-              <li><a href="../building-blocks/seek-bars.html">Seek Bars</a></li>
-              <li><a href="../building-blocks/progress.html">Progress &amp; Activity</a></li>
-              <li><a href="../building-blocks/switches.html">Switches</a></li>
-              <li><a href="../building-blocks/dialogs.html">Dialogs</a></li>
-              <li><a href="../building-blocks/pickers.html">Pickers</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header empty"><a href="../downloads/index.html">Downloads</a></div>
-          </li>
-
-          <li>
-            <div id="back-dac-section"><a href="../../index.html">Developers</a></div>
-          </li>
-
-        </ul>
-
-        <div id="content">
-
-          
-          <div class="layout-content-row content-header">
-            <div class="layout-content-col span-9">
-              <h2>Application Structure</h2>
-            </div>
-            <div class="paging-links layout-content-col span-4">
-              <a href="#" class="prev-page-link">Previous</a>
-              <a href="#" class="next-page-link">Next</a>
-            </div>
-          </div>
-          
-
-          
-
-<p>Apps come in many varieties that address very different needs. For example:</p>
-<ul>
-<li>Apps such as Calculator or Camera that are built around a single focused activity handled from a
-  single screen</li>
-<li>Apps such as Phone whose main purpose is to switch between different activities without deeper
-  navigation</li>
-<li>Apps such as Gmail or Market that combine a broad set of data views with deep navigation</li>
-</ul>
-<p>Your app's structure depends largely on the content and tasks you want to surface for your users.</p>
-<h2 id="general-structure">General Structure</h2>
-
-<p>A typical Android app consists of top level and detail/edit views. If the navigation hierarchy is
-deep and complex, category views connect top level and detail views.</p>
-
-<div class="layout-content-row">
-  <div class="layout-content-col span-9">
-
-    <img src="../static/content/app_structure_overview.png">
-
-  </div>
-  <div class="layout-content-col span-4">
-
-<h4>Top level views</h4>
-<p>The top level of the app typically consists of the different views that your app supports. The views
-either show different representations of the same data or expose an altogether different functional
-facet of your app.</p>
-<div class="vspace size-3">&nbsp;</div>
-
-<h4>Category views</h4>
-<p>Category views allow you to drill deeper into your data.</p>
-<div class="vspace size-11">&nbsp;</div>
-
-<h4>Detail/edit view</h4>
-<p>The detail/edit view is where you consume or create data.</p>
-
-  </div>
-</div>
-
-<h2 id="top-level">Top Level</h2>
-
-<p>The layout of your start screen requires special attention. This is the first screen people see
-after launching your app, so it should be an equally rewarding experience for new and frequent
-visitors alike.</p>
-<p>Ask yourself: "What are my typical users most likely going to want to do in my app?", and structure
-your start screen experience accordingly.</p>
-
-<div class="layout-content-row">
-  <div class="layout-content-col span-5">
-
-<h4>Put content forward</h4>
-<p>Many apps focus on the content display. Avoid navigation-only screens and instead let people get to
-the meat of your app right away by making content the centerpiece of your start screen. Choose
-layouts that are visually engaging and appropriate for the data type and screen size.</p>
-
-  </div>
-  <div class="layout-content-col span-8">
-
-    <img src="../static/content/app_structure_market.png">
-    <div class="figure-caption">
-      Market's start screen primarily allows navigation into the stores for Apps, Music, Books,
-      Movies and Games. It is also enriched with tailored recommendations and promotions that
-      surface content of interest to the user. Search is readily available from the action bar.
-    </div>
-
-  </div>
-</div>
-
-<div class="layout-content-row">
-  <div class="layout-content-col span-5">
-
-<h4>Set up action bars for navigation and actions</h4>
-<p>All screens in your app should display action bars to provide consistent navigation and surface
-important actions.</p>
-<p>At the top level, special considerations apply to the action bar:</p>
-<ul>
-<li>Use the action bar to display your app's icon or title.</li>
-<li>If your top level consists of multiple views, or if switching between data from different user
-  accounts is a significant use case, make sure that it's easy for the user to navigate between them
-  by adding view controls to your action bar.</li>
-<li>If your app allows people to create content, consider making the content accessible right from the
-  top level.</li>
-<li>If your content is searchable, include the Search action in the action bar so people can cut
-  through the navigation hierarchy.</li>
-</ul>
-
-  </div>
-  <div class="layout-content-col span-8">
-
-    <img src="../static/content/app_structure_gmail.png">
-    <div class="figure-caption">
-      Email is about productivity, so an efficient, easy-to-skim list with higher data density works
-      well. Navigation supports switching between accounts and recent labels. Icons for creating a
-      new message or searching are prominent in the split action bar at the bottom.
-    </div>
-
-  </div>
-</div>
-
-<div class="layout-content-row">
-  <div class="layout-content-col span-5">
-
-<h4>Create an identity for your app</h4>
-<p>Creating an identity for your app goes beyond the action bar. Your app communicates its identity
-through its data, the way that data is arranged, and how people interact with it. Especially for
-media-rich applications, try to create unique layouts that showcase your data and go beyond the
-monotony of simple list views.</p>
-
-  </div>
-  <div class="layout-content-col span-8">
-
-    <img src="../static/content/app_structure_music_lndscp.png">
-    <div class="figure-caption">
-      The 3D carousel celebrates cover art and establishes a unique identity for the Music app.
-      Defaulting to the Recent view keeps the focus on music the user has been listening to lately.
-    </div>
-
-  </div>
-</div>
-
-<h2 id="categories">Categories</h2>
-
-<p>Generally, the purpose of a deep, data-driven app is to navigate through organizational categories
-to the detail level, where data can be viewed and managed. Minimize perceived navigation effort by
-keeping your apps shallow.</p>
-<p>Even though the number of vertical navigation steps from the top level down to the detail views is
-typically dictated by the structure of your app's content, there are several ways you can cut down
-on the perception of onerous navigation.</p>
-<h4>Use tabs to combine category selection and data display</h4>
-<p>This can be successful if the categories are familiar or the number of categories is small. It has
-the advantage that a level of hierarchy is removed and data remains at the center of the user's
-attention. Navigating laterally between data-rich categories is more akin to a casual browsing
-experience than to an explicit navigation step.</p>
-
-<div class="vspace size-1">&nbsp;</div>
-
-<div class="layout-content-row">
-  <div class="layout-content-col span-8">
-
-<p>If the categories are familiar, predictable, or closely related, use scrolling tabs (where not all
-items are in view simultaneously). Keep the number of scrolling tabs at a manageable level to
-minimize navigational effort. Rule of thumb: no more than 5&ndash;7 tabs.</p>
-
-    <img src="../static/content/app_structure_scrolltabs.png">
-    <div class="figure-caption">
-      Market uses tabs to simultaneously show category choice and content. To navigate between
-      categories, users can swipe left/right on the content.
-    </div>
-
-  </div>
-  <div class="layout-content-col span-5">
-
-<p>If the categories in the tabs are not closely related, favor fixed tabs, so that all categories are
-in view at the same time.</p>
-
-    <img src="../static/content/app_structure_fixedtabs.png">
-    <div class="figure-caption">
-      YouTube uses fixed tabs to switch between different, relatively unrelated functional areas.
-    </div>
-
-
-  </div>
-</div>
-
-<h4>Allow cutting through hierarchies</h4>
-<p>Take advantage of shortcuts that allow people to reach their goals quicker. To allow top-level
-invocation of actions for a data item from within list or grid views, display prominent actions
-directly on list view items using drop-downs or split list items. This lets people invoke actions on
-data without having to navigate all the way down the hierarchy.</p>
-
-<img src="../static/content/app_structure_shortcut_on_item.png">
-<div class="figure-caption">
-  Music allows the user to act upon a data item (song) from within the category view (album),
-  thereby removing the need to navigate all the way down to the song's detail view.
-</div>
-
-<h4>Acting upon multiple data items</h4>
-<p>Even though category views mostly serve to guide people to content detail, keep in mind that there
-are often good reasons to act on collections of data as well.</p>
-<p>For example, if you allow people to delete an item in a detail view, you should also allow them to
-delete multiple items in the category view. Analyze which detail view actions are applicable to
-collections of items. Then use multi-select to allow application of those actions to multiple items
-in a category view.</p>
-<h2 id="details">Details</h2>
-
-<p>The detail view allows you to view and act on your data. The layout of the detail view depends on
-the data type being displayed, and therefore differs widely among apps.</p>
-
-<div class="layout-content-row">
-  <div class="layout-content-col span-4">
-
-<h4>Layout</h4>
-<p>Consider the activities people will perform in the detail view and arrange the layout accordingly.
-For immersive content, make use of the lights-out mode to allow for distraction-free viewing of
-full-screen content.</p>
-
-    <img src="../static/content/app_structure_people_detail.png">
-
-  </div>
-  <div class="layout-content-col span-9">
-
-    <img src="../static/content/app_structure_book_detail_page_flip.png">
-    <div class="figure-caption">
-      Google Books' detail view is all about replicating the experience of reading an actual book.
-      The page-flip animation reinforces that notion. To create an immersive experience the app
-      enters lights-out mode, which hides all system UI affordances.
-    </div>
-
-    <div class="figure-caption">
-      The purpose of the People app's detail view is to surface communication options. The list view
-      allows for efficient scanning and quick access of phone numbers, email addresses and other
-      information items. Split items are used to combine calling and messaging into one compact line
-      item.
-    </div>
-  </div>
-</div>
-
-<h4>Make navigation between detail views efficient</h4>
-<p>If your users are likely to want to look at multiple items in sequence, allow them to navigate
-between items from within the detail view. Use swipe views or other techniques, such as filmstrips,
-to achieve this.</p>
-
-<img src="../static/content/app_structure_gmail_swipe.png">
-<div class="figure-caption">
-  Gmail using swipe views to navigate from detail view to detail view.
-</div>
-
-<img src="../static/content/app_structure_gallery_filmstrip.png">
-<div class="figure-caption">
-  In addition to supporting swipe gestures to move left or right through images, Gallery provides a
-  filmstrip control that lets people quickly jump to specific images.
-</div>
-
-<h2 id="checklist">Checklist</h2>
-
-<ul>
-<li>
-<p>Find ways to display useful content on your start screen.</p>
-</li>
-<li>
-<p>Use action bars to provide consistent navigation.</p>
-</li>
-<li>
-<p>Keep your hierarchies shallow by using horizontal navigation and shortcuts.</p>
-</li>
-<li>
-<p>Use multi-select to allow the user to act on collections of data.</p>
-</li>
-<li>
-<p>Allow for quick navigation between detail items with swipe views.</p>
-</li>
-</ul>
-
-
-
-          
-          <div class="layout-content-row content-footer">
-            <div class="paging-links layout-content-col span-9">&nbsp;</div>
-            <div class="paging-links layout-content-col span-4">
-              <a href="#" class="prev-page-link">Previous</a>
-              <a href="#" class="next-page-link">Next</a>
-            </div>
-          </div>
-          
-        </div>
-
-      </div>
-
-      <div id="page-footer">
-
-        <p id="copyright">
-          Except as noted, this content is licensed under
-          <a href="http://creativecommons.org/licenses/by/2.5/">
-          Creative Commons Attribution 2.5</a>.<br>
-          For details and restrictions, see the
-          <a href="http://developer.android.com/license.html">Content License</a>.
-        </p>
-
-        <p>
-          <a href="http://www.android.com/terms.html">Site Terms of Service</a> &ndash;
-          <a href="http://www.android.com/privacy.html">Privacy Policy</a> &ndash;
-          <a href="http://www.android.com/branding.html">Brand Guidelines</a>
-        </p>
-
-      </div>
-    </div>
-
-    <script src="../static/jquery-1.6.2.min.js"></script>
-    <script>
-    var SITE_ROOT = '../';
-    </script>
-    <script src="../static/default.js"></script>
-
-
-    <script type="text/javascript">
-    var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
-    document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
-    </script>
-    <script type="text/javascript">
-    var pageTracker = _gat._getTracker("UA-5831155-1");
-    pageTracker._trackPageview();
-    </script>
-  </body>
-</html>
diff --git a/docs/html/design/patterns/app-structure.jd b/docs/html/design/patterns/app-structure.jd
new file mode 100644
index 0000000..b54b12f
--- /dev/null
+++ b/docs/html/design/patterns/app-structure.jd
@@ -0,0 +1,254 @@
+page.title=Application Structure
+@jd:body
+
+<p>Apps come in many varieties that address very different needs. For example:</p>
+<ul>
+<li>Apps such as Calculator or Camera that are built around a single focused activity handled from a
+  single screen</li>
+<li>Apps such as Phone whose main purpose is to switch between different activities without deeper
+  navigation</li>
+<li>Apps such as Gmail or Google Play that combine a broad set of data views with deep navigation</li>
+</ul>
+<p>Your app's structure depends largely on the content and tasks you want to surface for your users.</p>
+<h2 id="general-structure">General Structure</h2>
+
+<p>A typical Android app consists of top level and detail/edit views. If the navigation hierarchy is
+deep and complex, category views connect top level and detail views.</p>
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-9">
+
+    <img src="{@docRoot}design/media/app_structure_overview.png">
+
+  </div>
+  <div class="layout-content-col span-4">
+
+<h4>Top level views</h4>
+<p>The top level of the app typically consists of the different views that your app supports. The views
+either show different representations of the same data or expose an altogether different functional
+facet of your app.</p>
+<div class="vspace size-3">&nbsp;</div>
+
+<h4>Category views</h4>
+<p>Category views allow you to drill deeper into your data.</p>
+<div class="vspace size-11">&nbsp;</div>
+
+<h4>Detail/edit view</h4>
+<p>The detail/edit view is where you consume or create data.</p>
+
+  </div>
+</div>
+
+<h2 id="top-level">Top Level</h2>
+
+<p>The layout of your start screen requires special attention. This is the first screen people see
+after launching your app, so it should be an equally rewarding experience for new and frequent
+visitors alike.</p>
+<p>Ask yourself: "What are my typical users most likely going to want to do in my app?", and structure
+your start screen experience accordingly.</p>
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-5">
+
+<h4>Put content forward</h4>
+<p>Many apps focus on the content display. Avoid navigation-only screens and instead let people get to
+the meat of your app right away by making content the centerpiece of your start screen. Choose
+layouts that are visually engaging and appropriate for the data type and screen size.</p>
+
+  </div>
+  <div class="layout-content-col span-8">
+
+    <img src="{@docRoot}design/media/app_structure_market.png">
+    <div class="figure-caption">
+      The Google Play app's start screen primarily allows navigation into the stores for Apps, Music, Books,
+      Movies and Games. It is also enriched with tailored recommendations and promotions that
+      surface content of interest to the user. Search is readily available from the action bar.
+    </div>
+
+  </div>
+</div>
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-5">
+
+<h4>Set up action bars for navigation and actions</h4>
+<p>All screens in your app should display action bars to provide consistent navigation and surface
+important actions.</p>
+<p>At the top level, special considerations apply to the action bar:</p>
+<ul>
+<li>Use the action bar to display your app's icon or title.</li>
+<li>If your top level consists of multiple views, or if switching between data from different user
+  accounts is a significant use case, make sure that it's easy for the user to navigate between them
+  by adding view controls to your action bar.</li>
+<li>If your app allows people to create content, consider making the content accessible right from the
+  top level.</li>
+<li>If your content is searchable, include the Search action in the action bar so people can cut
+  through the navigation hierarchy.</li>
+</ul>
+
+  </div>
+  <div class="layout-content-col span-8">
+
+    <img src="{@docRoot}design/media/app_structure_gmail.png">
+    <div class="figure-caption">
+      Email is about productivity, so an efficient, easy-to-skim list with higher data density works
+      well. Navigation supports switching between accounts and recent labels. Icons for creating a
+      new message or searching are prominent in the split action bar at the bottom.
+    </div>
+
+  </div>
+</div>
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-5">
+
+<h4>Create an identity for your app</h4>
+<p>Creating an identity for your app goes beyond the action bar. Your app communicates its identity
+through its data, the way that data is arranged, and how people interact with it. Especially for
+media-rich applications, try to create unique layouts that showcase your data and go beyond the
+monotony of simple list views.</p>
+
+  </div>
+  <div class="layout-content-col span-8">
+
+    <img src="{@docRoot}design/media/app_structure_music_lndscp.png">
+    <div class="figure-caption">
+      The 3D carousel celebrates cover art and establishes a unique identity for the Music app.
+      Defaulting to the Recent view keeps the focus on music the user has been listening to lately.
+    </div>
+
+  </div>
+</div>
+
+<h2 id="categories">Categories</h2>
+
+<p>Generally, the purpose of a deep, data-driven app is to navigate through organizational categories
+to the detail level, where data can be viewed and managed. Minimize perceived navigation effort by
+keeping your apps shallow.</p>
+<p>Even though the number of vertical navigation steps from the top level down to the detail views is
+typically dictated by the structure of your app's content, there are several ways you can cut down
+on the perception of onerous navigation.</p>
+<h4>Use tabs to combine category selection and data display</h4>
+<p>This can be successful if the categories are familiar or the number of categories is small. It has
+the advantage that a level of hierarchy is removed and data remains at the center of the user's
+attention. Navigating laterally between data-rich categories is more akin to a casual browsing
+experience than to an explicit navigation step.</p>
+
+<div class="vspace size-1">&nbsp;</div>
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-8">
+
+<p>If the categories are familiar, predictable, or closely related, use scrolling tabs (where not all
+items are in view simultaneously). Keep the number of scrolling tabs at a manageable level to
+minimize navigational effort. Rule of thumb: no more than 5&ndash;7 tabs.</p>
+
+    <img src="{@docRoot}design/media/app_structure_scrolltabs.png">
+    <div class="figure-caption">
+      Google Play uses tabs to simultaneously show category choice and content. To navigate between
+      categories, users can swipe left/right on the content.
+    </div>
+
+  </div>
+  <div class="layout-content-col span-5">
+
+<p>If the categories in the tabs are not closely related, favor fixed tabs, so that all categories are
+in view at the same time.</p>
+
+    <img src="{@docRoot}design/media/app_structure_fixedtabs.png">
+    <div class="figure-caption">
+      YouTube uses fixed tabs to switch between different, relatively unrelated functional areas.
+    </div>
+
+
+  </div>
+</div>
+
+<h4>Allow cutting through hierarchies</h4>
+<p>Take advantage of shortcuts that allow people to reach their goals quicker. To allow top-level
+invocation of actions for a data item from within list or grid views, display prominent actions
+directly on list view items using drop-downs or split list items. This lets people invoke actions on
+data without having to navigate all the way down the hierarchy.</p>
+
+<img src="{@docRoot}design/media/app_structure_shortcut_on_item.png">
+<div class="figure-caption">
+  Music allows the user to act upon a data item (song) from within the category view (album),
+  thereby removing the need to navigate all the way down to the song's detail view.
+</div>
+
+<h4>Acting upon multiple data items</h4>
+<p>Even though category views mostly serve to guide people to content detail, keep in mind that there
+are often good reasons to act on collections of data as well.</p>
+<p>For example, if you allow people to delete an item in a detail view, you should also allow them to
+delete multiple items in the category view. Analyze which detail view actions are applicable to
+collections of items. Then use multi-select to allow application of those actions to multiple items
+in a category view.</p>
+<h2 id="details">Details</h2>
+
+<p>The detail view allows you to view and act on your data. The layout of the detail view depends on
+the data type being displayed, and therefore differs widely among apps.</p>
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-4">
+
+<h4>Layout</h4>
+<p>Consider the activities people will perform in the detail view and arrange the layout accordingly.
+For immersive content, make use of the lights-out mode to allow for distraction-free viewing of
+full-screen content.</p>
+
+    <img src="{@docRoot}design/media/app_structure_people_detail.png">
+
+  </div>
+  <div class="layout-content-col span-9">
+
+    <img src="{@docRoot}design/media/app_structure_book_detail_page_flip.png">
+    <div class="figure-caption">
+      Google Books' detail view is all about replicating the experience of reading an actual book.
+      The page-flip animation reinforces that notion. To create an immersive experience the app
+      enters lights-out mode, which hides all system UI affordances.
+    </div>
+
+    <div class="figure-caption">
+      The purpose of the People app's detail view is to surface communication options. The list view
+      allows for efficient scanning and quick access of phone numbers, email addresses and other
+      information items. Split items are used to combine calling and messaging into one compact line
+      item.
+    </div>
+  </div>
+</div>
+
+<h4>Make navigation between detail views efficient</h4>
+<p>If your users are likely to want to look at multiple items in sequence, allow them to navigate
+between items from within the detail view. Use swipe views or other techniques, such as filmstrips,
+to achieve this.</p>
+
+<img src="{@docRoot}design/media/app_structure_gmail_swipe.png">
+<div class="figure-caption">
+  Gmail using swipe views to navigate from detail view to detail view.
+</div>
+
+<img src="{@docRoot}design/media/app_structure_gallery_filmstrip.png">
+<div class="figure-caption">
+  In addition to supporting swipe gestures to move left or right through images, Gallery provides a
+  filmstrip control that lets people quickly jump to specific images.
+</div>
+
+<h2 id="checklist">Checklist</h2>
+
+<ul>
+<li>
+<p>Find ways to display useful content on your start screen.</p>
+</li>
+<li>
+<p>Use action bars to provide consistent navigation.</p>
+</li>
+<li>
+<p>Keep your hierarchies shallow by using horizontal navigation and shortcuts.</p>
+</li>
+<li>
+<p>Use multi-select to allow the user to act on collections of data.</p>
+</li>
+<li>
+<p>Allow for quick navigation between detail items with swipe views.</p>
+</li>
+</ul>
diff --git a/docs/html/design/patterns/compatibility.html b/docs/html/design/patterns/compatibility.html
deleted file mode 100644
index d6e59f5..0000000
--- a/docs/html/design/patterns/compatibility.html
+++ /dev/null
@@ -1,218 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-  <head>
-    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
-    <title>
-
-Android Design - Backwards Compatibility
-    </title>
-    <link rel="shortcut icon" type="image/x-icon" href="/favicon.ico">
-    <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Roboto:regular,medium,thin,italic,mediumitalic">
-    <link rel="stylesheet" href="../static/yui-3.3.0-reset-min.css">
-    <link rel="stylesheet" href="../static/default.css">
-
-  </head>
-  <body>
-
-    <div id="page-container">
-
-      <div id="page-header"><a href="../index.html">Android Design</a></div>
-
-      <div id="main-row">
-
-        <ul id="nav">
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../index.html">Get Started</a></div>
-            <ul>
-              <li><a href="../get-started/creative-vision.html">Creative Vision</a></li>
-              <li><a href="../get-started/principles.html">Design Principles</a></li>
-              <li><a href="../get-started/ui-overview.html">UI Overview</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../style/index.html">Style</a></div>
-            <ul>
-              <li><a href="../style/devices-displays.html">Devices and Displays</a></li>
-              <li><a href="../style/themes.html">Themes</a></li>
-              <li><a href="../style/touch-feedback.html">Touch Feedback</a></li>
-              <li><a href="../style/metrics-grids.html">Metrics and Grids</a></li>
-              <li><a href="../style/typography.html">Typography</a></li>
-              <li><a href="../style/color.html">Color</a></li>
-              <li><a href="../style/iconography.html">Iconography</a></li>
-              <li><a href="../style/writing.html">Writing Style</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../patterns/index.html">Patterns</a></div>
-            <ul>
-              <li><a href="../patterns/new-4-0.html">New in Android 4.0</a></li>
-              <li><a href="../patterns/gestures.html">Gestures</a></li>
-              <li><a href="../patterns/app-structure.html">App Structure</a></li>
-              <li><a href="../patterns/navigation.html">Navigation</a></li>
-              <li><a href="../patterns/actionbar.html">Action Bar</a></li>
-              <li><a href="../patterns/multi-pane-layouts.html">Multi-pane Layouts</a></li>
-              <li><a href="../patterns/swipe-views.html">Swipe Views</a></li>
-              <li><a href="../patterns/selection.html">Selection</a></li>
-              <li><a href="../patterns/notifications.html">Notifications</a></li>
-              <li><a href="../patterns/compatibility.html">Compatibility</a></li>
-              <li><a href="../patterns/pure-android.html">Pure Android</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../building-blocks/index.html">Building Blocks</a></div>
-            <ul>
-              <li><a href="../building-blocks/tabs.html">Tabs</a></li>
-              <li><a href="../building-blocks/lists.html">Lists</a></li>
-              <li><a href="../building-blocks/grid-lists.html">Grid Lists</a></li>
-              <li><a href="../building-blocks/scrolling.html">Scrolling</a></li>
-              <li><a href="../building-blocks/spinners.html">Spinners</a></li>
-              <li><a href="../building-blocks/buttons.html">Buttons</a></li>
-              <li><a href="../building-blocks/text-fields.html">Text Fields</a></li>
-              <li><a href="../building-blocks/seek-bars.html">Seek Bars</a></li>
-              <li><a href="../building-blocks/progress.html">Progress &amp; Activity</a></li>
-              <li><a href="../building-blocks/switches.html">Switches</a></li>
-              <li><a href="../building-blocks/dialogs.html">Dialogs</a></li>
-              <li><a href="../building-blocks/pickers.html">Pickers</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header empty"><a href="../downloads/index.html">Downloads</a></div>
-          </li>
-
-          <li>
-            <div id="back-dac-section"><a href="../../index.html">Developers</a></div>
-          </li>
-
-        </ul>
-
-        <div id="content">
-
-          
-          <div class="layout-content-row content-header">
-            <div class="layout-content-col span-9">
-              <h2>Backwards Compatibility</h2>
-            </div>
-            <div class="paging-links layout-content-col span-4">
-              <a href="#" class="prev-page-link">Previous</a>
-              <a href="#" class="next-page-link">Next</a>
-            </div>
-          </div>
-          
-
-          
-
-<p>Significant changes in Android 3.0 included:</p>
-<ul>
-<li>Deprecation of navigation hardware keys (Back, Menu, Search, Home) in favor of handling navigation
-  via virtual controls (Back, Home, Recents).</li>
-<li>Robust pattern for the use of menus in action bars.</li>
-</ul>
-<p>Android 4.0 brings these changes for tablets to the phone platform.</p>
-
-<h2 id="older-hardware">Adapting Android 4.0 to Older Hardware and Apps</h2>
-
-<div class="layout-content-row">
-  <div class="layout-content-col span-6">
-
-<h4>Phones with virtual navigation controls</h4>
-<p>Android apps written for Android 3.0 and later display actions in the action bar. Actions that don't
-fit in the action bar or aren't important enough to be displayed at the top level appear in the
-action overflow.</p>
-<p>Users access the action overflow by touching it in the action bar.</p>
-
-  </div>
-  <div class="layout-content-col span-7">
-
-    <img src="../static/content/compatibility_virtual_nav.png">
-
-  </div>
-</div>
-
-<div class="layout-content-row">
-  <div class="layout-content-col span-6">
-
-<h4>Phones with physical navigation keys</h4>
-<p>Android phones with traditional navigation hardware keys don't display the virtual navigation bar at
-the bottom of the screen. Instead, the action overflow is available from the menu hardware key. The
-resulting actions popup has the same style as in the previous example, but is displayed at the bottom of the screen.</p>
-
-  </div>
-  <div class="layout-content-col span-7">
-
-    <img src="../static/content/compatibility_physical_buttons.png">
-
-  </div>
-</div>
-
-<div class="layout-content-row">
-  <div class="layout-content-col span-6">
-
-<h4>Legacy apps on phones with virtual navigation controls</h4>
-<p>When you run an app that was built for Android 2.3 or earlier on a phone with virtual navigation
-controls, an action overflow control appears at the right side of the virtual navigation bar. You
-can touch the control to display the app's actions in the traditional Android menu styling.</p>
-
-  </div>
-  <div class="layout-content-col span-7">
-
-    <img src="../static/content/compatibility_legacy_apps.png">
-
-  </div>
-</div>
-
-
-
-          
-          <div class="layout-content-row content-footer">
-            <div class="paging-links layout-content-col span-9">&nbsp;</div>
-            <div class="paging-links layout-content-col span-4">
-              <a href="#" class="prev-page-link">Previous</a>
-              <a href="#" class="next-page-link">Next</a>
-            </div>
-          </div>
-          
-        </div>
-
-      </div>
-
-      <div id="page-footer">
-
-        <p id="copyright">
-          Except as noted, this content is licensed under
-          <a href="http://creativecommons.org/licenses/by/2.5/">
-          Creative Commons Attribution 2.5</a>.<br>
-          For details and restrictions, see the
-          <a href="http://developer.android.com/license.html">Content License</a>.
-        </p>
-
-        <p>
-          <a href="http://www.android.com/terms.html">Site Terms of Service</a> &ndash;
-          <a href="http://www.android.com/privacy.html">Privacy Policy</a> &ndash;
-          <a href="http://www.android.com/branding.html">Brand Guidelines</a>
-        </p>
-
-      </div>
-    </div>
-
-    <script src="../static/jquery-1.6.2.min.js"></script>
-    <script>
-    var SITE_ROOT = '../';
-    </script>
-    <script src="../static/default.js"></script>
-
-
-    <script type="text/javascript">
-    var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
-    document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
-    </script>
-    <script type="text/javascript">
-    var pageTracker = _gat._getTracker("UA-5831155-1");
-    pageTracker._trackPageview();
-    </script>
-  </body>
-</html>
diff --git a/docs/html/design/patterns/compatibility.jd b/docs/html/design/patterns/compatibility.jd
new file mode 100644
index 0000000..84ae337
--- /dev/null
+++ b/docs/html/design/patterns/compatibility.jd
@@ -0,0 +1,61 @@
+page.title=Backwards Compatibility
+@jd:body
+
+<p>Significant changes in Android 3.0 included:</p>
+<ul>
+<li>Deprecation of navigation hardware keys (Back, Menu, Search, Home) in favor of handling navigation
+  via virtual controls (Back, Home, Recents).</li>
+<li>Robust pattern for the use of menus in action bars.</li>
+</ul>
+<p>Android 4.0 brings these changes for tablets to the phone platform.</p>
+
+<h2 id="older-hardware">Adapting Android 4.0 to Older Hardware and Apps</h2>
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-6">
+
+<h4>Phones with virtual navigation controls</h4>
+<p>Android apps written for Android 3.0 and later display actions in the action bar. Actions that don't
+fit in the action bar or aren't important enough to be displayed at the top level appear in the
+action overflow.</p>
+<p>Users access the action overflow by touching it in the action bar.</p>
+
+  </div>
+  <div class="layout-content-col span-7">
+
+    <img src="{@docRoot}design/media/compatibility_virtual_nav.png">
+
+  </div>
+</div>
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-6">
+
+<h4>Phones with physical navigation keys</h4>
+<p>Android phones with traditional navigation hardware keys don't display the virtual navigation bar at
+the bottom of the screen. Instead, the action overflow is available from the menu hardware key. The
+resulting actions popup has the same style as in the previous example, but is displayed at the bottom of the screen.</p>
+
+  </div>
+  <div class="layout-content-col span-7">
+
+    <img src="{@docRoot}design/media/compatibility_physical_buttons.png">
+
+  </div>
+</div>
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-6">
+
+<h4>Legacy apps on phones with virtual navigation controls</h4>
+<p>When you run an app that was built for Android 2.3 or earlier on a phone with virtual navigation
+controls, an action overflow control appears at the right side of the virtual navigation bar. You
+can touch the control to display the app's actions in the traditional Android menu styling.</p>
+
+  </div>
+  <div class="layout-content-col span-7">
+
+    <img src="{@docRoot}design/media/compatibility_legacy_apps.png">
+
+  </div>
+</div>
diff --git a/docs/html/design/patterns/gestures.html b/docs/html/design/patterns/gestures.html
deleted file mode 100644
index c88817f..0000000
--- a/docs/html/design/patterns/gestures.html
+++ /dev/null
@@ -1,272 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-  <head>
-    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
-    <title>
-
-Android Design - Gestures
-    </title>
-    <link rel="shortcut icon" type="image/x-icon" href="/favicon.ico">
-    <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Roboto:regular,medium,thin,italic,mediumitalic">
-    <link rel="stylesheet" href="../static/yui-3.3.0-reset-min.css">
-    <link rel="stylesheet" href="../static/default.css">
-
-  </head>
-  <body>
-
-    <div id="page-container">
-
-      <div id="page-header"><a href="../index.html">Android Design</a></div>
-
-      <div id="main-row">
-
-        <ul id="nav">
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../index.html">Get Started</a></div>
-            <ul>
-              <li><a href="../get-started/creative-vision.html">Creative Vision</a></li>
-              <li><a href="../get-started/principles.html">Design Principles</a></li>
-              <li><a href="../get-started/ui-overview.html">UI Overview</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../style/index.html">Style</a></div>
-            <ul>
-              <li><a href="../style/devices-displays.html">Devices and Displays</a></li>
-              <li><a href="../style/themes.html">Themes</a></li>
-              <li><a href="../style/touch-feedback.html">Touch Feedback</a></li>
-              <li><a href="../style/metrics-grids.html">Metrics and Grids</a></li>
-              <li><a href="../style/typography.html">Typography</a></li>
-              <li><a href="../style/color.html">Color</a></li>
-              <li><a href="../style/iconography.html">Iconography</a></li>
-              <li><a href="../style/writing.html">Writing Style</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../patterns/index.html">Patterns</a></div>
-            <ul>
-              <li><a href="../patterns/new-4-0.html">New in Android 4.0</a></li>
-              <li><a href="../patterns/gestures.html">Gestures</a></li>
-              <li><a href="../patterns/app-structure.html">App Structure</a></li>
-              <li><a href="../patterns/navigation.html">Navigation</a></li>
-              <li><a href="../patterns/actionbar.html">Action Bar</a></li>
-              <li><a href="../patterns/multi-pane-layouts.html">Multi-pane Layouts</a></li>
-              <li><a href="../patterns/swipe-views.html">Swipe Views</a></li>
-              <li><a href="../patterns/selection.html">Selection</a></li>
-              <li><a href="../patterns/notifications.html">Notifications</a></li>
-              <li><a href="../patterns/compatibility.html">Compatibility</a></li>
-              <li><a href="../patterns/pure-android.html">Pure Android</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../building-blocks/index.html">Building Blocks</a></div>
-            <ul>
-              <li><a href="../building-blocks/tabs.html">Tabs</a></li>
-              <li><a href="../building-blocks/lists.html">Lists</a></li>
-              <li><a href="../building-blocks/grid-lists.html">Grid Lists</a></li>
-              <li><a href="../building-blocks/scrolling.html">Scrolling</a></li>
-              <li><a href="../building-blocks/spinners.html">Spinners</a></li>
-              <li><a href="../building-blocks/buttons.html">Buttons</a></li>
-              <li><a href="../building-blocks/text-fields.html">Text Fields</a></li>
-              <li><a href="../building-blocks/seek-bars.html">Seek Bars</a></li>
-              <li><a href="../building-blocks/progress.html">Progress &amp; Activity</a></li>
-              <li><a href="../building-blocks/switches.html">Switches</a></li>
-              <li><a href="../building-blocks/dialogs.html">Dialogs</a></li>
-              <li><a href="../building-blocks/pickers.html">Pickers</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header empty"><a href="../downloads/index.html">Downloads</a></div>
-          </li>
-
-          <li>
-            <div id="back-dac-section"><a href="../../index.html">Developers</a></div>
-          </li>
-
-        </ul>
-
-        <div id="content">
-
-          
-          <div class="layout-content-row content-header">
-            <div class="layout-content-col span-9">
-              <h2>Gestures</h2>
-            </div>
-            <div class="paging-links layout-content-col span-4">
-              <a href="#" class="prev-page-link">Previous</a>
-              <a href="#" class="next-page-link">Next</a>
-            </div>
-          </div>
-          
-
-          
-
-<p>Gestures allow users to interact with your app by manipulating the screen objects you provide. The
-following table shows the core gesture set that is supported in Android.</p>
-
-<div class="layout-content-row">
-  <div class="layout-content-col span-4">
-
-    <img src="../static/content/gesture_touch.png">
-
-<h4>Touch</h4>
-<p>Triggers the default functionality for a given item.</p>
-
-<ul>
-  <li class="no-bullet with-icon action">
-    <h4>Action</h4>
-    <p>Press, lift</p></li>
-</ul>
-
-  </div>
-  <div class="layout-content-col span-4">
-
-    <img src="../static/content/gesture_longtouch.png">
-
-<h4>Long press</h4>
-<p>Enters data selection mode. Allows you to select one or more items in a view and act upon
-  the data using a contextual action bar. Avoid using long press for showing contextual menus.</p>
-
-<ul>
-  <li class="no-bullet with-icon action">
-    <h4>Action</h4>
-    <p>Press, wait, lift</p></li>
-</ul>
-
-  </div>
-  <div class="layout-content-col span-4">
-
-    <img src="../static/content/gesture_swipe.png">
-
-<h4>Swipe</h4>
-<p>Scrolls overflowing content, or navigates between views in the same hierarchy.</p>
-
-<ul>
-  <li class="no-bullet with-icon action">
-    <h4>Action</h4>
-    <p>Press, move, lift</p></li>
-</ul>
-
-  </div>
-</div>
-
-
-<div class="layout-content-row">
-  <div class="layout-content-col span-4">
-
-    <img src="../static/content/gesture_drag.png">
-
-<h4>Drag</h4>
-<p>Rearranges data within a view, or moves data into a container (e.g. folders on Home Screen).</p>
-
-<ul>
-  <li class="no-bullet with-icon action">
-    <h4>Action</h4>
-    <p>Long press, move, lift</p></li>
-</ul>
-
-  </div>
-  <div class="layout-content-col span-4">
-
-    <img src="../static/content/gesture_doubletouch.png">
-
-<h4>Double touch</h4>
-<p>Zooms into content. Also used as a secondary gesture for text selection.</p>
-
-<ul>
-  <li class="no-bullet with-icon action">
-    <h4>Action</h4>
-    <p>Two touches in quick succession</p></li>
-</ul>
-
-  </div>
-  <div class="layout-content-col span-4">
-
-    <img src="../static/content/gesture_pinchopen.png">
-
-<h4>Pinch open</h4>
-<p>Zooms into content.</p>
-
-<ul>
-  <li class="no-bullet with-icon action">
-    <h4>Action</h4>
-    <p>2-finger press, move outwards, lift</p></li>
-</ul>
-
-  </div>
-</div>
-
-
-<div class="layout-content-row">
-  <div class="layout-content-col span-4">
-
-    <img src="../static/content/gesture_pinchclose.png">
-
-<h4>Pinch close</h4>
-<p>Zooms out of content.</p>
-
-<ul>
-  <li class="no-bullet with-icon action">
-    <h4>Action</h4>
-    <p>2-finger press, move inwards, lift</p></li>
-</ul>
-
-  </div>
-</div>
-
-
-
-          
-          <div class="layout-content-row content-footer">
-            <div class="paging-links layout-content-col span-9">&nbsp;</div>
-            <div class="paging-links layout-content-col span-4">
-              <a href="#" class="prev-page-link">Previous</a>
-              <a href="#" class="next-page-link">Next</a>
-            </div>
-          </div>
-          
-        </div>
-
-      </div>
-
-      <div id="page-footer">
-
-        <p id="copyright">
-          Except as noted, this content is licensed under
-          <a href="http://creativecommons.org/licenses/by/2.5/">
-          Creative Commons Attribution 2.5</a>.<br>
-          For details and restrictions, see the
-          <a href="http://developer.android.com/license.html">Content License</a>.
-        </p>
-
-        <p>
-          <a href="http://www.android.com/terms.html">Site Terms of Service</a> &ndash;
-          <a href="http://www.android.com/privacy.html">Privacy Policy</a> &ndash;
-          <a href="http://www.android.com/branding.html">Brand Guidelines</a>
-        </p>
-
-      </div>
-    </div>
-
-    <script src="../static/jquery-1.6.2.min.js"></script>
-    <script>
-    var SITE_ROOT = '../';
-    </script>
-    <script src="../static/default.js"></script>
-
-
-    <script type="text/javascript">
-    var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
-    document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
-    </script>
-    <script type="text/javascript">
-    var pageTracker = _gat._getTracker("UA-5831155-1");
-    pageTracker._trackPageview();
-    </script>
-  </body>
-</html>
diff --git a/docs/html/design/patterns/gestures.jd b/docs/html/design/patterns/gestures.jd
new file mode 100644
index 0000000..9868df2
--- /dev/null
+++ b/docs/html/design/patterns/gestures.jd
@@ -0,0 +1,115 @@
+page.title=Gestures
+@jd:body
+
+<p>Gestures allow users to interact with your app by manipulating the screen objects you provide. The
+following table shows the core gesture set that is supported in Android.</p>
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-4">
+
+    <img src="{@docRoot}design/media/gesture_touch.png">
+
+<h4>Touch</h4>
+<p>Triggers the default functionality for a given item.</p>
+
+<ul>
+  <li class="no-bullet with-icon action">
+    <h4>Action</h4>
+    <p>Press, lift</p></li>
+</ul>
+
+  </div>
+  <div class="layout-content-col span-4">
+
+    <img src="{@docRoot}design/media/gesture_longtouch.png">
+
+<h4>Long press</h4>
+<p>Enters data selection mode. Allows you to select one or more items in a view and act upon
+  the data using a contextual action bar. Avoid using long press for showing contextual menus.</p>
+
+<ul>
+  <li class="no-bullet with-icon action">
+    <h4>Action</h4>
+    <p>Press, wait, lift</p></li>
+</ul>
+
+  </div>
+  <div class="layout-content-col span-4">
+
+    <img src="{@docRoot}design/media/gesture_swipe.png">
+
+<h4>Swipe</h4>
+<p>Scrolls overflowing content, or navigates between views in the same hierarchy.</p>
+
+<ul>
+  <li class="no-bullet with-icon action">
+    <h4>Action</h4>
+    <p>Press, move, lift</p></li>
+</ul>
+
+  </div>
+</div>
+
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-4">
+
+    <img src="{@docRoot}design/media/gesture_drag.png">
+
+<h4>Drag</h4>
+<p>Rearranges data within a view, or moves data into a container (e.g. folders on Home Screen).</p>
+
+<ul>
+  <li class="no-bullet with-icon action">
+    <h4>Action</h4>
+    <p>Long press, move, lift</p></li>
+</ul>
+
+  </div>
+  <div class="layout-content-col span-4">
+
+    <img src="{@docRoot}design/media/gesture_doubletouch.png">
+
+<h4>Double touch</h4>
+<p>Zooms into content. Also used as a secondary gesture for text selection.</p>
+
+<ul>
+  <li class="no-bullet with-icon action">
+    <h4>Action</h4>
+    <p>Two touches in quick succession</p></li>
+</ul>
+
+  </div>
+  <div class="layout-content-col span-4">
+
+    <img src="{@docRoot}design/media/gesture_pinchopen.png">
+
+<h4>Pinch open</h4>
+<p>Zooms into content.</p>
+
+<ul>
+  <li class="no-bullet with-icon action">
+    <h4>Action</h4>
+    <p>2-finger press, move outwards, lift</p></li>
+</ul>
+
+  </div>
+</div>
+
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-4">
+
+    <img src="{@docRoot}design/media/gesture_pinchclose.png">
+
+<h4>Pinch close</h4>
+<p>Zooms out of content.</p>
+
+<ul>
+  <li class="no-bullet with-icon action">
+    <h4>Action</h4>
+    <p>2-finger press, move inwards, lift</p></li>
+</ul>
+
+  </div>
+</div>
diff --git a/docs/html/design/patterns/index.html b/docs/html/design/patterns/index.html
deleted file mode 100644
index 863baa9..0000000
--- a/docs/html/design/patterns/index.html
+++ /dev/null
@@ -1,175 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-  <head>
-    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
-    <title>
-
-Android Design - Design Patterns
-    </title>
-    <link rel="shortcut icon" type="image/x-icon" href="/favicon.ico">
-    <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Roboto:regular,medium,thin,italic,mediumitalic">
-    <link rel="stylesheet" href="../static/yui-3.3.0-reset-min.css">
-    <link rel="stylesheet" href="../static/default.css">
-
-<style>
-#landing-graphic-container {
-  position: relative;
-}
-
-#text-overlay {
-  position: absolute;
-  left: 10px;
-  top: 492px;
-  width: 200px;
-}
-</style>
-
-  </head>
-  <body>
-
-    <div id="page-container">
-
-      <div id="page-header"><a href="../index.html">Android Design</a></div>
-
-      <div id="main-row">
-
-        <ul id="nav">
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../index.html">Get Started</a></div>
-            <ul>
-              <li><a href="../get-started/creative-vision.html">Creative Vision</a></li>
-              <li><a href="../get-started/principles.html">Design Principles</a></li>
-              <li><a href="../get-started/ui-overview.html">UI Overview</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../style/index.html">Style</a></div>
-            <ul>
-              <li><a href="../style/devices-displays.html">Devices and Displays</a></li>
-              <li><a href="../style/themes.html">Themes</a></li>
-              <li><a href="../style/touch-feedback.html">Touch Feedback</a></li>
-              <li><a href="../style/metrics-grids.html">Metrics and Grids</a></li>
-              <li><a href="../style/typography.html">Typography</a></li>
-              <li><a href="../style/color.html">Color</a></li>
-              <li><a href="../style/iconography.html">Iconography</a></li>
-              <li><a href="../style/writing.html">Writing Style</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../patterns/index.html">Patterns</a></div>
-            <ul>
-              <li><a href="../patterns/new-4-0.html">New in Android 4.0</a></li>
-              <li><a href="../patterns/gestures.html">Gestures</a></li>
-              <li><a href="../patterns/app-structure.html">App Structure</a></li>
-              <li><a href="../patterns/navigation.html">Navigation</a></li>
-              <li><a href="../patterns/actionbar.html">Action Bar</a></li>
-              <li><a href="../patterns/multi-pane-layouts.html">Multi-pane Layouts</a></li>
-              <li><a href="../patterns/swipe-views.html">Swipe Views</a></li>
-              <li><a href="../patterns/selection.html">Selection</a></li>
-              <li><a href="../patterns/notifications.html">Notifications</a></li>
-              <li><a href="../patterns/compatibility.html">Compatibility</a></li>
-              <li><a href="../patterns/pure-android.html">Pure Android</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../building-blocks/index.html">Building Blocks</a></div>
-            <ul>
-              <li><a href="../building-blocks/tabs.html">Tabs</a></li>
-              <li><a href="../building-blocks/lists.html">Lists</a></li>
-              <li><a href="../building-blocks/grid-lists.html">Grid Lists</a></li>
-              <li><a href="../building-blocks/scrolling.html">Scrolling</a></li>
-              <li><a href="../building-blocks/spinners.html">Spinners</a></li>
-              <li><a href="../building-blocks/buttons.html">Buttons</a></li>
-              <li><a href="../building-blocks/text-fields.html">Text Fields</a></li>
-              <li><a href="../building-blocks/seek-bars.html">Seek Bars</a></li>
-              <li><a href="../building-blocks/progress.html">Progress &amp; Activity</a></li>
-              <li><a href="../building-blocks/switches.html">Switches</a></li>
-              <li><a href="../building-blocks/dialogs.html">Dialogs</a></li>
-              <li><a href="../building-blocks/pickers.html">Pickers</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header empty"><a href="../downloads/index.html">Downloads</a></div>
-          </li>
-
-          <li>
-            <div id="back-dac-section"><a href="../../index.html">Developers</a></div>
-          </li>
-
-        </ul>
-
-        <div id="content">
-
-          
-<div class="layout-content-row content-header just-links">
-  <div class="layout-content-col span-9">&nbsp;</div>
-  <div class="paging-links layout-content-col span-4">
-    <a href="#" class="prev-page-link">Previous</a>
-    <a href="#" class="next-page-link">Next</a>
-  </div>
-</div>
-
-
-          
-
-<div id="landing-graphic-container">
-  <div id="text-overlay">
-    Design apps that behave in a consistent, predictable fashion.
-    <br><br>
-    <a href="../patterns/new-4-0.html" class="landing-page-link">New in Android 4.0</a>
-  </div>
-
-  <a href="../patterns/new-4-0.html">
-    <img src="../static/content/patterns_landing.png">
-  </a>
-</div>
-
-
-
-          
-
-        </div>
-
-      </div>
-
-      <div id="page-footer">
-
-        <p id="copyright">
-          Except as noted, this content is licensed under
-          <a href="http://creativecommons.org/licenses/by/2.5/">
-          Creative Commons Attribution 2.5</a>.<br>
-          For details and restrictions, see the
-          <a href="http://developer.android.com/license.html">Content License</a>.
-        </p>
-
-        <p>
-          <a href="http://www.android.com/terms.html">Site Terms of Service</a> &ndash;
-          <a href="http://www.android.com/privacy.html">Privacy Policy</a> &ndash;
-          <a href="http://www.android.com/branding.html">Brand Guidelines</a>
-        </p>
-
-      </div>
-    </div>
-
-    <script src="../static/jquery-1.6.2.min.js"></script>
-    <script>
-    var SITE_ROOT = '../';
-    </script>
-    <script src="../static/default.js"></script>
-
-
-    <script type="text/javascript">
-    var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
-    document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
-    </script>
-    <script type="text/javascript">
-    var pageTracker = _gat._getTracker("UA-5831155-1");
-    pageTracker._trackPageview();
-    </script>
-  </body>
-</html>
diff --git a/docs/html/design/patterns/index.jd b/docs/html/design/patterns/index.jd
new file mode 100644
index 0000000..732e4db
--- /dev/null
+++ b/docs/html/design/patterns/index.jd
@@ -0,0 +1,29 @@
+page.title=Patterns
+header.justLinks=1
+footer.hide=1
+@jd:body
+
+<style>
+#landing-graphic-container {
+  position: relative;
+}
+
+#text-overlay {
+  position: absolute;
+  left: 10px;
+  top: 492px;
+  width: 200px;
+}
+</style>
+
+<div id="landing-graphic-container">
+  <div id="text-overlay">
+    Design apps that behave in a consistent, predictable fashion.
+    <br><br>
+    <a href="{@docRoot}design/patterns/new-4-0.html" class="landing-page-link">New in Android 4.0</a>
+  </div>
+
+  <a href="{@docRoot}design/patterns/new-4-0.html">
+    <img src="{@docRoot}design/media/patterns_landing.png">
+  </a>
+</div>
diff --git a/docs/html/design/patterns/multi-pane-layouts.html b/docs/html/design/patterns/multi-pane-layouts.html
deleted file mode 100644
index 7925c98..0000000
--- a/docs/html/design/patterns/multi-pane-layouts.html
+++ /dev/null
@@ -1,267 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-  <head>
-    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
-    <title>
-
-Android Design - Multi-pane Layouts
-    </title>
-    <link rel="shortcut icon" type="image/x-icon" href="/favicon.ico">
-    <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Roboto:regular,medium,thin,italic,mediumitalic">
-    <link rel="stylesheet" href="../static/yui-3.3.0-reset-min.css">
-    <link rel="stylesheet" href="../static/default.css">
-
-  </head>
-  <body>
-
-    <div id="page-container">
-
-      <div id="page-header"><a href="../index.html">Android Design</a></div>
-
-      <div id="main-row">
-
-        <ul id="nav">
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../index.html">Get Started</a></div>
-            <ul>
-              <li><a href="../get-started/creative-vision.html">Creative Vision</a></li>
-              <li><a href="../get-started/principles.html">Design Principles</a></li>
-              <li><a href="../get-started/ui-overview.html">UI Overview</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../style/index.html">Style</a></div>
-            <ul>
-              <li><a href="../style/devices-displays.html">Devices and Displays</a></li>
-              <li><a href="../style/themes.html">Themes</a></li>
-              <li><a href="../style/touch-feedback.html">Touch Feedback</a></li>
-              <li><a href="../style/metrics-grids.html">Metrics and Grids</a></li>
-              <li><a href="../style/typography.html">Typography</a></li>
-              <li><a href="../style/color.html">Color</a></li>
-              <li><a href="../style/iconography.html">Iconography</a></li>
-              <li><a href="../style/writing.html">Writing Style</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../patterns/index.html">Patterns</a></div>
-            <ul>
-              <li><a href="../patterns/new-4-0.html">New in Android 4.0</a></li>
-              <li><a href="../patterns/gestures.html">Gestures</a></li>
-              <li><a href="../patterns/app-structure.html">App Structure</a></li>
-              <li><a href="../patterns/navigation.html">Navigation</a></li>
-              <li><a href="../patterns/actionbar.html">Action Bar</a></li>
-              <li><a href="../patterns/multi-pane-layouts.html">Multi-pane Layouts</a></li>
-              <li><a href="../patterns/swipe-views.html">Swipe Views</a></li>
-              <li><a href="../patterns/selection.html">Selection</a></li>
-              <li><a href="../patterns/notifications.html">Notifications</a></li>
-              <li><a href="../patterns/compatibility.html">Compatibility</a></li>
-              <li><a href="../patterns/pure-android.html">Pure Android</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../building-blocks/index.html">Building Blocks</a></div>
-            <ul>
-              <li><a href="../building-blocks/tabs.html">Tabs</a></li>
-              <li><a href="../building-blocks/lists.html">Lists</a></li>
-              <li><a href="../building-blocks/grid-lists.html">Grid Lists</a></li>
-              <li><a href="../building-blocks/scrolling.html">Scrolling</a></li>
-              <li><a href="../building-blocks/spinners.html">Spinners</a></li>
-              <li><a href="../building-blocks/buttons.html">Buttons</a></li>
-              <li><a href="../building-blocks/text-fields.html">Text Fields</a></li>
-              <li><a href="../building-blocks/seek-bars.html">Seek Bars</a></li>
-              <li><a href="../building-blocks/progress.html">Progress &amp; Activity</a></li>
-              <li><a href="../building-blocks/switches.html">Switches</a></li>
-              <li><a href="../building-blocks/dialogs.html">Dialogs</a></li>
-              <li><a href="../building-blocks/pickers.html">Pickers</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header empty"><a href="../downloads/index.html">Downloads</a></div>
-          </li>
-
-          <li>
-            <div id="back-dac-section"><a href="../../index.html">Developers</a></div>
-          </li>
-
-        </ul>
-
-        <div id="content">
-
-          
-          <div class="layout-content-row content-header">
-            <div class="layout-content-col span-9">
-              <h2>Multi-pane Layouts</h2>
-            </div>
-            <div class="paging-links layout-content-col span-4">
-              <a href="#" class="prev-page-link">Previous</a>
-              <a href="#" class="next-page-link">Next</a>
-            </div>
-          </div>
-          
-
-          
-
-<p>When writing an app for Android, keep in mind that Android devices come in many different screen
-sizes and types. Make sure that your app consistently provides a balanced and aesthetically pleasing
-layout by adjusting its content to varying screen sizes and orientations.</p>
-<p><em>Panels</em> are a great way for your app to achieve this. They allow you to combine multiple views into
-one compound view when a lot of horizontal screen real estate is available and by splitting them up
-when less space is available.</p>
-<h2 id="combining-views">Combining Multiple Views Into One</h2>
-
-<p>On smaller devices your content is typically divided into a master grid or list view and a detail
-view. Touching an item in the master view opens a different screen showing that item's detail
-information.</p>
-
-<img src="../static/content/multipane_views.png">
-
-<p>Because tablets have more screen real estate than phones, you can use panels to combine the related
-list and detail views into a single compound view. This uses the additional space more efficiently
-and makes navigating the app easier. </p>
-
-<img src="../static/content/multipane_view_tablet.png">
-
-<p>In general, use the pane on the right to present more information about the item you selected in the
-left pane. Make sure to keep the item in the left pane selected in order to establish the
-relationship between the panels.</p>
-<h2 id="orientation">Compound Views and Orientation Changes</h2>
-
-<p>Screens should have the same functionality regardless of orientation. If you use a compound view in
-one orientation, don't split it up when the user rotates the screen. There are several techniques
-you can use to adjust the layout after orientation change while keeping functional parity intact.</p>
-
-<div class="layout-content-row">
-  <div class="layout-content-col span-8">
-
-    <img src="../static/content/multipane_stretch.png">
-    
-  </div>
-  <div class="layout-content-col span-5">
-
-<h4>Stretch/compress</h4>
-<p>Adjust the column width of your left pane to achieve a balanced layout in both orientations.</p>
-
-  </div>
-</div>
-
-<div class="layout-content-row">
-  <div class="layout-content-col span-8">
-
-    <img src="../static/content/multipane_stack.png">
-    
-  </div>
-  <div class="layout-content-col span-5">
-
-<h4>Stack</h4>
-<p>Rearrange the panels on your screen to match the orientation.</p>
-
-  </div>
-</div>
-
-<div class="layout-content-row">
-  <div class="layout-content-col span-8">
-
-    <img src="../static/content/multipane_expand.png">
-    
-  </div>
-  <div class="layout-content-col span-5">
-
-<h4>Expand/collapse</h4>
-<p>When the device rotates, collapse the left pane view to only show the most important information.
-Provide an <em>expand</em> control that allows the user to bring the left pane content back to its original
-width and vice versa.</p>
-
-  </div>
-</div>
-
-<div class="layout-content-row">
-  <div class="layout-content-col span-8">
-
-    <img src="../static/content/multipane_show.png">
-    
-  </div>
-  <div class="layout-content-col span-5">
-
-<h4>Show/hide</h4>
-<p>After rotating the device, show the right pane in fullscreen view. Use the Up icon in the action bar
-to show the left panel and allow navigation to a different email. Hide the left panel by touching
-the content in the detail panel.</p>
-
-  </div>
-</div>
-
-<h2 id="checklist">Checklist</h2>
-
-<ul>
-<li>
-<p>Plan in advance on how your app scales to different screen sizes and screen orientations.</p>
-</li>
-<li>
-<p>Identify the most appropriate method for the panels in your compound views to reorganize
-  themselves when screen orientation changes.</p>
-</li>
-<li>
-<p>Look for opportunities to consolidate your views into multi-panel compound views.</p>
-</li>
-<li>
-<p>Make sure that your screens provide functional parity after the screen orientation
-  changes.</p>
-</li>
-</ul>
-
-
-
-          
-          <div class="layout-content-row content-footer">
-            <div class="paging-links layout-content-col span-9">&nbsp;</div>
-            <div class="paging-links layout-content-col span-4">
-              <a href="#" class="prev-page-link">Previous</a>
-              <a href="#" class="next-page-link">Next</a>
-            </div>
-          </div>
-          
-        </div>
-
-      </div>
-
-      <div id="page-footer">
-
-        <p id="copyright">
-          Except as noted, this content is licensed under
-          <a href="http://creativecommons.org/licenses/by/2.5/">
-          Creative Commons Attribution 2.5</a>.<br>
-          For details and restrictions, see the
-          <a href="http://developer.android.com/license.html">Content License</a>.
-        </p>
-
-        <p>
-          <a href="http://www.android.com/terms.html">Site Terms of Service</a> &ndash;
-          <a href="http://www.android.com/privacy.html">Privacy Policy</a> &ndash;
-          <a href="http://www.android.com/branding.html">Brand Guidelines</a>
-        </p>
-
-      </div>
-    </div>
-
-    <script src="../static/jquery-1.6.2.min.js"></script>
-    <script>
-    var SITE_ROOT = '../';
-    </script>
-    <script src="../static/default.js"></script>
-
-
-    <script type="text/javascript">
-    var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
-    document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
-    </script>
-    <script type="text/javascript">
-    var pageTracker = _gat._getTracker("UA-5831155-1");
-    pageTracker._trackPageview();
-    </script>
-  </body>
-</html>
diff --git a/docs/html/design/patterns/multi-pane-layouts.jd b/docs/html/design/patterns/multi-pane-layouts.jd
new file mode 100644
index 0000000..0e63e32
--- /dev/null
+++ b/docs/html/design/patterns/multi-pane-layouts.jd
@@ -0,0 +1,110 @@
+page.title=Multi-pane Layouts
+@jd:body
+
+<p>When writing an app for Android, keep in mind that Android devices come in many different screen
+sizes and types. Make sure that your app consistently provides a balanced and aesthetically pleasing
+layout by adjusting its content to varying screen sizes and orientations.</p>
+<p><em>Panels</em> are a great way for your app to achieve this. They allow you to combine multiple views into
+one compound view when a lot of horizontal screen real estate is available and by splitting them up
+when less space is available.</p>
+<h2 id="combining-views">Combining Multiple Views Into One</h2>
+
+<p>On smaller devices your content is typically divided into a master grid or list view and a detail
+view. Touching an item in the master view opens a different screen showing that item's detail
+information.</p>
+
+<img src="{@docRoot}design/media/multipane_views.png">
+
+<p>Because tablets have more screen real estate than phones, you can use panels to combine the related
+list and detail views into a single compound view. This uses the additional space more efficiently
+and makes navigating the app easier. </p>
+
+<img src="{@docRoot}design/media/multipane_view_tablet.png">
+
+<p>In general, use the pane on the right to present more information about the item you selected in the
+left pane. Make sure to keep the item in the left pane selected in order to establish the
+relationship between the panels.</p>
+<h2 id="orientation">Compound Views and Orientation Changes</h2>
+
+<p>Screens should have the same functionality regardless of orientation. If you use a compound view in
+one orientation, don't split it up when the user rotates the screen. There are several techniques
+you can use to adjust the layout after orientation change while keeping functional parity intact.</p>
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-8">
+
+    <img src="{@docRoot}design/media/multipane_stretch.png">
+    
+  </div>
+  <div class="layout-content-col span-5">
+
+<h4>Stretch/compress</h4>
+<p>Adjust the column width of your left pane to achieve a balanced layout in both orientations.</p>
+
+  </div>
+</div>
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-8">
+
+    <img src="{@docRoot}design/media/multipane_stack.png">
+    
+  </div>
+  <div class="layout-content-col span-5">
+
+<h4>Stack</h4>
+<p>Rearrange the panels on your screen to match the orientation.</p>
+
+  </div>
+</div>
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-8">
+
+    <img src="{@docRoot}design/media/multipane_expand.png">
+    
+  </div>
+  <div class="layout-content-col span-5">
+
+<h4>Expand/collapse</h4>
+<p>When the device rotates, collapse the left pane view to only show the most important information.
+Provide an <em>expand</em> control that allows the user to bring the left pane content back to its original
+width and vice versa.</p>
+
+  </div>
+</div>
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-8">
+
+    <img src="{@docRoot}design/media/multipane_show.png">
+    
+  </div>
+  <div class="layout-content-col span-5">
+
+<h4>Show/hide</h4>
+<p>After rotating the device, show the right pane in fullscreen view. Use the Up icon in the action bar
+to show the left panel and allow navigation to a different email. Hide the left panel by touching
+the content in the detail panel.</p>
+
+  </div>
+</div>
+
+<h2 id="checklist">Checklist</h2>
+
+<ul>
+<li>
+<p>Plan in advance on how your app scales to different screen sizes and screen orientations.</p>
+</li>
+<li>
+<p>Identify the most appropriate method for the panels in your compound views to reorganize
+  themselves when screen orientation changes.</p>
+</li>
+<li>
+<p>Look for opportunities to consolidate your views into multi-panel compound views.</p>
+</li>
+<li>
+<p>Make sure that your screens provide functional parity after the screen orientation
+  changes.</p>
+</li>
+</ul>
diff --git a/docs/html/design/patterns/navigation.html b/docs/html/design/patterns/navigation.html
deleted file mode 100644
index 6287b5e..0000000
--- a/docs/html/design/patterns/navigation.html
+++ /dev/null
@@ -1,275 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-  <head>
-    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
-    <title>
-
-Android Design - Navigation with Back and Up
-    </title>
-    <link rel="shortcut icon" type="image/x-icon" href="/favicon.ico">
-    <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Roboto:regular,medium,thin,italic,mediumitalic">
-    <link rel="stylesheet" href="../static/yui-3.3.0-reset-min.css">
-    <link rel="stylesheet" href="../static/default.css">
-
-  </head>
-  <body>
-
-    <div id="page-container">
-
-      <div id="page-header"><a href="../index.html">Android Design</a></div>
-
-      <div id="main-row">
-
-        <ul id="nav">
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../index.html">Get Started</a></div>
-            <ul>
-              <li><a href="../get-started/creative-vision.html">Creative Vision</a></li>
-              <li><a href="../get-started/principles.html">Design Principles</a></li>
-              <li><a href="../get-started/ui-overview.html">UI Overview</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../style/index.html">Style</a></div>
-            <ul>
-              <li><a href="../style/devices-displays.html">Devices and Displays</a></li>
-              <li><a href="../style/themes.html">Themes</a></li>
-              <li><a href="../style/touch-feedback.html">Touch Feedback</a></li>
-              <li><a href="../style/metrics-grids.html">Metrics and Grids</a></li>
-              <li><a href="../style/typography.html">Typography</a></li>
-              <li><a href="../style/color.html">Color</a></li>
-              <li><a href="../style/iconography.html">Iconography</a></li>
-              <li><a href="../style/writing.html">Writing Style</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../patterns/index.html">Patterns</a></div>
-            <ul>
-              <li><a href="../patterns/new-4-0.html">New in Android 4.0</a></li>
-              <li><a href="../patterns/gestures.html">Gestures</a></li>
-              <li><a href="../patterns/app-structure.html">App Structure</a></li>
-              <li><a href="../patterns/navigation.html">Navigation</a></li>
-              <li><a href="../patterns/actionbar.html">Action Bar</a></li>
-              <li><a href="../patterns/multi-pane-layouts.html">Multi-pane Layouts</a></li>
-              <li><a href="../patterns/swipe-views.html">Swipe Views</a></li>
-              <li><a href="../patterns/selection.html">Selection</a></li>
-              <li><a href="../patterns/notifications.html">Notifications</a></li>
-              <li><a href="../patterns/compatibility.html">Compatibility</a></li>
-              <li><a href="../patterns/pure-android.html">Pure Android</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../building-blocks/index.html">Building Blocks</a></div>
-            <ul>
-              <li><a href="../building-blocks/tabs.html">Tabs</a></li>
-              <li><a href="../building-blocks/lists.html">Lists</a></li>
-              <li><a href="../building-blocks/grid-lists.html">Grid Lists</a></li>
-              <li><a href="../building-blocks/scrolling.html">Scrolling</a></li>
-              <li><a href="../building-blocks/spinners.html">Spinners</a></li>
-              <li><a href="../building-blocks/buttons.html">Buttons</a></li>
-              <li><a href="../building-blocks/text-fields.html">Text Fields</a></li>
-              <li><a href="../building-blocks/seek-bars.html">Seek Bars</a></li>
-              <li><a href="../building-blocks/progress.html">Progress &amp; Activity</a></li>
-              <li><a href="../building-blocks/switches.html">Switches</a></li>
-              <li><a href="../building-blocks/dialogs.html">Dialogs</a></li>
-              <li><a href="../building-blocks/pickers.html">Pickers</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header empty"><a href="../downloads/index.html">Downloads</a></div>
-          </li>
-
-          <li>
-            <div id="back-dac-section"><a href="../../index.html">Developers</a></div>
-          </li>
-
-        </ul>
-
-        <div id="content">
-
-          
-          <div class="layout-content-row content-header">
-            <div class="layout-content-col span-9">
-              <h2>Navigation with Back and Up</h2>
-            </div>
-            <div class="paging-links layout-content-col span-4">
-              <a href="#" class="prev-page-link">Previous</a>
-              <a href="#" class="next-page-link">Next</a>
-            </div>
-          </div>
-          
-
-          
-
-<p>Consistent navigation is an essential component of the overall user experience. Few things frustrate
-users more than basic navigation that behaves in inconsistent and unexpected ways. Android 3.0
-introduced significant changes to the global navigation behavior. Thoughtfully following the
-guidelines for Back and Up will make your app's navigation predictable and reliable for your users.</p>
-<p>Android 2.3 and earlier relied upon the system <em>Back</em> button for supporting navigation within an
-app. With the introduction of action bars in Android 3.0, a second navigation mechanism appeared:
-the <em>Up</em> button, consisting of the app icon and a left-point caret.</p>
-
-<img src="../static/content/navigation_with_back_and_up.png">
-
-<h2 id="up-vs-back">Up vs. Back</h2>
-
-<p>The Up button is used to navigate within an application based on the hierarchical relationships
-between screens. For instance, if screen A displays a list of items, and selecting an item leads to
-screen B (which presents that item in more detail), then screen B should offer an Up button that
-returns to screen A.</p>
-<p>If a screen is the topmost one in an app (i.e. the home of the app), it should not present an Up
-button.</p>
-<p>The system Back key is used to navigate based on the history of screens the user has recently seen,
-in reverse chronological order&mdash;in effect, the temporal relationships between screens.</p>
-<p>When the previously viewed screen is also the hierarchical parent of the current screen, pressing
-the Back key will have the same result as pressing an Up button -- this is a common occurrence.
-However, unlike the Up button, which ensures the user remains within your app, the Back key can
-return the user to the Home screen, or even to a different application.</p>
-
-<img src="../static/content/navigation_up_vs_back_gmail.png">
-
-<p>The Back key also supports a few behaviors not directly tied to screen-to-screen navigation:</p>
-<ul>
-<li>Back dismisses floating windows (dialogs, popups)</li>
-<li>Back dismisses contextual action bars, and removes the highlight from the selected items</li>
-<li>Back hides the onscreen keyboard (IME)</li>
-</ul>
-<h2 id="within-app">Navigation Within Your App</h2>
-
-<h4>Navigating to screens with multiple entry points</h4>
-<p>Sometimes a screen doesn't have a strict position within the app's hierarchy, and can be reached
-from multiple entry points&mdash;e.g., a settings screen which can be navigated to from any screen
-in your app. In this case, the Up button should choose to return to the referring screen, behaving
-identically to Back.</p>
-<h4>Changing view within a screen</h4>
-<p>Changing view options for a screen does not change the behavior of Up or Back: the screen is still
-in the same place within the app's hierarchy, and no new navigation history is created.</p>
-<p>Examples of such view changes are:</p>
-<ul>
-<li>Switching views using tabs and/or left-and-right swipes</li>
-<li>Switching views using a dropdown (aka collapsed tabs)</li>
-<li>Filtering a list</li>
-<li>Sorting a list</li>
-<li>Changing display characteristics (e.g. zooming)</li>
-</ul>
-<h4>Navigating between sibling screens</h4>
-<p>When your app supports navigation from a list of items to a detail view of one of those items, it's
-often desirable to support direction navigation from that item to another one which precedes or
-follows it in the list. For example, in Gmail, it's easy to swipe left or right from a conversation
-to view a newer or older one in the same Inbox. Just as when changing view within a screen, such
-navigation does not change the behavior of Up or Back.</p>
-
-<img src="../static/content/navigation_between_siblings_gmail.png">
-
-<p>However, a notable exception to this occurs when browsing between "related" detail views not tied
-together by the referring list&mdash;for example, when browsing in the Market between apps from
-the same developer, or albums by the same artist. In these cases, following each link does create
-history, causing the Back button to step through each screen of related content which has been
-viewed. Up should continue to bypass these related screens and navigate to the most recently viewed
-container screen.</p>
-
-<img src="../static/content/navigation_between_siblings_market1.png">
-
-<p>You have the ability to make the Up behavior even smarter based on your knowledge of detail
-view. If we extend our Market sample from above, imagine the user has navigated from the last Book
-viewed to the details for the Movie adaptation. In that case, Up can return to a container (Movies)
-which the user had not previously navigated through.</p>
-
-<img src="../static/content/navigation_between_siblings_market2.png">
-
-<h2 id="from-outside">Navigation From Outside Your App</h2>
-
-<p>There are two categories of navigation from outside your app to screens deep within the app's
-hierarchy:</p>
-<ul>
-<li>App-to-app navigation, such as via intent completion.</li>
-<li>System-to-app navigation, such as via notifications and home screen widgets.</li>
-</ul>
-<p>Gmail provides examples of each of these. For app-to-app navigation, a "Share" intent goes directly
-to the compose screen. For system-to-app navigation, both a new message notification and a home
-screen widget can bypass the Inbox screen, taking the user directly to a conversation view.</p>
-<h4>App-to-app navigation</h4>
-<p>When navigating deep into your app's hierarchy directly from another app via an intent, Back will
-return to the referring app.</p>
-<p>The Up button is handled as follows:
-- If the destination screen is typically reached from one particular screen within your app, Up
-  should navigate to that screen.
-- Otherwise, Up should navigate to the topmost ("Home") screen of your app.</p>
-<p>For example, after choosing to share a book being viewed in Market, the user navigates directly to
-Gmail's compose screen. From there, Up returns to the Inbox (which happens to be both the
-typical referrer to compose, as well as the topmost screen of the app), while Back returns to
-Market.</p>
-
-<img src="../static/content/navigation_from_outside_up.png">
-
-<h4>System-to-app navigation</h4>
-<p>If your app was reached via the system mechanisms of notifications or home screen widgets, Up
-behaves as described for app-to-app navigation, above.</p>
-<p>For the Back key, you should make navigation more predictably by inserting into the task's back
-stack the complete upward navigation path to the app's topmost screen. This way, a user who has
-forgotten how they entered your app can safely navigate to the app's topmost screen before exiting
-it.</p>
-<p>For example, Gmail's Home screen widget has a button for diving directly to its compose screen.
-After following that path, the Back key first returns to the Inbox, and from there continues to
-Home.</p>
-
-<img src="../static/content/navigation_from_outside_back.png">
-
-
-
-
-
-          
-          <div class="layout-content-row content-footer">
-            <div class="paging-links layout-content-col span-9">&nbsp;</div>
-            <div class="paging-links layout-content-col span-4">
-              <a href="#" class="prev-page-link">Previous</a>
-              <a href="#" class="next-page-link">Next</a>
-            </div>
-          </div>
-          
-        </div>
-
-      </div>
-
-      <div id="page-footer">
-
-        <p id="copyright">
-          Except as noted, this content is licensed under
-          <a href="http://creativecommons.org/licenses/by/2.5/">
-          Creative Commons Attribution 2.5</a>.<br>
-          For details and restrictions, see the
-          <a href="http://developer.android.com/license.html">Content License</a>.
-        </p>
-
-        <p>
-          <a href="http://www.android.com/terms.html">Site Terms of Service</a> &ndash;
-          <a href="http://www.android.com/privacy.html">Privacy Policy</a> &ndash;
-          <a href="http://www.android.com/branding.html">Brand Guidelines</a>
-        </p>
-
-      </div>
-    </div>
-
-    <script src="../static/jquery-1.6.2.min.js"></script>
-    <script>
-    var SITE_ROOT = '../';
-    </script>
-    <script src="../static/default.js"></script>
-
-
-    <script type="text/javascript">
-    var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
-    document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
-    </script>
-    <script type="text/javascript">
-    var pageTracker = _gat._getTracker("UA-5831155-1");
-    pageTracker._trackPageview();
-    </script>
-  </body>
-</html>
diff --git a/docs/html/design/patterns/navigation.jd b/docs/html/design/patterns/navigation.jd
new file mode 100644
index 0000000..d35cd82
--- /dev/null
+++ b/docs/html/design/patterns/navigation.jd
@@ -0,0 +1,116 @@
+page.title=Navigation with Back and Up
+@jd:body
+
+<p>Consistent navigation is an essential component of the overall user experience. Few things frustrate
+users more than basic navigation that behaves in inconsistent and unexpected ways. Android 3.0
+introduced significant changes to the global navigation behavior. Thoughtfully following the
+guidelines for Back and Up will make your app's navigation predictable and reliable for your users.</p>
+<p>Android 2.3 and earlier relied upon the system <em>Back</em> button for supporting navigation within an
+app. With the introduction of action bars in Android 3.0, a second navigation mechanism appeared:
+the <em>Up</em> button, consisting of the app icon and a left-point caret.</p>
+
+<img src="{@docRoot}design/media/navigation_with_back_and_up.png">
+
+<h2 id="up-vs-back">Up vs. Back</h2>
+
+<p>The Up button is used to navigate within an application based on the hierarchical relationships
+between screens. For instance, if screen A displays a list of items, and selecting an item leads to
+screen B (which presents that item in more detail), then screen B should offer an Up button that
+returns to screen A.</p>
+<p>If a screen is the topmost one in an app (i.e. the home of the app), it should not present an Up
+button.</p>
+<p>The system Back key is used to navigate based on the history of screens the user has recently seen,
+in reverse chronological order&mdash;in effect, the temporal relationships between screens.</p>
+<p>When the previously viewed screen is also the hierarchical parent of the current screen, pressing
+the Back key will have the same result as pressing an Up button -- this is a common occurrence.
+However, unlike the Up button, which ensures the user remains within your app, the Back key can
+return the user to the Home screen, or even to a different application.</p>
+
+<img src="{@docRoot}design/media/navigation_up_vs_back_gmail.png">
+
+<p>The Back key also supports a few behaviors not directly tied to screen-to-screen navigation:</p>
+<ul>
+<li>Back dismisses floating windows (dialogs, popups)</li>
+<li>Back dismisses contextual action bars, and removes the highlight from the selected items</li>
+<li>Back hides the onscreen keyboard (IME)</li>
+</ul>
+<h2 id="within-app">Navigation Within Your App</h2>
+
+<h4>Navigating to screens with multiple entry points</h4>
+<p>Sometimes a screen doesn't have a strict position within the app's hierarchy, and can be reached
+from multiple entry points&mdash;e.g., a settings screen which can be navigated to from any screen
+in your app. In this case, the Up button should choose to return to the referring screen, behaving
+identically to Back.</p>
+<h4>Changing view within a screen</h4>
+<p>Changing view options for a screen does not change the behavior of Up or Back: the screen is still
+in the same place within the app's hierarchy, and no new navigation history is created.</p>
+<p>Examples of such view changes are:</p>
+<ul>
+<li>Switching views using tabs and/or left-and-right swipes</li>
+<li>Switching views using a dropdown (aka collapsed tabs)</li>
+<li>Filtering a list</li>
+<li>Sorting a list</li>
+<li>Changing display characteristics (e.g. zooming)</li>
+</ul>
+<h4>Navigating between sibling screens</h4>
+<p>When your app supports navigation from a list of items to a detail view of one of those items, it's
+often desirable to support direction navigation from that item to another one which precedes or
+follows it in the list. For example, in Gmail, it's easy to swipe left or right from a conversation
+to view a newer or older one in the same Inbox. Just as when changing view within a screen, such
+navigation does not change the behavior of Up or Back.</p>
+
+<img src="{@docRoot}design/media/navigation_between_siblings_gmail.png">
+
+<p>However, a notable exception to this occurs when browsing between "related" detail views not tied
+together by the referring list&mdash;for example, when browsing on Google Play between apps from
+the same developer, or albums by the same artist. In these cases, following each link does create
+history, causing the Back button to step through each screen of related content which has been
+viewed. Up should continue to bypass these related screens and navigate to the most recently viewed
+container screen.</p>
+
+<img src="{@docRoot}design/media/navigation_between_siblings_market1.png">
+
+<p>You have the ability to make the Up behavior even smarter based on your knowledge of detail
+view. If we extend our Google Play sample from above, imagine the user has navigated from the last Book
+viewed to the details for the Movie adaptation. In that case, Up can return to a container (Movies)
+which the user had not previously navigated through.</p>
+
+<img src="{@docRoot}design/media/navigation_between_siblings_market2.png">
+
+<h2 id="from-outside">Navigation From Outside Your App</h2>
+
+<p>There are two categories of navigation from outside your app to screens deep within the app's
+hierarchy:</p>
+<ul>
+<li>App-to-app navigation, such as via intent completion.</li>
+<li>System-to-app navigation, such as via notifications and home screen widgets.</li>
+</ul>
+<p>Gmail provides examples of each of these. For app-to-app navigation, a "Share" intent goes directly
+to the compose screen. For system-to-app navigation, both a new message notification and a home
+screen widget can bypass the Inbox screen, taking the user directly to a conversation view.</p>
+<h4>App-to-app navigation</h4>
+<p>When navigating deep into your app's hierarchy directly from another app via an intent, Back will
+return to the referring app.</p>
+<p>The Up button is handled as follows:
+- If the destination screen is typically reached from one particular screen within your app, Up
+  should navigate to that screen.
+- Otherwise, Up should navigate to the topmost ("Home") screen of your app.</p>
+<p>For example, after choosing to share a book being viewed on Google Play, the user navigates directly to
+Gmail's compose screen. From there, Up returns to the Inbox (which happens to be both the
+typical referrer to compose, as well as the topmost screen of the app), while Back returns to
+Google Play.</p>
+
+<img src="{@docRoot}design/media/navigation_from_outside_up.png">
+
+<h4>System-to-app navigation</h4>
+<p>If your app was reached via the system mechanisms of notifications or home screen widgets, Up
+behaves as described for app-to-app navigation, above.</p>
+<p>For the Back key, you should make navigation more predictably by inserting into the task's back
+stack the complete upward navigation path to the app's topmost screen. This way, a user who has
+forgotten how they entered your app can safely navigate to the app's topmost screen before exiting
+it.</p>
+<p>For example, Gmail's Home screen widget has a button for diving directly to its compose screen.
+After following that path, the Back key first returns to the Inbox, and from there continues to
+Home.</p>
+
+<img src="{@docRoot}design/media/navigation_from_outside_back.png">
diff --git a/docs/html/design/patterns/new-4-0.html b/docs/html/design/patterns/new-4-0.html
deleted file mode 100644
index 2e2cbc2..0000000
--- a/docs/html/design/patterns/new-4-0.html
+++ /dev/null
@@ -1,228 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-  <head>
-    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
-    <title>
-
-Android Design - New in Android 4.0
-    </title>
-    <link rel="shortcut icon" type="image/x-icon" href="/favicon.ico">
-    <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Roboto:regular,medium,thin,italic,mediumitalic">
-    <link rel="stylesheet" href="../static/yui-3.3.0-reset-min.css">
-    <link rel="stylesheet" href="../static/default.css">
-
-  </head>
-  <body>
-
-    <div id="page-container">
-
-      <div id="page-header"><a href="../index.html">Android Design</a></div>
-
-      <div id="main-row">
-
-        <ul id="nav">
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../index.html">Get Started</a></div>
-            <ul>
-              <li><a href="../get-started/creative-vision.html">Creative Vision</a></li>
-              <li><a href="../get-started/principles.html">Design Principles</a></li>
-              <li><a href="../get-started/ui-overview.html">UI Overview</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../style/index.html">Style</a></div>
-            <ul>
-              <li><a href="../style/devices-displays.html">Devices and Displays</a></li>
-              <li><a href="../style/themes.html">Themes</a></li>
-              <li><a href="../style/touch-feedback.html">Touch Feedback</a></li>
-              <li><a href="../style/metrics-grids.html">Metrics and Grids</a></li>
-              <li><a href="../style/typography.html">Typography</a></li>
-              <li><a href="../style/color.html">Color</a></li>
-              <li><a href="../style/iconography.html">Iconography</a></li>
-              <li><a href="../style/writing.html">Writing Style</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../patterns/index.html">Patterns</a></div>
-            <ul>
-              <li><a href="../patterns/new-4-0.html">New in Android 4.0</a></li>
-              <li><a href="../patterns/gestures.html">Gestures</a></li>
-              <li><a href="../patterns/app-structure.html">App Structure</a></li>
-              <li><a href="../patterns/navigation.html">Navigation</a></li>
-              <li><a href="../patterns/actionbar.html">Action Bar</a></li>
-              <li><a href="../patterns/multi-pane-layouts.html">Multi-pane Layouts</a></li>
-              <li><a href="../patterns/swipe-views.html">Swipe Views</a></li>
-              <li><a href="../patterns/selection.html">Selection</a></li>
-              <li><a href="../patterns/notifications.html">Notifications</a></li>
-              <li><a href="../patterns/compatibility.html">Compatibility</a></li>
-              <li><a href="../patterns/pure-android.html">Pure Android</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../building-blocks/index.html">Building Blocks</a></div>
-            <ul>
-              <li><a href="../building-blocks/tabs.html">Tabs</a></li>
-              <li><a href="../building-blocks/lists.html">Lists</a></li>
-              <li><a href="../building-blocks/grid-lists.html">Grid Lists</a></li>
-              <li><a href="../building-blocks/scrolling.html">Scrolling</a></li>
-              <li><a href="../building-blocks/spinners.html">Spinners</a></li>
-              <li><a href="../building-blocks/buttons.html">Buttons</a></li>
-              <li><a href="../building-blocks/text-fields.html">Text Fields</a></li>
-              <li><a href="../building-blocks/seek-bars.html">Seek Bars</a></li>
-              <li><a href="../building-blocks/progress.html">Progress &amp; Activity</a></li>
-              <li><a href="../building-blocks/switches.html">Switches</a></li>
-              <li><a href="../building-blocks/dialogs.html">Dialogs</a></li>
-              <li><a href="../building-blocks/pickers.html">Pickers</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header empty"><a href="../downloads/index.html">Downloads</a></div>
-          </li>
-
-          <li>
-            <div id="back-dac-section"><a href="../../index.html">Developers</a></div>
-          </li>
-
-        </ul>
-
-        <div id="content">
-
-          
-          <div class="layout-content-row content-header">
-            <div class="layout-content-col span-9">
-              <h2>New in Android 4.0</h2>
-            </div>
-            <div class="paging-links layout-content-col span-4">
-              <a href="#" class="prev-page-link">Previous</a>
-              <a href="#" class="next-page-link">Next</a>
-            </div>
-          </div>
-          
-
-          
-
-<div class="layout-content-row">
-  <div class="layout-content-col span-7">
-
-<h4>Navigation bar</h4>
-<p>Android 4.0 removes the need for traditional hardware keys on phones by replacing them with a
-virtual navigation bar that houses the Back, Home and Recents buttons. Read the
-<a href="../patterns/compatibility.html">Compatibility</a> pattern to learn how the OS adapts to
-phones with hardware buttons and how pre-Android 3.0 apps that rely on menu keys are supported.</p>
-
-  </div>
-  <div class="layout-content-col span-6">
-
-    <img src="../static/content/whats_new_nav_bar.png">
-
-  </div>
-</div>
-
-<div class="vspace size-2">&nbsp;</div>
-
-<div class="layout-content-row">
-  <div class="layout-content-col span-7">
-
-<h4>Action bar</h4>
-<p>The action bar is the most important structural element of an Android app. It provides consistent
-navigation across the platform and allows your app to surface actions.</p>
-
-  </div>
-  <div class="layout-content-col span-6">
-
-    <img src="../static/content/whats_new_action_bar.png">
-
-  </div>
-</div>
-
-<div class="vspace size-2">&nbsp;</div>
-
-<div class="layout-content-row">
-  <div class="layout-content-col span-7">
-
-<h4>Multi-pane layouts</h4>
-<p>Creating apps that scale well across different form factors and screen sizes is important in the
-Android world. Multi-pane layouts allow you to combine different activities that show separately on
-smaller devices into richer compound views for tablets.</p>
-
-  </div>
-  <div class="layout-content-col span-6">
-
-    <img src="../static/content/whats_new_multipanel.png">
-
-  </div>
-</div>
-
-<div class="vspace size-2">&nbsp;</div>
-
-<div class="layout-content-row">
-  <div class="layout-content-col span-7">
-
-<h4>Selection</h4>
-<p>The long press gesture which was traditionally used to show contextual actions for objects is now
-used for data selection. When selecting data, contextual action bars allow you to surface actions.</p>
-
-  </div>
-  <div class="layout-content-col span-6">
-
-    <img src="../static/content/whats_new_multiselect.png">
-
-  </div>
-</div>
-
-
-
-          
-          <div class="layout-content-row content-footer">
-            <div class="paging-links layout-content-col span-9">&nbsp;</div>
-            <div class="paging-links layout-content-col span-4">
-              <a href="#" class="prev-page-link">Previous</a>
-              <a href="#" class="next-page-link">Next</a>
-            </div>
-          </div>
-          
-        </div>
-
-      </div>
-
-      <div id="page-footer">
-
-        <p id="copyright">
-          Except as noted, this content is licensed under
-          <a href="http://creativecommons.org/licenses/by/2.5/">
-          Creative Commons Attribution 2.5</a>.<br>
-          For details and restrictions, see the
-          <a href="http://developer.android.com/license.html">Content License</a>.
-        </p>
-
-        <p>
-          <a href="http://www.android.com/terms.html">Site Terms of Service</a> &ndash;
-          <a href="http://www.android.com/privacy.html">Privacy Policy</a> &ndash;
-          <a href="http://www.android.com/branding.html">Brand Guidelines</a>
-        </p>
-
-      </div>
-    </div>
-
-    <script src="../static/jquery-1.6.2.min.js"></script>
-    <script>
-    var SITE_ROOT = '../';
-    </script>
-    <script src="../static/default.js"></script>
-
-
-    <script type="text/javascript">
-    var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
-    document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
-    </script>
-    <script type="text/javascript">
-    var pageTracker = _gat._getTracker("UA-5831155-1");
-    pageTracker._trackPageview();
-    </script>
-  </body>
-</html>
diff --git a/docs/html/design/patterns/new-4-0.jd b/docs/html/design/patterns/new-4-0.jd
new file mode 100644
index 0000000..91ebba7
--- /dev/null
+++ b/docs/html/design/patterns/new-4-0.jd
@@ -0,0 +1,71 @@
+page.title=New in Android 4.0
+@jd:body
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-7">
+
+<h4>Navigation bar</h4>
+<p>Android 4.0 removes the need for traditional hardware keys on phones by replacing them with a
+virtual navigation bar that houses the Back, Home and Recents buttons. Read the
+<a href="{@docRoot}design/patterns/compatibility.html">Compatibility</a> pattern to learn how the OS adapts to
+phones with hardware buttons and how pre-Android 3.0 apps that rely on menu keys are supported.</p>
+
+  </div>
+  <div class="layout-content-col span-6">
+
+    <img src="{@docRoot}design/media/whats_new_nav_bar.png">
+
+  </div>
+</div>
+
+<div class="vspace size-2">&nbsp;</div>
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-7">
+
+<h4>Action bar</h4>
+<p>The action bar is the most important structural element of an Android app. It provides consistent
+navigation across the platform and allows your app to surface actions.</p>
+
+  </div>
+  <div class="layout-content-col span-6">
+
+    <img src="{@docRoot}design/media/whats_new_action_bar.png">
+
+  </div>
+</div>
+
+<div class="vspace size-2">&nbsp;</div>
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-7">
+
+<h4>Multi-pane layouts</h4>
+<p>Creating apps that scale well across different form factors and screen sizes is important in the
+Android world. Multi-pane layouts allow you to combine different activities that show separately on
+smaller devices into richer compound views for tablets.</p>
+
+  </div>
+  <div class="layout-content-col span-6">
+
+    <img src="{@docRoot}design/media/whats_new_multipanel.png">
+
+  </div>
+</div>
+
+<div class="vspace size-2">&nbsp;</div>
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-7">
+
+<h4>Selection</h4>
+<p>The long press gesture which was traditionally used to show contextual actions for objects is now
+used for data selection. When selecting data, contextual action bars allow you to surface actions.</p>
+
+  </div>
+  <div class="layout-content-col span-6">
+
+    <img src="{@docRoot}design/media/whats_new_multiselect.png">
+
+  </div>
+</div>
diff --git a/docs/html/design/patterns/notifications.html b/docs/html/design/patterns/notifications.html
deleted file mode 100644
index 99af418..0000000
--- a/docs/html/design/patterns/notifications.html
+++ /dev/null
@@ -1,394 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-  <head>
-    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
-    <title>
-
-Android Design - Notifications
-    </title>
-    <link rel="shortcut icon" type="image/x-icon" href="/favicon.ico">
-    <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Roboto:regular,medium,thin,italic,mediumitalic">
-    <link rel="stylesheet" href="../static/yui-3.3.0-reset-min.css">
-    <link rel="stylesheet" href="../static/default.css">
-
-  </head>
-  <body>
-
-    <div id="page-container">
-
-      <div id="page-header"><a href="../index.html">Android Design</a></div>
-
-      <div id="main-row">
-
-        <ul id="nav">
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../index.html">Get Started</a></div>
-            <ul>
-              <li><a href="../get-started/creative-vision.html">Creative Vision</a></li>
-              <li><a href="../get-started/principles.html">Design Principles</a></li>
-              <li><a href="../get-started/ui-overview.html">UI Overview</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../style/index.html">Style</a></div>
-            <ul>
-              <li><a href="../style/devices-displays.html">Devices and Displays</a></li>
-              <li><a href="../style/themes.html">Themes</a></li>
-              <li><a href="../style/touch-feedback.html">Touch Feedback</a></li>
-              <li><a href="../style/metrics-grids.html">Metrics and Grids</a></li>
-              <li><a href="../style/typography.html">Typography</a></li>
-              <li><a href="../style/color.html">Color</a></li>
-              <li><a href="../style/iconography.html">Iconography</a></li>
-              <li><a href="../style/writing.html">Writing Style</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../patterns/index.html">Patterns</a></div>
-            <ul>
-              <li><a href="../patterns/new-4-0.html">New in Android 4.0</a></li>
-              <li><a href="../patterns/gestures.html">Gestures</a></li>
-              <li><a href="../patterns/app-structure.html">App Structure</a></li>
-              <li><a href="../patterns/navigation.html">Navigation</a></li>
-              <li><a href="../patterns/actionbar.html">Action Bar</a></li>
-              <li><a href="../patterns/multi-pane-layouts.html">Multi-pane Layouts</a></li>
-              <li><a href="../patterns/swipe-views.html">Swipe Views</a></li>
-              <li><a href="../patterns/selection.html">Selection</a></li>
-              <li><a href="../patterns/notifications.html">Notifications</a></li>
-              <li><a href="../patterns/compatibility.html">Compatibility</a></li>
-              <li><a href="../patterns/pure-android.html">Pure Android</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../building-blocks/index.html">Building Blocks</a></div>
-            <ul>
-              <li><a href="../building-blocks/tabs.html">Tabs</a></li>
-              <li><a href="../building-blocks/lists.html">Lists</a></li>
-              <li><a href="../building-blocks/grid-lists.html">Grid Lists</a></li>
-              <li><a href="../building-blocks/scrolling.html">Scrolling</a></li>
-              <li><a href="../building-blocks/spinners.html">Spinners</a></li>
-              <li><a href="../building-blocks/buttons.html">Buttons</a></li>
-              <li><a href="../building-blocks/text-fields.html">Text Fields</a></li>
-              <li><a href="../building-blocks/seek-bars.html">Seek Bars</a></li>
-              <li><a href="../building-blocks/progress.html">Progress &amp; Activity</a></li>
-              <li><a href="../building-blocks/switches.html">Switches</a></li>
-              <li><a href="../building-blocks/dialogs.html">Dialogs</a></li>
-              <li><a href="../building-blocks/pickers.html">Pickers</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header empty"><a href="../downloads/index.html">Downloads</a></div>
-          </li>
-
-          <li>
-            <div id="back-dac-section"><a href="../../index.html">Developers</a></div>
-          </li>
-
-        </ul>
-
-        <div id="content">
-
-          
-          <div class="layout-content-row content-header">
-            <div class="layout-content-col span-9">
-              <h2>Notifications</h2>
-            </div>
-            <div class="paging-links layout-content-col span-4">
-              <a href="#" class="prev-page-link">Previous</a>
-              <a href="#" class="next-page-link">Next</a>
-            </div>
-          </div>
-          
-
-          
-
-<p>The notification system allows your app to keep the user informed about important events, such as
-new messages in a chat app or a calendar event.</p>
-<p>To create an app that feels streamlined, pleasant, and respectful, it is important to design your
-notifications carefully. Notifications embody your app's voice, and contribute to your app's
-personality. Unwanted or unimportant notifications can annoy the user, so use them judiciously.</p>
-<h4>When to display a notification</h4>
-<p>To create an application that people love, it's important to recognize that the user's attention and
-focus is a resource that must be protected. To use an analogy that might resonate with software
-developers, the user is not a method that can be invoked to return a value.  The user's focus is a
-resource more akin to a thread, and creating a notification momentarily blocks the user thread as
-they process and then dismiss the interruptive notification.</p>
-<p>Android's notification system has been designed to quickly inform users of events while they focus
-on a task, but it is nonetheless still important to be conscientious when deciding to create a
-notification.</p>
-<p>While well behaved apps generally only speak when spoken to, there are some limited cases where an
-app actually should interrupt the user with an unprompted notification.</p>
-<p>Notifications should be used primarily for <strong>time sensitive events</strong>, and especially if these
-synchronous events <strong>involve other people</strong>. For instance, an incoming chat is a real time and
-synchronous form of communication: there is another user actively waiting on you to respond.
-Calendar events are another good example of when to use a notification and grab the user's
-attention, because the event is imminent, and calendar events often involve other people.</p>
-
-<img src="../static/content/notifications_pattern_real_time_people.png">
-
-<div class="vspace size-2">&nbsp;</div>
-
-<div class="layout-content-row">
-  <div class="layout-content-col span-7">
-
-<h4>When not to display a notification</h4>
-<p>There are however many other cases where notifications should not be used:</p>
-<ul>
-<li>
-<p>Don't notify the user of information that is not directed specifically at them, or information
-that is not truly time sensitive.  For instance the asynchronous and undirected updates flowing
-through a social network do not warrant a real time interruption.</p>
-</li>
-<li>
-<p>Don't create a notification if the relevant new information is currently on screen. Instead, use
-the UI of the application itself to notify the user of new information directly in context. For
-instance, a chat application should not create system notifications while the user is actively
-chatting with another user.</p>
-</li>
-<li>
-<p>Don't interrupt the user for low level technical operations, like saving or syncing information,
-or updating an application, if it is possible for the system to simply take care of itself without
-involving the user.</p>
-</li>
-<li>
-<p>Don't interrupt the user to inform them of an error if it is possible for the application to
-quickly recover from the error on its own without the user taking any action.</p>
-</li>
-<li>
-<p>Don't use notifications for services that the user cannot manually start or stop.</p>
-</li>
-<li>
-<p>Don't create superfluous notifications just to get your brand in front of users. Such
-notifications will only frustrate and likely alienate your audience. The best way to provide the
-user with a small amount of updated information and to keep them engaged with your application is to
-develop a widget that they can choose to place on their home screen.</p>
-</li>
-</ul>
-
-  </div>
-  <div class="layout-content-col span-6">
-
-    <img src="../static/content/notifications_pattern_social_fail.png">
-
-  </div>
-</div>
-
-<h2 id="design-guidelines">Design Guidelines</h2>
-
-<div class="layout-content-row">
-  <div class="layout-content-col span-6">
-
-    <img src="../static/content/notifications_pattern_anatomy.png">
-
-  </div>
-  <div class="layout-content-col span-6">
-
-<h4>Make it personal</h4>
-<p>For notifications of items sent by another user (such as a message or status update), include that
-person's image.</p>
-<p>Remember to include the app icon as a secondary icon in the notification, so that the user can
-still identify which app posted it.</p>    
-
-  </div>
-</div>
-
-<h4>Navigate to the right place</h4>
-<p>When the user touches a notification, be open your app to the place where the user can consume and
-act upon the data referenced in the notification. In most cases this will be the detail view of a
-single data item (e.g. a message), but it might also be a summary view if the notification is
-stacked (see <em>Stacked notifications</em> below) and references multiple items. If in any of those cases
-the user is taken to a hierarchy level below your app's top-level, insert navigation into your app's
-back stack to allow them to navigate to your app's top level using the system back key. For more
-information, see the chapter on <em>System-to-app navigation</em> in the
-<a href="../patterns/navigation.html">Navigation</a> design pattern.</p>
-<h4>Timestamps for time sensitive events</h4>
-<p>By default, standard Android notifications include a timestamp in the upper right corner. Consider
-whether the timestamp is valuable in the context of your notification. If the timestamp is not
-valuable, consider if the event is important enough to warrant grabbing the user's attention with a
-notification. If the notification is important enough, decide if you would like to opt out of
-displaying the timestamp.</p>
-<p>Include a timestamp if the user likely needs to know how long ago the notification occurred. Good
-candidates for timestamps include communication notifications (email, messaging, chat, voicemail)
-where the user may need the timestamp information to understand the context of a message or to
-tailor a response.</p>
-<h4>Stack your notifications</h4>
-<p>If your app creates a notification while another of the same type is still pending, avoid creating
-an altogether new notification object. Instead, stack the notification.</p>
-<p>A stacked notification builds a summary description and allows the user to understand how many
-notifications of a particular kind are pending.</p>
-<p><strong>Don't</strong>:</p>
-
-<img src="../static/content/notifications_pattern_additional_fail.png">
-
-<p><strong>Do</strong>:</p>
-
-<img src="../static/content/notifications_pattern_additional_win.png">
-
-<p>If you keep the summary and detail information on different screens, a stacked notification may need
-to open to a different place in the app than a single notification.</p>
-<p>For example, a single email notification should always open to the content of the email, whereas a
-stacked email notification opens to the Inbox view.</p>
-<h4>Clean up after yourself</h4>
-<p>Just like calendar events, some notifications alert the user to an event that happens at a
-particular point in time. After that moment has passed, the notification is likely not important to
-the user anymore, and you should consider removing it automatically.  The same is true for active
-chat conversations or voicemail messages the user has listened to, users should not have to manually
-dismiss notifications independently from taking action on them.</p>
-
-<div class="vspace size-1">&nbsp;</div>
-
-<div class="layout-content-row">
-  <div class="layout-content-col span-7">
-
-<h4>Provide a peek into your notification</h4>
-<p>You can provide a short preview of your notification's content by providing optional ticker text.
-The ticker text is shown for a short amount of time when the notification enters the system and then
-hides automatically.</p>
-
-  </div>
-  <div class="layout-content-col span-6">
-
-    <img src="../static/content/notifications_pattern_phone_ticker.png">
-
-  </div>
-</div>
-
-<h4>Make notifications optional</h4>
-<p>Users should always be in control of notifications. Allow the user to silence the notifications from
-your app by adding a notification settings item to your application settings.</p>
-<h4>Use distinct icons</h4>
-<p>By glancing at the notification area, the user should be able to discern what notification types are
-currently pending.</p>
-<p><strong>Do</strong>:</p>
-<ul>
-<li>Look at the notification icons the Android apps already provide and create notification icons for
-  your app that are sufficiently distinct in appearance.</li>
-</ul>
-<p><strong>Don't</strong>:</p>
-<ul>
-<li>Use color to distinguish your app from others. Notification icons should generally be monochrome.</li>
-</ul>
-
-<h2 id="interacting-with-notifications">Interacting With Notifications</h2>
-
-<div class="layout-content-row">
-  <div class="layout-content-col span-6">
-
-    <img src="../static/content/notifications_pattern_phone_icons.png">
-
-  </div>
-  <div class="layout-content-col span-6">
-
-<p>Notifications are indicated by icons in the notification area and can be accessed by opening the
-notification drawer.</p>
-<p>Inside the drawer, notifications are chronologically sorted with the latest one on top. Touching a
-notification opens the associated app to detailed content matching the notification. Swiping left or
-right on a notification removes it from the drawer.</p>
-
-  </div>
-</div>
-
-<div class="layout-content-row">
-  <div class="layout-content-col span-6">
-
-<p>On tablets, the notification area is integrated with the system bar at the bottom of the screen. The
-notification drawer is opened by touching anywhere inside the notification area.</p>
-
-  </div>
-  <div class="layout-content-col span-6">
-
-    <img src="../static/content/notifications_pattern_tablet.png">
-
-  </div>
-</div>
-
-<div class="layout-content-row">
-  <div class="layout-content-col span-6">
-
-    <img src="../static/content/notifications_pattern_ongoing_music.png">
-
-  </div>
-  <div class="layout-content-col span-6">
-
-<h4>Ongoing notifications</h4>
-<p>Ongoing notifications keep users informed about an ongoing process in the background. For example,
-music players announce the currently playing track in the notification system and continue to do so
-until the user stops the playback. They can also be used to show the user feedback for longer tasks
-like downloading a file, or encoding a video. Ongoing notifications cannot be manually removed from
-the notification drawer.</p>
-
-  </div>
-</div>
-
-<div class="layout-content-row">
-  <div class="layout-content-col span-12">
-
-<h4>Dialogs and toasts are for feedback not notification</h4>
-<p>Your app should not create a dialog or toast if it is not currently on screen. Dialogs and Toasts
-should only be displayed as the immediate response to the user taking an action inside of your app.
-For instance, dialogs can be used to confirm that the user understands the severity of an action,
-and toasts can echo back that an action has been successfully taken.</p>
-
-  </div>
-</div>
-
-<div class="vspace size-1">&nbsp;</div>
-
-<img src="../static/content/notifications_pattern_dialog_toast.png">
-
-
-
-
-          
-          <div class="layout-content-row content-footer">
-            <div class="paging-links layout-content-col span-9">&nbsp;</div>
-            <div class="paging-links layout-content-col span-4">
-              <a href="#" class="prev-page-link">Previous</a>
-              <a href="#" class="next-page-link">Next</a>
-            </div>
-          </div>
-          
-        </div>
-
-      </div>
-
-      <div id="page-footer">
-
-        <p id="copyright">
-          Except as noted, this content is licensed under
-          <a href="http://creativecommons.org/licenses/by/2.5/">
-          Creative Commons Attribution 2.5</a>.<br>
-          For details and restrictions, see the
-          <a href="http://developer.android.com/license.html">Content License</a>.
-        </p>
-
-        <p>
-          <a href="http://www.android.com/terms.html">Site Terms of Service</a> &ndash;
-          <a href="http://www.android.com/privacy.html">Privacy Policy</a> &ndash;
-          <a href="http://www.android.com/branding.html">Brand Guidelines</a>
-        </p>
-
-      </div>
-    </div>
-
-    <script src="../static/jquery-1.6.2.min.js"></script>
-    <script>
-    var SITE_ROOT = '../';
-    </script>
-    <script src="../static/default.js"></script>
-
-
-    <script type="text/javascript">
-    var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
-    document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
-    </script>
-    <script type="text/javascript">
-    var pageTracker = _gat._getTracker("UA-5831155-1");
-    pageTracker._trackPageview();
-    </script>
-  </body>
-</html>
diff --git a/docs/html/design/patterns/notifications.jd b/docs/html/design/patterns/notifications.jd
new file mode 100644
index 0000000..ad88a01
--- /dev/null
+++ b/docs/html/design/patterns/notifications.jd
@@ -0,0 +1,236 @@
+page.title=Notifications
+@jd:body
+
+<p>The notification system allows your app to keep the user informed about important events, such as
+new messages in a chat app or a calendar event.</p>
+<p>To create an app that feels streamlined, pleasant, and respectful, it is important to design your
+notifications carefully. Notifications embody your app's voice, and contribute to your app's
+personality. Unwanted or unimportant notifications can annoy the user, so use them judiciously.</p>
+<h4>When to display a notification</h4>
+<p>To create an application that people love, it's important to recognize that the user's attention and
+focus is a resource that must be protected. To use an analogy that might resonate with software
+developers, the user is not a method that can be invoked to return a value.  The user's focus is a
+resource more akin to a thread, and creating a notification momentarily blocks the user thread as
+they process and then dismiss the interruptive notification.</p>
+<p>Android's notification system has been designed to quickly inform users of events while they focus
+on a task, but it is nonetheless still important to be conscientious when deciding to create a
+notification.</p>
+<p>While well behaved apps generally only speak when spoken to, there are some limited cases where an
+app actually should interrupt the user with an unprompted notification.</p>
+<p>Notifications should be used primarily for <strong>time sensitive events</strong>, and especially if these
+synchronous events <strong>involve other people</strong>. For instance, an incoming chat is a real time and
+synchronous form of communication: there is another user actively waiting on you to respond.
+Calendar events are another good example of when to use a notification and grab the user's
+attention, because the event is imminent, and calendar events often involve other people.</p>
+
+<img src="{@docRoot}design/media/notifications_pattern_real_time_people.png">
+
+<div class="vspace size-2">&nbsp;</div>
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-7">
+
+<h4>When not to display a notification</h4>
+<p>There are however many other cases where notifications should not be used:</p>
+<ul>
+<li>
+<p>Don't notify the user of information that is not directed specifically at them, or information
+that is not truly time sensitive.  For instance the asynchronous and undirected updates flowing
+through a social network do not warrant a real time interruption.</p>
+</li>
+<li>
+<p>Don't create a notification if the relevant new information is currently on screen. Instead, use
+the UI of the application itself to notify the user of new information directly in context. For
+instance, a chat application should not create system notifications while the user is actively
+chatting with another user.</p>
+</li>
+<li>
+<p>Don't interrupt the user for low level technical operations, like saving or syncing information,
+or updating an application, if it is possible for the system to simply take care of itself without
+involving the user.</p>
+</li>
+<li>
+<p>Don't interrupt the user to inform them of an error if it is possible for the application to
+quickly recover from the error on its own without the user taking any action.</p>
+</li>
+<li>
+<p>Don't use notifications for services that the user cannot manually start or stop.</p>
+</li>
+<li>
+<p>Don't create superfluous notifications just to get your brand in front of users. Such
+notifications will only frustrate and likely alienate your audience. The best way to provide the
+user with a small amount of updated information and to keep them engaged with your application is to
+develop a widget that they can choose to place on their home screen.</p>
+</li>
+</ul>
+
+  </div>
+  <div class="layout-content-col span-6">
+
+    <img src="{@docRoot}design/media/notifications_pattern_social_fail.png">
+
+  </div>
+</div>
+
+<h2 id="design-guidelines">Design Guidelines</h2>
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-6">
+
+    <img src="{@docRoot}design/media/notifications_pattern_anatomy.png">
+
+  </div>
+  <div class="layout-content-col span-6">
+
+<h4>Make it personal</h4>
+<p>For notifications of items sent by another user (such as a message or status update), include that
+person's image.</p>
+<p>Remember to include the app icon as a secondary icon in the notification, so that the user can
+still identify which app posted it.</p>    
+
+  </div>
+</div>
+
+<h4>Navigate to the right place</h4>
+<p>When the user touches a notification, be open your app to the place where the user can consume and
+act upon the data referenced in the notification. In most cases this will be the detail view of a
+single data item (e.g. a message), but it might also be a summary view if the notification is
+stacked (see <em>Stacked notifications</em> below) and references multiple items. If in any of those cases
+the user is taken to a hierarchy level below your app's top-level, insert navigation into your app's
+back stack to allow them to navigate to your app's top level using the system back key. For more
+information, see the chapter on <em>System-to-app navigation</em> in the
+<a href="{@docRoot}design/patterns/navigation.html">Navigation</a> design pattern.</p>
+<h4>Timestamps for time sensitive events</h4>
+<p>By default, standard Android notifications include a timestamp in the upper right corner. Consider
+whether the timestamp is valuable in the context of your notification. If the timestamp is not
+valuable, consider if the event is important enough to warrant grabbing the user's attention with a
+notification. If the notification is important enough, decide if you would like to opt out of
+displaying the timestamp.</p>
+<p>Include a timestamp if the user likely needs to know how long ago the notification occurred. Good
+candidates for timestamps include communication notifications (email, messaging, chat, voicemail)
+where the user may need the timestamp information to understand the context of a message or to
+tailor a response.</p>
+<h4>Stack your notifications</h4>
+<p>If your app creates a notification while another of the same type is still pending, avoid creating
+an altogether new notification object. Instead, stack the notification.</p>
+<p>A stacked notification builds a summary description and allows the user to understand how many
+notifications of a particular kind are pending.</p>
+<p><strong>Don't</strong>:</p>
+
+<img src="{@docRoot}design/media/notifications_pattern_additional_fail.png">
+
+<p><strong>Do</strong>:</p>
+
+<img src="{@docRoot}design/media/notifications_pattern_additional_win.png">
+
+<p>If you keep the summary and detail information on different screens, a stacked notification may need
+to open to a different place in the app than a single notification.</p>
+<p>For example, a single email notification should always open to the content of the email, whereas a
+stacked email notification opens to the Inbox view.</p>
+<h4>Clean up after yourself</h4>
+<p>Just like calendar events, some notifications alert the user to an event that happens at a
+particular point in time. After that moment has passed, the notification is likely not important to
+the user anymore, and you should consider removing it automatically.  The same is true for active
+chat conversations or voicemail messages the user has listened to, users should not have to manually
+dismiss notifications independently from taking action on them.</p>
+
+<div class="vspace size-1">&nbsp;</div>
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-7">
+
+<h4>Provide a peek into your notification</h4>
+<p>You can provide a short preview of your notification's content by providing optional ticker text.
+The ticker text is shown for a short amount of time when the notification enters the system and then
+hides automatically.</p>
+
+  </div>
+  <div class="layout-content-col span-6">
+
+    <img src="{@docRoot}design/media/notifications_pattern_phone_ticker.png">
+
+  </div>
+</div>
+
+<h4>Make notifications optional</h4>
+<p>Users should always be in control of notifications. Allow the user to silence the notifications from
+your app by adding a notification settings item to your application settings.</p>
+<h4>Use distinct icons</h4>
+<p>By glancing at the notification area, the user should be able to discern what notification types are
+currently pending.</p>
+<p><strong>Do</strong>:</p>
+<ul>
+<li>Look at the notification icons the Android apps already provide and create notification icons for
+  your app that are sufficiently distinct in appearance.</li>
+</ul>
+<p><strong>Don't</strong>:</p>
+<ul>
+<li>Use color to distinguish your app from others. Notification icons should generally be monochrome.</li>
+</ul>
+
+<h2 id="interacting-with-notifications">Interacting With Notifications</h2>
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-6">
+
+    <img src="{@docRoot}design/media/notifications_pattern_phone_icons.png">
+
+  </div>
+  <div class="layout-content-col span-6">
+
+<p>Notifications are indicated by icons in the notification area and can be accessed by opening the
+notification drawer.</p>
+<p>Inside the drawer, notifications are chronologically sorted with the latest one on top. Touching a
+notification opens the associated app to detailed content matching the notification. Swiping left or
+right on a notification removes it from the drawer.</p>
+
+  </div>
+</div>
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-6">
+
+<p>On tablets, the notification area is integrated with the system bar at the bottom of the screen. The
+notification drawer is opened by touching anywhere inside the notification area.</p>
+
+  </div>
+  <div class="layout-content-col span-6">
+
+    <img src="{@docRoot}design/media/notifications_pattern_tablet.png">
+
+  </div>
+</div>
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-6">
+
+    <img src="{@docRoot}design/media/notifications_pattern_ongoing_music.png">
+
+  </div>
+  <div class="layout-content-col span-6">
+
+<h4>Ongoing notifications</h4>
+<p>Ongoing notifications keep users informed about an ongoing process in the background. For example,
+music players announce the currently playing track in the notification system and continue to do so
+until the user stops the playback. They can also be used to show the user feedback for longer tasks
+like downloading a file, or encoding a video. Ongoing notifications cannot be manually removed from
+the notification drawer.</p>
+
+  </div>
+</div>
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-12">
+
+<h4>Dialogs and toasts are for feedback not notification</h4>
+<p>Your app should not create a dialog or toast if it is not currently on screen. Dialogs and Toasts
+should only be displayed as the immediate response to the user taking an action inside of your app.
+For instance, dialogs can be used to confirm that the user understands the severity of an action,
+and toasts can echo back that an action has been successfully taken.</p>
+
+  </div>
+</div>
+
+<div class="vspace size-1">&nbsp;</div>
+
+<img src="{@docRoot}design/media/notifications_pattern_dialog_toast.png">
diff --git a/docs/html/design/patterns/pure-android.html b/docs/html/design/patterns/pure-android.html
deleted file mode 100644
index f5a8042..0000000
--- a/docs/html/design/patterns/pure-android.html
+++ /dev/null
@@ -1,292 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-  <head>
-    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
-    <title>
-
-Android Design - Pure Android
-    </title>
-    <link rel="shortcut icon" type="image/x-icon" href="/favicon.ico">
-    <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Roboto:regular,medium,thin,italic,mediumitalic">
-    <link rel="stylesheet" href="../static/yui-3.3.0-reset-min.css">
-    <link rel="stylesheet" href="../static/default.css">
-
-  </head>
-  <body>
-
-    <div id="page-container">
-
-      <div id="page-header"><a href="../index.html">Android Design</a></div>
-
-      <div id="main-row">
-
-        <ul id="nav">
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../index.html">Get Started</a></div>
-            <ul>
-              <li><a href="../get-started/creative-vision.html">Creative Vision</a></li>
-              <li><a href="../get-started/principles.html">Design Principles</a></li>
-              <li><a href="../get-started/ui-overview.html">UI Overview</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../style/index.html">Style</a></div>
-            <ul>
-              <li><a href="../style/devices-displays.html">Devices and Displays</a></li>
-              <li><a href="../style/themes.html">Themes</a></li>
-              <li><a href="../style/touch-feedback.html">Touch Feedback</a></li>
-              <li><a href="../style/metrics-grids.html">Metrics and Grids</a></li>
-              <li><a href="../style/typography.html">Typography</a></li>
-              <li><a href="../style/color.html">Color</a></li>
-              <li><a href="../style/iconography.html">Iconography</a></li>
-              <li><a href="../style/writing.html">Writing Style</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../patterns/index.html">Patterns</a></div>
-            <ul>
-              <li><a href="../patterns/new-4-0.html">New in Android 4.0</a></li>
-              <li><a href="../patterns/gestures.html">Gestures</a></li>
-              <li><a href="../patterns/app-structure.html">App Structure</a></li>
-              <li><a href="../patterns/navigation.html">Navigation</a></li>
-              <li><a href="../patterns/actionbar.html">Action Bar</a></li>
-              <li><a href="../patterns/multi-pane-layouts.html">Multi-pane Layouts</a></li>
-              <li><a href="../patterns/swipe-views.html">Swipe Views</a></li>
-              <li><a href="../patterns/selection.html">Selection</a></li>
-              <li><a href="../patterns/notifications.html">Notifications</a></li>
-              <li><a href="../patterns/compatibility.html">Compatibility</a></li>
-              <li><a href="../patterns/pure-android.html">Pure Android</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../building-blocks/index.html">Building Blocks</a></div>
-            <ul>
-              <li><a href="../building-blocks/tabs.html">Tabs</a></li>
-              <li><a href="../building-blocks/lists.html">Lists</a></li>
-              <li><a href="../building-blocks/grid-lists.html">Grid Lists</a></li>
-              <li><a href="../building-blocks/scrolling.html">Scrolling</a></li>
-              <li><a href="../building-blocks/spinners.html">Spinners</a></li>
-              <li><a href="../building-blocks/buttons.html">Buttons</a></li>
-              <li><a href="../building-blocks/text-fields.html">Text Fields</a></li>
-              <li><a href="../building-blocks/seek-bars.html">Seek Bars</a></li>
-              <li><a href="../building-blocks/progress.html">Progress &amp; Activity</a></li>
-              <li><a href="../building-blocks/switches.html">Switches</a></li>
-              <li><a href="../building-blocks/dialogs.html">Dialogs</a></li>
-              <li><a href="../building-blocks/pickers.html">Pickers</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header empty"><a href="../downloads/index.html">Downloads</a></div>
-          </li>
-
-          <li>
-            <div id="back-dac-section"><a href="../../index.html">Developers</a></div>
-          </li>
-
-        </ul>
-
-        <div id="content">
-
-          
-          <div class="layout-content-row content-header">
-            <div class="layout-content-col span-9">
-              <h2>Pure Android</h2>
-            </div>
-            <div class="paging-links layout-content-col span-4">
-              <a href="#" class="prev-page-link">Previous</a>
-              <a href="#" class="next-page-link">Next</a>
-            </div>
-          </div>
-          
-
-          
-
-<p>Most developers want to distribute their apps on multiple platforms. As you plan your app for
-Android, keep in mind that different platforms play by different rules and conventions. Design
-decisions that make perfect sense on one platform will look and feel misplaced in the context of a
-different platform. While a "design once, ship anywhere" approach might save you time up-front, you
-run the very real risk of creating inconsistent apps that alienate users. Consider the following
-guidelines to avoid the most common traps and pitfalls.</p>
-
-<div class="vspace size-1">&nbsp;</div>
-
-<div class="layout-content-row">
-  <div class="layout-content-col span-5">
-
-<h4>Don't mimic UI elements from other platforms</h4>
-<p>Platforms typically provide a carefully designed set of UI elements that are themed in a very
-distinctive fashion. For example, some platforms advocate rounded corners for their buttons, others
-use gradients in their title bars. In some cases, elements may have the same purpose, but are
-designed to work a bit differently.</p>
-<p>As you build your app for Android, don't carry over themed UI elements from other platforms and
-don't mimic their specific behaviors. Review the <a href="../building-
-blocks/index.html">Building Blocks</a> section in this styleguide to learn about Android's most important UI elements
-and the way they look in the system default themes. Also examine Android's platform apps to get a
-sense of how elements are applied in the context of an app. If you want to customize the theme of UI
-elements, customize carefully according to your specific branding - and not according to the
-conventions of a different platform.</p>
-
-  </div>
-  <div class="layout-content-col span-8">
-
-    <img src="../static/content/migrating_ui_elements.png">
-    <div class="figure-caption">
-      Sampling of UI elements from Android, iOS and Windows Phone 7.
-    </div>
-
-  </div>
-</div>
-
-<div class="vspace size-2">&nbsp;</div>
-
-<div class="layout-content-row">
-  <div class="layout-content-col span-5">
-
-<h4>Don't carry over platform-specific icons</h4>
-<p>Platforms typically provide sets of icons for common functionality, such as sharing, creating a new
-document or deleting.</p>
-<p>As you are migrating your app to Android, please swap out platform-specific icons with their Android
-counterparts.</p>
-<p>You can find a wide variety of icons for use in your app in the Android SDK.</p>
-
-  </div>
-  <div class="layout-content-col span-8">
-
-    <img src="../static/content/migrating_icons.png">
-    <div class="figure-caption">
-      Sampling of icons from Android, iOS and Windows Phone 7.
-    </div>
-
-  </div>
-</div>
-
-<div class="vspace size-2">&nbsp;</div>
-
-<div class="layout-content-row">
-  <div class="layout-content-col span-5">
-
-<h4>Don't use bottom tab bars</h4>
-<p>Other platforms use the bottom tab bar to switch between the app's views. Per platform convention,
-Android's tabs for view control are shown in action bars at the top of the screen instead. In
-addition, Android apps may use a bottom bar to display actions on a split action bar.</p>
-<p>You should follow this guideline to create a consistent experience with other apps on the Android
-platform and to avoid confusion between actions and view switching on Android.</p>
-<p>For more information on how to properly use action bars for view control, see
-<a href="../patterns/actionbar.html">Action Bars</a>.</p>
-
-  </div>
-  <div class="layout-content-col span-8">
-
-    <img src="../static/content/migrating_ios_dialers.png">
-    <div class="figure-caption">
-      Android dialer with tabs in an action bar vs. bottom tabs in iOS.
-    </div>
-
-  </div>
-</div>
-
-<div class="layout-content-row">
-  <div class="layout-content-col span-5">
-
-<h4>Don't use labeled back buttons on action bars</h4>
-<p>Other platforms use an explicit back button with label to allow the user to navigate up the
-application's hierarchy. Instead, Android uses the main action bar's app icon for hierarchical
-navigation and the navigation bar's back button for temporal navigation. For more information,
-please review the <a href="../patterns/navigation.html">Navigation</a> pattern.</p>
-<p>Follow this guideline to provide a consistent navigation experience across the platform.</p>
-
-  </div>
-  <div class="layout-content-col span-8">
-
-    <img src="../static/content/migrating_ios_galleries.png">
-    <div class="figure-caption">
-      Android action bar with up caret vs. iOS labeled "Back" button.
-    </div>
-
-  </div>
-</div>
-
-<div class="layout-content-row">
-  <div class="layout-content-col span-5">
-
-<h4>Don't use right-pointing carets on line items</h4>
-<p>A common pattern on other platforms is the display of right-pointing carets on line items that allow
-the user to drill deeper into additional content.</p>
-<p>Android does not use such indicators on drill-down line items. Avoid them to stay consistent with
-the platform and in order to not have the user guess as to what the meaning of those carets may be.</p>
-
-  </div>
-  <div class="layout-content-col span-8">
-
-    <img src="../static/content/migrating_ios_settings.png">
-    <div class="figure-caption">
-      Android settings without right-pointing carets in line items vs. iOS settings.
-    </div>
-
-  </div>
-</div>
-
-<h2 id="device-independence">Device Independence</h2>
-
-<p>Remember that your app will run on a wide variety of different screen sizes. Create visual assets
-for different screen sizes and densities and make use of concepts such as multi-pane layouts to
-appropriately scale your UI on different device form factors.</p>
-<p>For more information, read <a href="../style/devices-displays.html">Devices and Displays</a> as
-well as <a href="../patterns/multi-pane-layouts.html">Multi-pane Layouts</a> in this design guide.</p>
-
-
-
-          
-          <div class="layout-content-row content-footer">
-            <div class="paging-links layout-content-col span-9">&nbsp;</div>
-            <div class="paging-links layout-content-col span-4">
-              <a href="#" class="prev-page-link">Previous</a>
-              <a href="#" class="next-page-link">Next</a>
-            </div>
-          </div>
-          
-        </div>
-
-      </div>
-
-      <div id="page-footer">
-
-        <p id="copyright">
-          Except as noted, this content is licensed under
-          <a href="http://creativecommons.org/licenses/by/2.5/">
-          Creative Commons Attribution 2.5</a>.<br>
-          For details and restrictions, see the
-          <a href="http://developer.android.com/license.html">Content License</a>.
-        </p>
-
-        <p>
-          <a href="http://www.android.com/terms.html">Site Terms of Service</a> &ndash;
-          <a href="http://www.android.com/privacy.html">Privacy Policy</a> &ndash;
-          <a href="http://www.android.com/branding.html">Brand Guidelines</a>
-        </p>
-
-      </div>
-    </div>
-
-    <script src="../static/jquery-1.6.2.min.js"></script>
-    <script>
-    var SITE_ROOT = '../';
-    </script>
-    <script src="../static/default.js"></script>
-
-
-    <script type="text/javascript">
-    var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
-    document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
-    </script>
-    <script type="text/javascript">
-    var pageTracker = _gat._getTracker("UA-5831155-1");
-    pageTracker._trackPageview();
-    </script>
-  </body>
-</html>
diff --git a/docs/html/design/patterns/pure-android.jd b/docs/html/design/patterns/pure-android.jd
new file mode 100644
index 0000000..8ed1347
--- /dev/null
+++ b/docs/html/design/patterns/pure-android.jd
@@ -0,0 +1,136 @@
+page.title=Pure Android
+@jd:body
+
+<p>Most developers want to distribute their apps on multiple platforms. As you plan your app for
+Android, keep in mind that different platforms play by different rules and conventions. Design
+decisions that make perfect sense on one platform will look and feel misplaced in the context of a
+different platform. While a "design once, ship anywhere" approach might save you time up-front, you
+run the very real risk of creating inconsistent apps that alienate users. Consider the following
+guidelines to avoid the most common traps and pitfalls.</p>
+
+<div class="vspace size-1">&nbsp;</div>
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-5">
+
+<h4>Don't mimic UI elements from other platforms</h4>
+<p>Platforms typically provide a carefully designed set of UI elements that are themed in a very
+distinctive fashion. For example, some platforms advocate rounded corners for their buttons, others
+use gradients in their title bars. In some cases, elements may have the same purpose, but are
+designed to work a bit differently.</p>
+<p>As you build your app for Android, don't carry over themed UI elements from other platforms and
+don't mimic their specific behaviors. Review the
+<a href="{@docRoot}design/building-blocks/index.html">Building Blocks</a>
+section in this styleguide to learn about Android's most important UI elements
+and the way they look in the system default themes. Also examine Android's platform apps to get a
+sense of how elements are applied in the context of an app. If you want to customize the theme of UI
+elements, customize carefully according to your specific branding - and not according to the
+conventions of a different platform.</p>
+
+  </div>
+  <div class="layout-content-col span-8">
+
+    <img src="{@docRoot}design/media/migrating_ui_elements.png">
+    <div class="figure-caption">
+      Sampling of UI elements from Android, iOS and Windows Phone 7.
+    </div>
+
+  </div>
+</div>
+
+<div class="vspace size-2">&nbsp;</div>
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-5">
+
+<h4>Don't carry over platform-specific icons</h4>
+<p>Platforms typically provide sets of icons for common functionality, such as sharing, creating a new
+document or deleting.</p>
+<p>As you are migrating your app to Android, please swap out platform-specific icons with their Android
+counterparts.</p>
+<p>You can find a wide variety of icons for use in your app in the Android SDK.</p>
+
+  </div>
+  <div class="layout-content-col span-8">
+
+    <img src="{@docRoot}design/media/migrating_icons.png">
+    <div class="figure-caption">
+      Sampling of icons from Android, iOS and Windows Phone 7.
+    </div>
+
+  </div>
+</div>
+
+<div class="vspace size-2">&nbsp;</div>
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-5">
+
+<h4>Don't use bottom tab bars</h4>
+<p>Other platforms use the bottom tab bar to switch between the app's views. Per platform convention,
+Android's tabs for view control are shown in action bars at the top of the screen instead. In
+addition, Android apps may use a bottom bar to display actions on a split action bar.</p>
+<p>You should follow this guideline to create a consistent experience with other apps on the Android
+platform and to avoid confusion between actions and view switching on Android.</p>
+<p>For more information on how to properly use action bars for view control, see
+<a href="{@docRoot}design/patterns/actionbar.html">Action Bars</a>.</p>
+
+  </div>
+  <div class="layout-content-col span-8">
+
+    <img src="{@docRoot}design/media/migrating_ios_dialers.png">
+    <div class="figure-caption">
+      Android dialer with tabs in an action bar vs. bottom tabs in iOS.
+    </div>
+
+  </div>
+</div>
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-5">
+
+<h4>Don't use labeled back buttons on action bars</h4>
+<p>Other platforms use an explicit back button with label to allow the user to navigate up the
+application's hierarchy. Instead, Android uses the main action bar's app icon for hierarchical
+navigation and the navigation bar's back button for temporal navigation. For more information,
+please review the <a href="{@docRoot}design/patterns/navigation.html">Navigation</a> pattern.</p>
+<p>Follow this guideline to provide a consistent navigation experience across the platform.</p>
+
+  </div>
+  <div class="layout-content-col span-8">
+
+    <img src="{@docRoot}design/media/migrating_ios_galleries.png">
+    <div class="figure-caption">
+      Android action bar with up caret vs. iOS labeled "Back" button.
+    </div>
+
+  </div>
+</div>
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-5">
+
+<h4>Don't use right-pointing carets on line items</h4>
+<p>A common pattern on other platforms is the display of right-pointing carets on line items that allow
+the user to drill deeper into additional content.</p>
+<p>Android does not use such indicators on drill-down line items. Avoid them to stay consistent with
+the platform and in order to not have the user guess as to what the meaning of those carets may be.</p>
+
+  </div>
+  <div class="layout-content-col span-8">
+
+    <img src="{@docRoot}design/media/migrating_ios_settings.png">
+    <div class="figure-caption">
+      Android settings without right-pointing carets in line items vs. iOS settings.
+    </div>
+
+  </div>
+</div>
+
+<h2 id="device-independence">Device Independence</h2>
+
+<p>Remember that your app will run on a wide variety of different screen sizes. Create visual assets
+for different screen sizes and densities and make use of concepts such as multi-pane layouts to
+appropriately scale your UI on different device form factors.</p>
+<p>For more information, read <a href="{@docRoot}design/style/devices-displays.html">Devices and Displays</a> as
+well as <a href="{@docRoot}design/patterns/multi-pane-layouts.html">Multi-pane Layouts</a> in this design guide.</p>
diff --git a/docs/html/design/patterns/selection.html b/docs/html/design/patterns/selection.html
deleted file mode 100644
index 44c6a84..0000000
--- a/docs/html/design/patterns/selection.html
+++ /dev/null
@@ -1,257 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-  <head>
-    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
-    <title>
-
-Android Design - Selection
-    </title>
-    <link rel="shortcut icon" type="image/x-icon" href="/favicon.ico">
-    <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Roboto:regular,medium,thin,italic,mediumitalic">
-    <link rel="stylesheet" href="../static/yui-3.3.0-reset-min.css">
-    <link rel="stylesheet" href="../static/default.css">
-
-  </head>
-  <body>
-
-    <div id="page-container">
-
-      <div id="page-header"><a href="../index.html">Android Design</a></div>
-
-      <div id="main-row">
-
-        <ul id="nav">
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../index.html">Get Started</a></div>
-            <ul>
-              <li><a href="../get-started/creative-vision.html">Creative Vision</a></li>
-              <li><a href="../get-started/principles.html">Design Principles</a></li>
-              <li><a href="../get-started/ui-overview.html">UI Overview</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../style/index.html">Style</a></div>
-            <ul>
-              <li><a href="../style/devices-displays.html">Devices and Displays</a></li>
-              <li><a href="../style/themes.html">Themes</a></li>
-              <li><a href="../style/touch-feedback.html">Touch Feedback</a></li>
-              <li><a href="../style/metrics-grids.html">Metrics and Grids</a></li>
-              <li><a href="../style/typography.html">Typography</a></li>
-              <li><a href="../style/color.html">Color</a></li>
-              <li><a href="../style/iconography.html">Iconography</a></li>
-              <li><a href="../style/writing.html">Writing Style</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../patterns/index.html">Patterns</a></div>
-            <ul>
-              <li><a href="../patterns/new-4-0.html">New in Android 4.0</a></li>
-              <li><a href="../patterns/gestures.html">Gestures</a></li>
-              <li><a href="../patterns/app-structure.html">App Structure</a></li>
-              <li><a href="../patterns/navigation.html">Navigation</a></li>
-              <li><a href="../patterns/actionbar.html">Action Bar</a></li>
-              <li><a href="../patterns/multi-pane-layouts.html">Multi-pane Layouts</a></li>
-              <li><a href="../patterns/swipe-views.html">Swipe Views</a></li>
-              <li><a href="../patterns/selection.html">Selection</a></li>
-              <li><a href="../patterns/notifications.html">Notifications</a></li>
-              <li><a href="../patterns/compatibility.html">Compatibility</a></li>
-              <li><a href="../patterns/pure-android.html">Pure Android</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../building-blocks/index.html">Building Blocks</a></div>
-            <ul>
-              <li><a href="../building-blocks/tabs.html">Tabs</a></li>
-              <li><a href="../building-blocks/lists.html">Lists</a></li>
-              <li><a href="../building-blocks/grid-lists.html">Grid Lists</a></li>
-              <li><a href="../building-blocks/scrolling.html">Scrolling</a></li>
-              <li><a href="../building-blocks/spinners.html">Spinners</a></li>
-              <li><a href="../building-blocks/buttons.html">Buttons</a></li>
-              <li><a href="../building-blocks/text-fields.html">Text Fields</a></li>
-              <li><a href="../building-blocks/seek-bars.html">Seek Bars</a></li>
-              <li><a href="../building-blocks/progress.html">Progress &amp; Activity</a></li>
-              <li><a href="../building-blocks/switches.html">Switches</a></li>
-              <li><a href="../building-blocks/dialogs.html">Dialogs</a></li>
-              <li><a href="../building-blocks/pickers.html">Pickers</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header empty"><a href="../downloads/index.html">Downloads</a></div>
-          </li>
-
-          <li>
-            <div id="back-dac-section"><a href="../../index.html">Developers</a></div>
-          </li>
-
-        </ul>
-
-        <div id="content">
-
-          
-          <div class="layout-content-row content-header">
-            <div class="layout-content-col span-9">
-              <h2>Selection</h2>
-            </div>
-            <div class="paging-links layout-content-col span-4">
-              <a href="#" class="prev-page-link">Previous</a>
-              <a href="#" class="next-page-link">Next</a>
-            </div>
-          </div>
-          
-
-          
-
-<p>Android 3.0 introduced the <em>long press</em> gesture&mdash;that is, a touch that's held in the same
-position for a moment&mdash;as the global gesture to select data. This affects the way you should
-handle multi-select and contextual actions in your apps.</p>
-
-<div class="vspace size-1">&nbsp;</div>
-
-<div class="layout-content-row">
-  <div class="layout-content-col span-6">
-
-<h4>What has changed?</h4>
-<p>In previous versions of Android, the long press gesture was universally used to display contextual
-actions for a given data item in a contextual menu.</p>
-<p>This pattern changed with Android 3.0. The long press gesture is now used to select data, combining
-contextual actions and selection management functions for selected data into a new element called
-the contextual action bar (CAB).</p>
-
-  </div>
-  <div class="layout-content-col span-7">
-
-    <img src="../static/content/selection_context_menu.png">
-    <div class="figure-caption">
-      Traditional use of the long press gesture to show contextual menus.
-    </div>
-
-  </div>
-</div>
-
-<h4>Using the contextual action bar (CAB)</h4>
-<p>The selection CAB is a temporary action bar that overlays your app's current action bar while data
-is selected. It appears after the user long presses on a selectable data item.</p>
-
-<img src="../static/content/selection_cab_big.png">
-
-<div class="vspace size-1">&nbsp;</div>
-
-<div class="layout-content-row">
-  <div class="layout-content-col span-6">
-
-<p>From here the user can:</p>
-<ul>
-<li>Select additional data items by touching them.</li>
-<li>Trigger an action from the CAB that applies to all highlighted data items. The CAB then
-  automatically dismisses itself.</li>
-<li>Dismiss the CAB via the navigation bar's Back button or the CAB's checkmark button. This removes
-  the CAB along with all selection highlights.</li>
-</ul>
-
-  </div>
-  <div class="layout-content-col span-7">
-
-    <img src="../static/content/selection_cab_example.png">
-
-  </div>
-</div>
-
-<div class="layout-content-row">
-  <div class="layout-content-col span-6">
-
-<h4>Selecting CAB actions</h4>
-<p>You can decide which actions and elements appear in the CAB. Use the guidelines in the <a href="actionbar.html">Action Bar
-pattern</a> to decide which items to surface at the top level and which to move to the
-action overflow.</p>
-<h4>Dynamically adjust CAB actions</h4>
-<p>In most cases you need to adjust the actions in the CAB dynamically as the user adds more items to
-the selection. Actions that apply to a single selected data item don't necessarily apply to multiple
-selected data items of the same kind.</p>
-
-  </div>
-  <div class="layout-content-col span-7">
-
-    <img src="../static/content/selection_adjusting_actions.png">
-    <div class="figure-caption">
-      Adjusting actions in the CAB as additional items are selected.
-    </div>
-
-  </div>
-</div>
-
-<h2 id="checklist">Checklist</h2>
-
-<ul>
-<li>
-<p>Whenever your app supports the selection of multiple data items, make use of the contextual action
-  bar (CAB).</p>
-</li>
-<li>
-<p>Reserve the long press gesture for selection exclusively. Don't use it to display traditional
-  contextual menus.</p>
-</li>
-<li>
-<p>If you don't support multi-selection within a list, long press should do nothing.</p>
-</li>
-<li>
-<p>Plan the actions you want to display inside of a CAB in the same way you would plan the actions
-  inside your app's action bar.</p>
-</li>
-</ul>
-
-
-
-          
-          <div class="layout-content-row content-footer">
-            <div class="paging-links layout-content-col span-9">&nbsp;</div>
-            <div class="paging-links layout-content-col span-4">
-              <a href="#" class="prev-page-link">Previous</a>
-              <a href="#" class="next-page-link">Next</a>
-            </div>
-          </div>
-          
-        </div>
-
-      </div>
-
-      <div id="page-footer">
-
-        <p id="copyright">
-          Except as noted, this content is licensed under
-          <a href="http://creativecommons.org/licenses/by/2.5/">
-          Creative Commons Attribution 2.5</a>.<br>
-          For details and restrictions, see the
-          <a href="http://developer.android.com/license.html">Content License</a>.
-        </p>
-
-        <p>
-          <a href="http://www.android.com/terms.html">Site Terms of Service</a> &ndash;
-          <a href="http://www.android.com/privacy.html">Privacy Policy</a> &ndash;
-          <a href="http://www.android.com/branding.html">Brand Guidelines</a>
-        </p>
-
-      </div>
-    </div>
-
-    <script src="../static/jquery-1.6.2.min.js"></script>
-    <script>
-    var SITE_ROOT = '../';
-    </script>
-    <script src="../static/default.js"></script>
-
-
-    <script type="text/javascript">
-    var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
-    document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
-    </script>
-    <script type="text/javascript">
-    var pageTracker = _gat._getTracker("UA-5831155-1");
-    pageTracker._trackPageview();
-    </script>
-  </body>
-</html>
diff --git a/docs/html/design/patterns/selection.jd b/docs/html/design/patterns/selection.jd
new file mode 100644
index 0000000..e3ee90e
--- /dev/null
+++ b/docs/html/design/patterns/selection.jd
@@ -0,0 +1,100 @@
+page.title=Selection
+@jd:body
+
+<p>Android 3.0 introduced the <em>long press</em> gesture&mdash;that is, a touch that's held in the same
+position for a moment&mdash;as the global gesture to select data. This affects the way you should
+handle multi-select and contextual actions in your apps.</p>
+
+<div class="vspace size-1">&nbsp;</div>
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-6">
+
+<h4>What has changed?</h4>
+<p>In previous versions of Android, the long press gesture was universally used to display contextual
+actions for a given data item in a contextual menu.</p>
+<p>This pattern changed with Android 3.0. The long press gesture is now used to select data, combining
+contextual actions and selection management functions for selected data into a new element called
+the contextual action bar (CAB).</p>
+
+  </div>
+  <div class="layout-content-col span-7">
+
+    <img src="{@docRoot}design/media/selection_context_menu.png">
+    <div class="figure-caption">
+      Traditional use of the long press gesture to show contextual menus.
+    </div>
+
+  </div>
+</div>
+
+<h4>Using the contextual action bar (CAB)</h4>
+<p>The selection CAB is a temporary action bar that overlays your app's current action bar while data
+is selected. It appears after the user long presses on a selectable data item.</p>
+
+<img src="{@docRoot}design/media/selection_cab_big.png">
+
+<div class="vspace size-1">&nbsp;</div>
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-6">
+
+<p>From here the user can:</p>
+<ul>
+<li>Select additional data items by touching them.</li>
+<li>Trigger an action from the CAB that applies to all highlighted data items. The CAB then
+  automatically dismisses itself.</li>
+<li>Dismiss the CAB via the navigation bar's Back button or the CAB's checkmark button. This removes
+  the CAB along with all selection highlights.</li>
+</ul>
+
+  </div>
+  <div class="layout-content-col span-7">
+
+    <img src="{@docRoot}design/media/selection_cab_example.png">
+
+  </div>
+</div>
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-6">
+
+<h4>Selecting CAB actions</h4>
+<p>You can decide which actions and elements appear in the CAB. Use the guidelines in the <a href="actionbar.html">Action Bar
+pattern</a> to decide which items to surface at the top level and which to move to the
+action overflow.</p>
+<h4>Dynamically adjust CAB actions</h4>
+<p>In most cases you need to adjust the actions in the CAB dynamically as the user adds more items to
+the selection. Actions that apply to a single selected data item don't necessarily apply to multiple
+selected data items of the same kind.</p>
+
+  </div>
+  <div class="layout-content-col span-7">
+
+    <img src="{@docRoot}design/media/selection_adjusting_actions.png">
+    <div class="figure-caption">
+      Adjusting actions in the CAB as additional items are selected.
+    </div>
+
+  </div>
+</div>
+
+<h2 id="checklist">Checklist</h2>
+
+<ul>
+<li>
+<p>Whenever your app supports the selection of multiple data items, make use of the contextual action
+  bar (CAB).</p>
+</li>
+<li>
+<p>Reserve the long press gesture for selection exclusively. Don't use it to display traditional
+  contextual menus.</p>
+</li>
+<li>
+<p>If you don't support multi-selection within a list, long press should do nothing.</p>
+</li>
+<li>
+<p>Plan the actions you want to display inside of a CAB in the same way you would plan the actions
+  inside your app's action bar.</p>
+</li>
+</ul>
diff --git a/docs/html/design/patterns/swipe-views.html b/docs/html/design/patterns/swipe-views.html
deleted file mode 100644
index acc9f39..0000000
--- a/docs/html/design/patterns/swipe-views.html
+++ /dev/null
@@ -1,231 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-  <head>
-    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
-    <title>
-
-Android Design - Swipe Views
-    </title>
-    <link rel="shortcut icon" type="image/x-icon" href="/favicon.ico">
-    <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Roboto:regular,medium,thin,italic,mediumitalic">
-    <link rel="stylesheet" href="../static/yui-3.3.0-reset-min.css">
-    <link rel="stylesheet" href="../static/default.css">
-
-  </head>
-  <body>
-
-    <div id="page-container">
-
-      <div id="page-header"><a href="../index.html">Android Design</a></div>
-
-      <div id="main-row">
-
-        <ul id="nav">
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../index.html">Get Started</a></div>
-            <ul>
-              <li><a href="../get-started/creative-vision.html">Creative Vision</a></li>
-              <li><a href="../get-started/principles.html">Design Principles</a></li>
-              <li><a href="../get-started/ui-overview.html">UI Overview</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../style/index.html">Style</a></div>
-            <ul>
-              <li><a href="../style/devices-displays.html">Devices and Displays</a></li>
-              <li><a href="../style/themes.html">Themes</a></li>
-              <li><a href="../style/touch-feedback.html">Touch Feedback</a></li>
-              <li><a href="../style/metrics-grids.html">Metrics and Grids</a></li>
-              <li><a href="../style/typography.html">Typography</a></li>
-              <li><a href="../style/color.html">Color</a></li>
-              <li><a href="../style/iconography.html">Iconography</a></li>
-              <li><a href="../style/writing.html">Writing Style</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../patterns/index.html">Patterns</a></div>
-            <ul>
-              <li><a href="../patterns/new-4-0.html">New in Android 4.0</a></li>
-              <li><a href="../patterns/gestures.html">Gestures</a></li>
-              <li><a href="../patterns/app-structure.html">App Structure</a></li>
-              <li><a href="../patterns/navigation.html">Navigation</a></li>
-              <li><a href="../patterns/actionbar.html">Action Bar</a></li>
-              <li><a href="../patterns/multi-pane-layouts.html">Multi-pane Layouts</a></li>
-              <li><a href="../patterns/swipe-views.html">Swipe Views</a></li>
-              <li><a href="../patterns/selection.html">Selection</a></li>
-              <li><a href="../patterns/notifications.html">Notifications</a></li>
-              <li><a href="../patterns/compatibility.html">Compatibility</a></li>
-              <li><a href="../patterns/pure-android.html">Pure Android</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../building-blocks/index.html">Building Blocks</a></div>
-            <ul>
-              <li><a href="../building-blocks/tabs.html">Tabs</a></li>
-              <li><a href="../building-blocks/lists.html">Lists</a></li>
-              <li><a href="../building-blocks/grid-lists.html">Grid Lists</a></li>
-              <li><a href="../building-blocks/scrolling.html">Scrolling</a></li>
-              <li><a href="../building-blocks/spinners.html">Spinners</a></li>
-              <li><a href="../building-blocks/buttons.html">Buttons</a></li>
-              <li><a href="../building-blocks/text-fields.html">Text Fields</a></li>
-              <li><a href="../building-blocks/seek-bars.html">Seek Bars</a></li>
-              <li><a href="../building-blocks/progress.html">Progress &amp; Activity</a></li>
-              <li><a href="../building-blocks/switches.html">Switches</a></li>
-              <li><a href="../building-blocks/dialogs.html">Dialogs</a></li>
-              <li><a href="../building-blocks/pickers.html">Pickers</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header empty"><a href="../downloads/index.html">Downloads</a></div>
-          </li>
-
-          <li>
-            <div id="back-dac-section"><a href="../../index.html">Developers</a></div>
-          </li>
-
-        </ul>
-
-        <div id="content">
-
-          
-          <div class="layout-content-row content-header">
-            <div class="layout-content-col span-9">
-              <h2>Swipe Views</h2>
-            </div>
-            <div class="paging-links layout-content-col span-4">
-              <a href="#" class="prev-page-link">Previous</a>
-              <a href="#" class="next-page-link">Next</a>
-            </div>
-          </div>
-          
-
-          
-
-<p>Efficient navigation is one of the cornerstones of a well-designed app. While apps are generally
-built in a hierarchical fashion, there are instances where horizontal navigation can flatten
-vertical hierarchies and make access to related data items faster and more enjoyable. Swipe views
-allow the user to efficiently move from item to item using a simple gesture and thereby make
-browsing and consuming data a more fluent experience.</p>
-<h2 id="detail-views">Swiping Between Detail Views</h2>
-
-<p>An app's data is often organized in a master/detail relationship: The user can view a list of
-related data items, such as images, chats, or emails, and then pick one of the items to see the
-detail contents in a separate screen.</p>
-
-<img src="../static/content/swipe_views.png">
-<div class="figure-caption">
-  Master (left) and detail (right) views.
-</div>
-
-<p>On a phone, since the master and detail are on separate screens, this typically requires the user to
-jump back and forth between the list and the detail view, aka "pogo-sticking".</p>
-<p>In cases where users will want to view multiple detail items in succession, avoid pogo-sticking by
-using the swipe gesture to navigate to the next/previous detail view.</p>
-
-<img src="../static/content/swipe_views2.png">
-<div class="figure-caption">
-  Navigating between consecutive Email messages using the swipe gesture.
-</div>
-
-<h2 id="between-tabs">Swiping Between Tabs</h2>
-
-<div class="layout-content-row">
-  <div class="layout-content-col span-5">
-
-    <div class="framed-galaxynexus-port-span-5">
-      <video class="play-on-hover" autoplay>
-        <source src="../static/content/swipe_tabs.mp4" type="video/mp4">
-        <source src="../static/content/swipe_tabs.webm" type="video/webm">
-        <source src="../static/content/swipe_tabs.ogv" type="video/ogg">
-      </video>
-    </div>
-    <div class="figure-caption">
-      People app with swipe gesture navigation between top-level screens.
-      <div class="video-instructions">&nbsp;</div>
-    </div>
-
-  </div>
-  <div class="layout-content-col span-8">
-
-<p>If your app uses action bar tabs, use swipe to navigate between the different views.</p>
-<div class="vspace size-2">&nbsp;</div>
-
-<h2 id="checklist">Checklist</h2>
-
-<ul>
-<li>
-<p>Use swipe to quickly navigate between detail views or tabs.</p>
-</li>
-<li>
-<p>Transition between the views as the user performs the swipe gesture. Do not wait for the
-  gesture to complete and then transition between views.</p>
-</li>
-<li>
-<p>If you used buttons in the past for previous/next navigation, replace them with
-  the swipe gesture.</p>
-</li>
-<li>
-<p>Consider adding contextual information in your detail view that informs the user about the
-  relative list position of the currently visible item.</p>
-</li>
-</ul>
-
-  </div>
-</div>
-
-
-
-          
-          <div class="layout-content-row content-footer">
-            <div class="paging-links layout-content-col span-9">&nbsp;</div>
-            <div class="paging-links layout-content-col span-4">
-              <a href="#" class="prev-page-link">Previous</a>
-              <a href="#" class="next-page-link">Next</a>
-            </div>
-          </div>
-          
-        </div>
-
-      </div>
-
-      <div id="page-footer">
-
-        <p id="copyright">
-          Except as noted, this content is licensed under
-          <a href="http://creativecommons.org/licenses/by/2.5/">
-          Creative Commons Attribution 2.5</a>.<br>
-          For details and restrictions, see the
-          <a href="http://developer.android.com/license.html">Content License</a>.
-        </p>
-
-        <p>
-          <a href="http://www.android.com/terms.html">Site Terms of Service</a> &ndash;
-          <a href="http://www.android.com/privacy.html">Privacy Policy</a> &ndash;
-          <a href="http://www.android.com/branding.html">Brand Guidelines</a>
-        </p>
-
-      </div>
-    </div>
-
-    <script src="../static/jquery-1.6.2.min.js"></script>
-    <script>
-    var SITE_ROOT = '../';
-    </script>
-    <script src="../static/default.js"></script>
-
-
-    <script type="text/javascript">
-    var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
-    document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
-    </script>
-    <script type="text/javascript">
-    var pageTracker = _gat._getTracker("UA-5831155-1");
-    pageTracker._trackPageview();
-    </script>
-  </body>
-</html>
diff --git a/docs/html/design/patterns/swipe-views.jd b/docs/html/design/patterns/swipe-views.jd
new file mode 100644
index 0000000..95d65dd
--- /dev/null
+++ b/docs/html/design/patterns/swipe-views.jd
@@ -0,0 +1,74 @@
+page.title=Swipe Views
+@jd:body
+
+<p>Efficient navigation is one of the cornerstones of a well-designed app. While apps are generally
+built in a hierarchical fashion, there are instances where horizontal navigation can flatten
+vertical hierarchies and make access to related data items faster and more enjoyable. Swipe views
+allow the user to efficiently move from item to item using a simple gesture and thereby make
+browsing and consuming data a more fluent experience.</p>
+<h2 id="detail-views">Swiping Between Detail Views</h2>
+
+<p>An app's data is often organized in a master/detail relationship: The user can view a list of
+related data items, such as images, chats, or emails, and then pick one of the items to see the
+detail contents in a separate screen.</p>
+
+<img src="{@docRoot}design/media/swipe_views.png">
+<div class="figure-caption">
+  Master (left) and detail (right) views.
+</div>
+
+<p>On a phone, since the master and detail are on separate screens, this typically requires the user to
+jump back and forth between the list and the detail view, aka "pogo-sticking".</p>
+<p>In cases where users will want to view multiple detail items in succession, avoid pogo-sticking by
+using the swipe gesture to navigate to the next/previous detail view.</p>
+
+<img src="{@docRoot}design/media/swipe_views2.png">
+<div class="figure-caption">
+  Navigating between consecutive Email messages using the swipe gesture.
+</div>
+
+<h2 id="between-tabs">Swiping Between Tabs</h2>
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-5">
+
+    <div class="framed-galaxynexus-port-span-5">
+      <video class="play-on-hover" autoplay>
+        <source src="{@docRoot}design/media/swipe_tabs.mp4" type="video/mp4">
+        <source src="{@docRoot}design/media/swipe_tabs.webm" type="video/webm">
+        <source src="{@docRoot}design/media/swipe_tabs.ogv" type="video/ogg">
+      </video>
+    </div>
+    <div class="figure-caption">
+      People app with swipe gesture navigation between top-level screens.
+      <div class="video-instructions">&nbsp;</div>
+    </div>
+
+  </div>
+  <div class="layout-content-col span-8">
+
+<p>If your app uses action bar tabs, use swipe to navigate between the different views.</p>
+<div class="vspace size-2">&nbsp;</div>
+
+<h2 id="checklist">Checklist</h2>
+
+<ul>
+<li>
+<p>Use swipe to quickly navigate between detail views or tabs.</p>
+</li>
+<li>
+<p>Transition between the views as the user performs the swipe gesture. Do not wait for the
+  gesture to complete and then transition between views.</p>
+</li>
+<li>
+<p>If you used buttons in the past for previous/next navigation, replace them with
+  the swipe gesture.</p>
+</li>
+<li>
+<p>Consider adding contextual information in your detail view that informs the user about the
+  relative list position of the currently visible item.</p>
+</li>
+</ul>
+
+  </div>
+</div>
diff --git a/docs/html/design/static/callout.png b/docs/html/design/static/callout.png
deleted file mode 100644
index 5d49f34..0000000
--- a/docs/html/design/static/callout.png
+++ /dev/null
Binary files differ
diff --git a/docs/html/design/static/default.css b/docs/html/design/static/default.css
deleted file mode 100644
index 3aa1db3..0000000
--- a/docs/html/design/static/default.css
+++ /dev/null
@@ -1,633 +0,0 @@
-/* color definitions */
-/* 16 column layout */
-/* clearfix idiom */
-/* common mixins */
-/* page layout + top-level styles */
-::-webkit-selection,
-::-moz-selection,
-::selection {
-  background-color: #0099cc;
-  color: #fff; }
-
-html, body {
-  height: 100%;
-  margin: 0;
-  padding: 0;
-  background: #eee none no-repeat fixed top left;
-  background-image: -webkit-gradient(linear, 100% 0%, 100% 100%, from(#dddddd), color-stop(25%, #f2f2f2), color-stop(75%, #f2f2f2), to(#dddddd));
-  background-image: -moz-linear-gradient(top, #dddddd, #f2f2f2, #f2f2f2, #dddddd);
-  -webkit-font-smoothing: antialiased;
-  /* prevent subpixel antialiasing, which thickens the text */
-  text-rendering: optimizeLegibility;
-  /* opentype ftw */ }
-
-body {
-  color: #555555;
-  font: 14px/20px Roboto, sans-serif;
-  font-weight: 400; }
-
-#page-container {
-  width: 940px;
-  margin: 0 40px; }
-
-#page-header {
-  height: 80px;
-  margin-bottom: 20px;
-  font-size: 48px;
-  line-height: 48px;
-  font-weight: 100;
-  padding-left: 10px; }
-  #page-header a {
-    display: block;
-    position: relative;
-    top: 20px;
-    text-decoration: none;
-    color: #555555 !important; }
-
-#main-row {
-  display: inline-block; }
-  #main-row:after {
-    content: ".";
-    display: block;
-    height: 0;
-    clear: both;
-    visibility: hidden; }
-  * html #main-row {
-    height: 1px; }
-
-#page-footer {
-  margin-left: 190px;
-  margin-top: 80px;
-  color: #999999;
-  padding-bottom: 40px;
-  font-size: 12px;
-  line-height: 15px; }
-  #page-footer a {
-    color: #777777; }
-  #page-footer #copyright {
-    margin-bottom: 10px; }
-
-#nav {
-  width: 160px;
-  margin-right: 20px;
-  float: left; }
-
-#content {
-  width: 760px;
-  float: left; }
-
-a,
-a:visited {
-  color: #333333; }
-
-a:hover,
-acronym:hover {
-  color: #7aa1b0 !important; }
-
-a:focus,
-a:active {
-  color: #33b5e5 !important; }
-
-img {
-  border: none; }
-
-ul {
-  margin: 0;
-  padding: 0; }
-
-strong {
-  font-weight: 500; }
-
-em {
-  font-style: italic; }
-
-code {
-  font-family: Courier New, monospace; }
-
-acronym {
-  border-bottom: 1px dotted #555555;
-  cursor: help; }
-
-acronym:hover {
-  border-bottom-color: #7aa1b0; }
-
-img.with-shadow,
-video.with-shadow {
-  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.25); }
-
-/* disclosures mixin */
-/* content layout */
-.layout-content-row {
-  display: inline-block;
-  margin-bottom: 10px; }
-  .layout-content-row:after {
-    content: ".";
-    display: block;
-    height: 0;
-    clear: both;
-    visibility: hidden; }
-  * html .layout-content-row {
-    height: 1px; }
-
-.layout-content-col {
-  float: left;
-  margin-left: 20px; }
-  .layout-content-col:first-child {
-    margin-left: 0; }
-
-.layout-content-col.span-1 {
-  width: 40px; }
-
-.layout-content-col.span-2 {
-  width: 100px; }
-
-.layout-content-col.span-3 {
-  width: 160px; }
-
-.layout-content-col.span-4 {
-  width: 220px; }
-
-.layout-content-col.span-5 {
-  width: 280px; }
-
-.layout-content-col.span-6 {
-  width: 340px; }
-
-.layout-content-col.span-7 {
-  width: 400px; }
-
-.layout-content-col.span-8 {
-  width: 460px; }
-
-.layout-content-col.span-9 {
-  width: 520px; }
-
-.layout-content-col.span-10 {
-  width: 580px; }
-
-.layout-content-col.span-11 {
-  width: 640px; }
-
-.layout-content-col.span-12 {
-  width: 700px; }
-
-.layout-content-col.span-13 {
-  width: 760px; }
-
-.vspace.size-1 {
-  height: 10px; }
-
-.vspace.size-2 {
-  height: 20px; }
-
-.vspace.size-3 {
-  height: 30px; }
-
-.vspace.size-4 {
-  height: 40px; }
-
-.vspace.size-5 {
-  height: 50px; }
-
-.vspace.size-6 {
-  height: 60px; }
-
-.vspace.size-7 {
-  height: 70px; }
-
-.vspace.size-8 {
-  height: 80px; }
-
-.vspace.size-9 {
-  height: 90px; }
-
-.vspace.size-10 {
-  height: 100px; }
-
-.vspace.size-11 {
-  height: 110px; }
-
-.vspace.size-12 {
-  height: 120px; }
-
-.vspace.size-13 {
-  height: 130px; }
-
-.vspace.size-14 {
-  height: 140px; }
-
-.vspace.size-15 {
-  height: 150px; }
-
-.vspace.size-16 {
-  height: 160px; }
-
-/* nav */
-#nav {
-  /* section header divs */
-  /* expanded section header divs */
-  /* sublinks */ }
-  #nav li {
-    list-style-type: none;
-    font-size: 14px;
-    line-height: 10px; }
-  #nav a {
-    color: #555555;
-    text-decoration: none; }
-  #nav li.selected > a,
-  #nav li.selected .nav-section-header a {
-    font-weight: 500;
-    color: #0099cc !important; }
-  #nav .nav-section-header {
-    position: relative;
-    padding: 10px;
-    margin-bottom: 1px;
-    /* section header links */ }
-    #nav .nav-section-header a {
-      color: #333333;
-      font-weight: 500;
-      text-transform: uppercase; }
-    #nav .nav-section-header:after {
-      content: '';
-      background: transparent url(disclosure_down.png) no-repeat scroll top left;
-      width: 10px;
-      height: 10px;
-      display: block;
-      position: absolute;
-      top: 10px;
-      right: 10px; }
-    #nav .nav-section-header.empty:after {
-      display: none; }
-  #nav li.expanded .nav-section-header {
-    background: rgba(0, 0, 0, 0.05); }
-    #nav li.expanded .nav-section-header:after {
-      content: '';
-      background: transparent url(disclosure_up.png) no-repeat scroll top left;
-      width: 10px;
-      height: 10px; }
-  #nav > li > ul {
-    height: 0;
-    overflow: hidden;
-    margin-bottom: 0; }
-    #nav > li > ul.animate-height {
-      -webkit-transition: height 0.25s ease-in;
-      -moz-transition: height 0.25s ease-in;
-      transition: height 0.25s ease-in; }
-    #nav > li > ul li {
-      padding: 10px 10px 11px 10px; }
-  #nav > li.expanded > ul {
-    height: auto; }
-    #nav > li.expanded > ul li {
-      background: rgba(0, 0, 0, 0.03); }
-  #nav #back-dac-section {
-    padding: 10px;
-    border-top: 1px solid #ddd; }
-    #nav #back-dac-section a {
-      color: #333333;
-      font-weight: 500;
-      text-transform: uppercase; }
-
-/* content header */
-.content-header {
-  border-bottom: 1px solid #33b5e5;
-  height: 30px; }
-  .content-header h2 {
-    border-bottom: 0; }
-  .content-header.just-links {
-    border-bottom: 0; }
-
-.content-footer {
-  border-top: 1px solid #33b5e5;
-  margin-top: 10px;
-  height: 30px; }
-
-.paging-links {
-  position: relative; }
-  .paging-links a {
-    position: absolute;
-    font-size: 14px;
-    line-height: 30px;
-    color: #555555;
-    text-decoration: none;
-    text-transform: uppercase; }
-  .paging-links .prev-page-link {
-    display: none;
-    left: -5px; }
-    .paging-links .prev-page-link:before {
-      content: '';
-      background: transparent url(disclosure_left.png) no-repeat scroll top left;
-      width: 10px;
-      height: 10px;
-      display: inline-block;
-      margin-right: 5px; }
-  .paging-links .next-page-link {
-    display: none;
-    right: 10px; }
-    .paging-links .next-page-link:after {
-      content: '';
-      background: transparent url(disclosure_right.png) no-repeat scroll top left;
-      width: 10px;
-      height: 10px;
-      display: inline-block;
-      margin-left: 5px; }
-
-/* content body */
-@-webkit-keyframes glowheader {
-  from {
-    background-color: #33b5e5;
-    color: #000;
-    border-bottom-color: #000; }
-
-  to {
-    background-color: transparent;
-    color: #33b5e5;
-    border-bottom-color: #33b5e5; } }
-
-@-moz-keyframes glowheader {
-  from {
-    background-color: #33b5e5;
-    color: #000;
-    border-bottom-color: #000; }
-
-  to {
-    background-color: transparent;
-    color: #33b5e5;
-    border-bottom-color: #33b5e5; } }
-
-@keyframes glowheader {
-  from {
-    background-color: #33b5e5;
-    color: #000;
-    border-bottom-color: #000; }
-
-  to {
-    background-color: transparent;
-    color: #33b5e5;
-    border-bottom-color: #33b5e5; } }
-
-#content p,
-#content ul,
-#content ol,
-#content h3 {
-  margin: 0 10px 10px 10px; }
-#content h2 {
-  padding-left: 10px;
-  padding-right: 10px;
-  margin-bottom: 10px;
-  font-size: 16px;
-  line-height: 30px;
-  font-weight: 500;
-  color: #33b5e5;
-  border-bottom: 1px solid #33b5e5;
-  height: 30px; }
-  #content h2:target {
-    -webkit-animation-name: glowheader;
-    -moz-animation-name: glowheader;
-    animation-name: glowheader;
-    -webkit-animation-duration: 0.7s;
-    -moz-animation-duration: 0.7s;
-    animation-duration: 0.7s;
-    -webkit-animation-timing-function: ease-out;
-    -moz-animation-timing-function: ease-out;
-    animation-timing-function: ease-out; }
-#content hr {
-  border: 0;
-  border-bottom: 1px solid #33b5e5;
-  margin-bottom: 20px; }
-#content h3 {
-  color: #33b5e5;
-  text-transform: uppercase;
-  font-size: 14px;
-  line-height: 20px;
-  font-weight: 500; }
-#content h4 {
-  margin: 0 10px;
-  color: #333333;
-  font-weight: 500;
-  font-size: 14px;
-  line-height: 20px; }
-#content strong {
-  color: #333333; }
-#content ul li,
-#content ol li {
-  margin-left: 20px; }
-  #content ul li h4,
-  #content ol li h4 {
-    margin: 0; }
-  #content ul li p,
-  #content ol li p {
-    margin-left: 0; }
-#content ul li {
-  list-style-type: square;
-  list-style-type: none;
-  position: relative; }
-  #content ul li:before {
-    content: '\2022';
-    font-family: verdana;
-    font-size: 14px;
-    line-height: 20px;
-    position: absolute;
-    left: -20px;
-    top: -1px; }
-#content ol {
-  counter-reset: item; }
-  #content ol li {
-    font-size: 14px;
-    line-height: 20px;
-    list-style-type: none;
-    position: relative; }
-    #content ol li:before {
-      content: counter(item) ". ";
-      counter-increment: item;
-      position: absolute;
-      left: -20px;
-      top: 0; }
-    #content ol li.value-1:before {
-      content: "1. "; }
-    #content ol li.value-2:before {
-      content: "2. "; }
-    #content ol li.value-3:before {
-      content: "3. "; }
-    #content ol li.value-4:before {
-      content: "4. "; }
-    #content ol li.value-5:before {
-      content: "5. "; }
-    #content ol li.value-6:before {
-      content: "6. "; }
-    #content ol li.value-7:before {
-      content: "7. "; }
-    #content ol li.value-8:before {
-      content: "8. "; }
-    #content ol li.value-9:before {
-      content: "9. "; }
-    #content ol li.value-10:before {
-      content: "10. "; }
-#content .with-callouts ol li {
-  list-style-position: inside;
-  margin-left: 0; }
-  #content .with-callouts ol li:before {
-    position: static;
-    display: inline;
-    left: 0;
-    float: left;
-    width: 17px;
-    color: #33b5e5;
-    font-weight: 500; }
-
-/* special list items */
-li.no-bullet {
-  list-style-type: none !important; }
-
-#content li.with-icon {
-  position: relative;
-  margin-left: 40px;
-  min-height: 30px; }
-  #content li.with-icon p {
-    margin-left: 0 !important; }
-  #content li.with-icon:before {
-    position: absolute;
-    left: -40px;
-    top: 0;
-    content: '';
-    width: 30px;
-    height: 30px; }
-  #content li.with-icon.tablet:before {
-    background-image: url(ico_phone_tablet.png); }
-  #content li.with-icon.web:before {
-    background-image: url(ico_web.png); }
-  #content li.with-icon.checklist:before {
-    background-image: url(ico_checklist.png); }
-  #content li.with-icon.action:before {
-    background-image: url(ico_action.png); }
-  #content li.with-icon.use:before {
-    background-image: url(ico_use.png); }
-
-/* figures and callouts */
-.figure {
-  position: relative; }
-  .figure.pad-below {
-    margin-bottom: 20px; }
-  .figure .figure-callout {
-    position: absolute;
-    color: #fff;
-    font-weight: 500;
-    font-size: 16px;
-    line-height: 23px;
-    text-align: center;
-    background: transparent url(callout.png) no-repeat scroll 50% 50%;
-    padding-right: 2px;
-    width: 30px;
-    height: 29px;
-    z-index: 1000; }
-    .figure .figure-callout.top {
-      top: -9px; }
-    .figure .figure-callout.right {
-      right: -5px; }
-
-.figure-caption {
-  margin: 0 10px 20px 10px;
-  font-size: 14px;
-  line-height: 20px;
-  font-style: italic; }
-
-/* rows of figures */
-.figure-row {
-  font-size: 0;
-  line-height: 0;
-  /* to prevent space between figures */ }
-  .figure-row .figure {
-    display: inline-block;
-    vertical-align: top; }
-  .figure-row .figure + .figure {
-    margin-left: 10px;
-    /* reintroduce space between figures */ }
-
-/* video  containers */
-.framed-galaxynexus-land-span-13 {
-  background: transparent url(content/misc_full_galaxynexus_blank_land_span13.png) no-repeat scroll top left;
-  padding: 42px 122px 62px 126px;
-  overflow: hidden; }
-  .framed-galaxynexus-land-span-13, .framed-galaxynexus-land-span-13 video, .framed-galaxynexus-land-span-13 img {
-    width: 512px;
-    height: 286px; }
-
-.framed-galaxynexus-port-span-9 {
-  background: transparent url(content/misc_full_galaxynexus_blank_port_span9.png) no-repeat scroll top left;
-  padding: 95px 122px 107px 124px;
-  overflow: hidden; }
-  .framed-galaxynexus-port-span-9, .framed-galaxynexus-port-span-9 video, .framed-galaxynexus-port-span-9 img {
-    width: 274px;
-    height: 488px; }
-
-.framed-galaxynexus-port-span-5 {
-  background: transparent url(content/misc_full_galaxynexus_blank_port_span5.png) no-repeat scroll top left;
-  padding: 75px 31px 76px 33px;
-  overflow: hidden; }
-  .framed-galaxynexus-port-span-5, .framed-galaxynexus-port-span-5 video, .framed-galaxynexus-port-span-5 img {
-    width: 216px;
-    height: 384px; }
-
-/* landing page disclosures */
-.landing-page-link {
-  text-decoration: none;
-  font-weight: 500;
-  color: #333333; }
-  .landing-page-link:after {
-    content: '';
-    background: transparent url(disclosure_right.png) no-repeat scroll top left;
-    width: 10px;
-    height: 10px;
-    display: inline-block;
-    margin-left: 5px; }
-
-/* tooltips */
-.tooltip-box {
-  position: absolute;
-  background-color: rgba(0, 0, 0, 0.9);
-  border-radius: 2px;
-  font-size: 14px;
-  line-height: 20px;
-  color: #fff;
-  padding: 6px 10px;
-  max-width: 250px;
-  z-index: 10000; }
-  .tooltip-box.below:after {
-    position: absolute;
-    content: '';
-    line-height: 0;
-    display: block;
-    top: -10px;
-    left: 5px;
-    border: 5px solid transparent;
-    border-bottom-color: rgba(0, 0, 0, 0.9); }
-
-/* video note */
-.video-instructions {
-  margin-top: 10px;
-  margin-bottom: 10px; }
-  .video-instructions:before {
-    content: '';
-    background: transparent url(ico_movie_inline.png) no-repeat scroll top left;
-    display: inline-block;
-    width: 12px;
-    height: 12px;
-    margin-right: 8px; }
-  .video-instructions:after {
-    content: 'Click to replay movie.'; }
-
-/* download buttons */
-.download-button {
-  display: block;
-  margin-bottom: 5px;
-  text-decoration: none;
-  background-color: #33b5e5;
-  color: #fff !important;
-  font-weight: 500;
-  box-shadow: 0 1px 1px rgba(0, 0, 0, 0.12);
-  padding: 6px 12px;
-  border-radius: 2px; }
-  .download-button:hover, .download-button:focus {
-    background-color: #0099cc;
-    color: #fff !important; }
-  .download-button:active {
-    background-color: #006699; }
diff --git a/docs/html/design/static/default.js b/docs/html/design/static/default.js
deleted file mode 100644
index b213dd9..0000000
--- a/docs/html/design/static/default.js
+++ /dev/null
@@ -1,169 +0,0 @@
-$(document).ready(function() {
-  // prep nav expandos
-  var pagePath = document.location.pathname;
-  if (pagePath.indexOf(SITE_ROOT) == 0) {
-    pagePath = pagePath.substr(SITE_ROOT.length);
-    if (pagePath == '' || pagePath.charAt(pagePath.length - 1) == '/') {
-      pagePath += 'index.html';
-    }
-  }
-
-  if (SITE_ROOT.match(/\.\.\//) || SITE_ROOT == '') {
-    // If running locally, SITE_ROOT will be a relative path, so account for that by
-    // finding the relative URL to this page. This will allow us to find links on the page
-    // leading back to this page.
-    var pathParts = pagePath.split('/');
-    var relativePagePathParts = [];
-    var upDirs = (SITE_ROOT.match(/(\.\.\/)+/) || [''])[0].length / 3;
-    for (var i = 0; i < upDirs; i++) {
-      relativePagePathParts.push('..');
-    }
-    for (var i = 0; i < upDirs; i++) {
-      relativePagePathParts.push(pathParts[pathParts.length - (upDirs - i) - 1]);
-    }
-    relativePagePathParts.push(pathParts[pathParts.length - 1]);
-    pagePath = relativePagePathParts.join('/');
-  } else {
-    // Otherwise the page path should be an absolute URL.
-    pagePath = SITE_ROOT + pagePath;
-  }
-
-  // select current page in sidenav and set up prev/next links if they exist
-  var $selNavLink = $('#nav').find('a[href="' + pagePath + '"]');
-  if ($selNavLink.length) {
-    $selListItem = $selNavLink.closest('li');
-
-    $selListItem.addClass('selected');
-    $selListItem.closest('li.nav-section').addClass('expanded');
-
-    // set up prev links
-    var $prevLink = [];
-    var $prevListItem = $selListItem.prev('li');
-    if ($prevListItem.length) {
-      if ($prevListItem.hasClass('nav-section')) {
-        // jump to last topic of previous section
-        $prevLink = $prevListItem.find('a:last');
-      } else {
-        // jump to previous topic in this section
-        $prevLink = $prevListItem.find('a:eq(0)');
-      }
-    } else {
-      // jump to this section's index page (if it exists)
-      $prevLink = $selListItem.parents('li').find('a');
-    }
-
-    if ($prevLink.length) {
-      var prevHref = $prevLink.attr('href');
-      if (prevHref == SITE_ROOT + 'index.html') {
-        // Don't show Previous when it leads to the homepage
-        $('.prev-page-link').hide();
-      } else {
-        $('.prev-page-link').attr('href', prevHref).show();
-      }
-    } else {
-      $('.prev-page-link').hide();
-    }
-
-    // set up next links
-    var $nextLink = [];
-    if ($selListItem.hasClass('nav-section')) {
-      // we're on an index page, jump to the first topic
-      $nextLink = $selListItem.find('ul').find('a:eq(0)')
-    } else {
-      // jump to the next topic in this section (if it exists)
-      $nextLink = $selListItem.next('li').find('a:eq(0)');
-      if (!$nextLink.length) {
-        // no more topics in this section, jump to the first topic in the next section
-        $nextLink = $selListItem.parents('li').next('li.nav-section').find('a:eq(0)');
-      }
-    }
-    if ($nextLink.length) {
-      $('.next-page-link').attr('href', $nextLink.attr('href')).show();
-    } else {
-      $('.next-page-link').hide();
-    }
-  }
-
-  // Set up expand/collapse behavior
-  $('#nav li.nav-section').click(function() {
-    if ($(this).hasClass('expanded')) {
-      return;
-    }
-
-    // hide other
-    var $old = $('#nav li.nav-section.expanded');
-    if ($old.length) {
-      var $oldUl = $old.children('ul');
-      $oldUl.css('height', $oldUl.height() + 'px');
-      window.setTimeout(function() {
-        $oldUl
-            .addClass('animate-height')
-            .css('height', '');
-      }, 0);
-      $old.removeClass('expanded');
-    }
-
-    // show me
-    $(this).addClass('expanded');
-    var $ul = $(this).children('ul');
-    var expandedHeight = $ul.height();
-    $ul
-        .removeClass('animate-height')
-        .css('height', 0);
-    window.setTimeout(function() {
-      $ul
-          .addClass('animate-height')
-          .css('height', expandedHeight + 'px');
-    }, 0);
-  });
-
-  // Stop expand/collapse behavior when clicking on nav section links (since we're navigating away
-  // from the page)
-  $('.nav-section-header').find('a:eq(0)').click(function(evt) {
-    window.location.href = $(this).attr('href');
-    return false;
-  });
-
-  // Set up play-on-hover <video> tags.
-  $('video.play-on-hover').bind('click', function(){
-    $(this).get(0).load(); // in case the video isn't seekable
-    $(this).get(0).play();
-  });
-
-  // Set up tooltips
-  var TOOLTIP_MARGIN = 10;
-  $('acronym').each(function() {
-    var $target = $(this);
-    var $tooltip = $('<div>')
-        .addClass('tooltip-box')
-        .text($target.attr('title'))
-        .hide()
-        .appendTo('body');
-    $target.removeAttr('title');
-
-    $target.hover(function() {
-      // in
-      var targetRect = $target.offset();
-      targetRect.width = $target.width();
-      targetRect.height = $target.height();
-
-      $tooltip.css({
-        left: targetRect.left,
-        top: targetRect.top + targetRect.height + TOOLTIP_MARGIN
-      });
-      $tooltip.addClass('below');
-      $tooltip.show();
-    }, function() {
-      // out
-      $tooltip.hide();
-    });
-  });
-
-  // Set up <h2> deeplinks
-  $('h2').click(function() {
-    var id = $(this).attr('id');
-    if (id) {
-      document.location.hash = id;
-    }
-  });
-});
\ No newline at end of file
diff --git a/docs/html/design/static/disclosure_down.png b/docs/html/design/static/disclosure_down.png
deleted file mode 100644
index 4b3ff4d..0000000
--- a/docs/html/design/static/disclosure_down.png
+++ /dev/null
Binary files differ
diff --git a/docs/html/design/static/disclosure_left.png b/docs/html/design/static/disclosure_left.png
deleted file mode 100644
index 607845e..0000000
--- a/docs/html/design/static/disclosure_left.png
+++ /dev/null
Binary files differ
diff --git a/docs/html/design/static/disclosure_right.png b/docs/html/design/static/disclosure_right.png
deleted file mode 100644
index f3bceb1..0000000
--- a/docs/html/design/static/disclosure_right.png
+++ /dev/null
Binary files differ
diff --git a/docs/html/design/static/disclosure_up.png b/docs/html/design/static/disclosure_up.png
deleted file mode 100644
index 5ff6d9d..0000000
--- a/docs/html/design/static/disclosure_up.png
+++ /dev/null
Binary files differ
diff --git a/docs/html/design/static/ico_action.png b/docs/html/design/static/ico_action.png
deleted file mode 100644
index 30e4cc7..0000000
--- a/docs/html/design/static/ico_action.png
+++ /dev/null
Binary files differ
diff --git a/docs/html/design/static/ico_good.png b/docs/html/design/static/ico_good.png
deleted file mode 100644
index afebe1c..0000000
--- a/docs/html/design/static/ico_good.png
+++ /dev/null
Binary files differ
diff --git a/docs/html/design/static/ico_movie_inline.png b/docs/html/design/static/ico_movie_inline.png
deleted file mode 100644
index 7cfb5c5..0000000
--- a/docs/html/design/static/ico_movie_inline.png
+++ /dev/null
Binary files differ
diff --git a/docs/html/design/static/ico_phone_tablet.png b/docs/html/design/static/ico_phone_tablet.png
deleted file mode 100644
index 003b876..0000000
--- a/docs/html/design/static/ico_phone_tablet.png
+++ /dev/null
Binary files differ
diff --git a/docs/html/design/static/ico_use.png b/docs/html/design/static/ico_use.png
deleted file mode 100644
index 9d868b3..0000000
--- a/docs/html/design/static/ico_use.png
+++ /dev/null
Binary files differ
diff --git a/docs/html/design/static/ico_web.png b/docs/html/design/static/ico_web.png
deleted file mode 100644
index 0848e3c..0000000
--- a/docs/html/design/static/ico_web.png
+++ /dev/null
Binary files differ
diff --git a/docs/html/design/static/ico_wrong.png b/docs/html/design/static/ico_wrong.png
deleted file mode 100644
index b7d04ce..0000000
--- a/docs/html/design/static/ico_wrong.png
+++ /dev/null
Binary files differ
diff --git a/docs/html/design/static/jquery-1.6.2.min.js b/docs/html/design/static/jquery-1.6.2.min.js
deleted file mode 100644
index 8cdc80e..0000000
--- a/docs/html/design/static/jquery-1.6.2.min.js
+++ /dev/null
@@ -1,18 +0,0 @@
-/*!
- * jQuery JavaScript Library v1.6.2
- * http://jquery.com/
- *
- * Copyright 2011, John Resig
- * Dual licensed under the MIT or GPL Version 2 licenses.
- * http://jquery.org/license
- *
- * Includes Sizzle.js
- * http://sizzlejs.com/
- * Copyright 2011, The Dojo Foundation
- * Released under the MIT, BSD, and GPL Licenses.
- *
- * Date: Thu Jun 30 14:16:56 2011 -0400
- */
-(function(a,b){function cv(a){return f.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:!1}function cs(a){if(!cg[a]){var b=c.body,d=f("<"+a+">").appendTo(b),e=d.css("display");d.remove();if(e==="none"||e===""){ch||(ch=c.createElement("iframe"),ch.frameBorder=ch.width=ch.height=0),b.appendChild(ch);if(!ci||!ch.createElement)ci=(ch.contentWindow||ch.contentDocument).document,ci.write((c.compatMode==="CSS1Compat"?"<!doctype html>":"")+"<html><body>"),ci.close();d=ci.createElement(a),ci.body.appendChild(d),e=f.css(d,"display"),b.removeChild(ch)}cg[a]=e}return cg[a]}function cr(a,b){var c={};f.each(cm.concat.apply([],cm.slice(0,b)),function(){c[this]=a});return c}function cq(){cn=b}function cp(){setTimeout(cq,0);return cn=f.now()}function cf(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}function ce(){try{return new a.XMLHttpRequest}catch(b){}}function b$(a,c){a.dataFilter&&(c=a.dataFilter(c,a.dataType));var d=a.dataTypes,e={},g,h,i=d.length,j,k=d[0],l,m,n,o,p;for(g=1;g<i;g++){if(g===1)for(h in a.converters)typeof h=="string"&&(e[h.toLowerCase()]=a.converters[h]);l=k,k=d[g];if(k==="*")k=l;else if(l!=="*"&&l!==k){m=l+" "+k,n=e[m]||e["* "+k];if(!n){p=b;for(o in e){j=o.split(" ");if(j[0]===l||j[0]==="*"){p=e[j[1]+" "+k];if(p){o=e[o],o===!0?n=p:p===!0&&(n=o);break}}}}!n&&!p&&f.error("No conversion from "+m.replace(" "," to ")),n!==!0&&(c=n?n(c):p(o(c)))}}return c}function bZ(a,c,d){var e=a.contents,f=a.dataTypes,g=a.responseFields,h,i,j,k;for(i in g)i in d&&(c[g[i]]=d[i]);while(f[0]==="*")f.shift(),h===b&&(h=a.mimeType||c.getResponseHeader("content-type"));if(h)for(i in e)if(e[i]&&e[i].test(h)){f.unshift(i);break}if(f[0]in d)j=f[0];else{for(i in d){if(!f[0]||a.converters[i+" "+f[0]]){j=i;break}k||(k=i)}j=j||k}if(j){j!==f[0]&&f.unshift(j);return d[j]}}function bY(a,b,c,d){if(f.isArray(b))f.each(b,function(b,e){c||bC.test(a)?d(a,e):bY(a+"["+(typeof e=="object"||f.isArray(e)?b:"")+"]",e,c,d)});else if(!c&&b!=null&&typeof b=="object")for(var e in b)bY(a+"["+e+"]",b[e],c,d);else d(a,b)}function bX(a,c,d,e,f,g){f=f||c.dataTypes[0],g=g||{},g[f]=!0;var h=a[f],i=0,j=h?h.length:0,k=a===bR,l;for(;i<j&&(k||!l);i++)l=h[i](c,d,e),typeof l=="string"&&(!k||g[l]?l=b:(c.dataTypes.unshift(l),l=bX(a,c,d,e,l,g)));(k||!l)&&!g["*"]&&(l=bX(a,c,d,e,"*",g));return l}function bW(a){return function(b,c){typeof b!="string"&&(c=b,b="*");if(f.isFunction(c)){var d=b.toLowerCase().split(bN),e=0,g=d.length,h,i,j;for(;e<g;e++)h=d[e],j=/^\+/.test(h),j&&(h=h.substr(1)||"*"),i=a[h]=a[h]||[],i[j?"unshift":"push"](c)}}}function bA(a,b,c){var d=b==="width"?a.offsetWidth:a.offsetHeight,e=b==="width"?bv:bw;if(d>0){c!=="border"&&f.each(e,function(){c||(d-=parseFloat(f.css(a,"padding"+this))||0),c==="margin"?d+=parseFloat(f.css(a,c+this))||0:d-=parseFloat(f.css(a,"border"+this+"Width"))||0});return d+"px"}d=bx(a,b,b);if(d<0||d==null)d=a.style[b]||0;d=parseFloat(d)||0,c&&f.each(e,function(){d+=parseFloat(f.css(a,"padding"+this))||0,c!=="padding"&&(d+=parseFloat(f.css(a,"border"+this+"Width"))||0),c==="margin"&&(d+=parseFloat(f.css(a,c+this))||0)});return d+"px"}function bm(a,b){b.src?f.ajax({url:b.src,async:!1,dataType:"script"}):f.globalEval((b.text||b.textContent||b.innerHTML||"").replace(be,"/*$0*/")),b.parentNode&&b.parentNode.removeChild(b)}function bl(a){f.nodeName(a,"input")?bk(a):"getElementsByTagName"in a&&f.grep(a.getElementsByTagName("input"),bk)}function bk(a){if(a.type==="checkbox"||a.type==="radio")a.defaultChecked=a.checked}function bj(a){return"getElementsByTagName"in a?a.getElementsByTagName("*"):"querySelectorAll"in a?a.querySelectorAll("*"):[]}function bi(a,b){var c;if(b.nodeType===1){b.clearAttributes&&b.clearAttributes(),b.mergeAttributes&&b.mergeAttributes(a),c=b.nodeName.toLowerCase();if(c==="object")b.outerHTML=a.outerHTML;else if(c!=="input"||a.type!=="checkbox"&&a.type!=="radio"){if(c==="option")b.selected=a.defaultSelected;else if(c==="input"||c==="textarea")b.defaultValue=a.defaultValue}else a.checked&&(b.defaultChecked=b.checked=a.checked),b.value!==a.value&&(b.value=a.value);b.removeAttribute(f.expando)}}function bh(a,b){if(b.nodeType===1&&!!f.hasData(a)){var c=f.expando,d=f.data(a),e=f.data(b,d);if(d=d[c]){var g=d.events;e=e[c]=f.extend({},d);if(g){delete e.handle,e.events={};for(var h in g)for(var i=0,j=g[h].length;i<j;i++)f.event.add(b,h+(g[h][i].namespace?".":"")+g[h][i].namespace,g[h][i],g[h][i].data)}}}}function bg(a,b){return f.nodeName(a,"table")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function W(a,b,c){b=b||0;if(f.isFunction(b))return f.grep(a,function(a,d){var e=!!b.call(a,d,a);return e===c});if(b.nodeType)return f.grep(a,function(a,d){return a===b===c});if(typeof b=="string"){var d=f.grep(a,function(a){return a.nodeType===1});if(R.test(b))return f.filter(b,d,!c);b=f.filter(b,d)}return f.grep(a,function(a,d){return f.inArray(a,b)>=0===c})}function V(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function N(a,b){return(a&&a!=="*"?a+".":"")+b.replace(z,"`").replace(A,"&")}function M(a){var b,c,d,e,g,h,i,j,k,l,m,n,o,p=[],q=[],r=f._data(this,"events");if(!(a.liveFired===this||!r||!r.live||a.target.disabled||a.button&&a.type==="click")){a.namespace&&(n=new RegExp("(^|\\.)"+a.namespace.split(".").join("\\.(?:.*\\.)?")+"(\\.|$)")),a.liveFired=this;var s=r.live.slice(0);for(i=0;i<s.length;i++)g=s[i],g.origType.replace(x,"")===a.type?q.push(g.selector):s.splice(i--,1);e=f(a.target).closest(q,a.currentTarget);for(j=0,k=e.length;j<k;j++){m=e[j];for(i=0;i<s.length;i++){g=s[i];if(m.selector===g.selector&&(!n||n.test(g.namespace))&&!m.elem.disabled){h=m.elem,d=null;if(g.preType==="mouseenter"||g.preType==="mouseleave")a.type=g.preType,d=f(a.relatedTarget).closest(g.selector)[0],d&&f.contains(h,d)&&(d=h);(!d||d!==h)&&p.push({elem:h,handleObj:g,level:m.level})}}}for(j=0,k=p.length;j<k;j++){e=p[j];if(c&&e.level>c)break;a.currentTarget=e.elem,a.data=e.handleObj.data,a.handleObj=e.handleObj,o=e.handleObj.origHandler.apply(e.elem,arguments);if(o===!1||a.isPropagationStopped()){c=e.level,o===!1&&(b=!1);if(a.isImmediatePropagationStopped())break}}return b}}function K(a,c,d){var e=f.extend({},d[0]);e.type=a,e.originalEvent={},e.liveFired=b,f.event.handle.call(c,e),e.isDefaultPrevented()&&d[0].preventDefault()}function E(){return!0}function D(){return!1}function m(a,c,d){var e=c+"defer",g=c+"queue",h=c+"mark",i=f.data(a,e,b,!0);i&&(d==="queue"||!f.data(a,g,b,!0))&&(d==="mark"||!f.data(a,h,b,!0))&&setTimeout(function(){!f.data(a,g,b,!0)&&!f.data(a,h,b,!0)&&(f.removeData(a,e,!0),i.resolve())},0)}function l(a){for(var b in a)if(b!=="toJSON")return!1;return!0}function k(a,c,d){if(d===b&&a.nodeType===1){var e="data-"+c.replace(j,"$1-$2").toLowerCase();d=a.getAttribute(e);if(typeof d=="string"){try{d=d==="true"?!0:d==="false"?!1:d==="null"?null:f.isNaN(d)?i.test(d)?f.parseJSON(d):d:parseFloat(d)}catch(g){}f.data(a,c,d)}else d=b}return d}var c=a.document,d=a.navigator,e=a.location,f=function(){function J(){if(!e.isReady){try{c.documentElement.doScroll("left")}catch(a){setTimeout(J,1);return}e.ready()}}var e=function(a,b){return new e.fn.init(a,b,h)},f=a.jQuery,g=a.$,h,i=/^(?:[^<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,j=/\S/,k=/^\s+/,l=/\s+$/,m=/\d/,n=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,o=/^[\],:{}\s]*$/,p=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,q=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,r=/(?:^|:|,)(?:\s*\[)+/g,s=/(webkit)[ \/]([\w.]+)/,t=/(opera)(?:.*version)?[ \/]([\w.]+)/,u=/(msie) ([\w.]+)/,v=/(mozilla)(?:.*? rv:([\w.]+))?/,w=/-([a-z])/ig,x=function(a,b){return b.toUpperCase()},y=d.userAgent,z,A,B,C=Object.prototype.toString,D=Object.prototype.hasOwnProperty,E=Array.prototype.push,F=Array.prototype.slice,G=String.prototype.trim,H=Array.prototype.indexOf,I={};e.fn=e.prototype={constructor:e,init:function(a,d,f){var g,h,j,k;if(!a)return this;if(a.nodeType){this.context=this[0]=a,this.length=1;return this}if(a==="body"&&!d&&c.body){this.context=c,this[0]=c.body,this.selector=a,this.length=1;return this}if(typeof a=="string"){a.charAt(0)!=="<"||a.charAt(a.length-1)!==">"||a.length<3?g=i.exec(a):g=[null,a,null];if(g&&(g[1]||!d)){if(g[1]){d=d instanceof e?d[0]:d,k=d?d.ownerDocument||d:c,j=n.exec(a),j?e.isPlainObject(d)?(a=[c.createElement(j[1])],e.fn.attr.call(a,d,!0)):a=[k.createElement(j[1])]:(j=e.buildFragment([g[1]],[k]),a=(j.cacheable?e.clone(j.fragment):j.fragment).childNodes);return e.merge(this,a)}h=c.getElementById(g[2]);if(h&&h.parentNode){if(h.id!==g[2])return f.find(a);this.length=1,this[0]=h}this.context=c,this.selector=a;return this}return!d||d.jquery?(d||f).find(a):this.constructor(d).find(a)}if(e.isFunction(a))return f.ready(a);a.selector!==b&&(this.selector=a.selector,this.context=a.context);return e.makeArray(a,this)},selector:"",jquery:"1.6.2",length:0,size:function(){return this.length},toArray:function(){return F.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=this.constructor();e.isArray(a)?E.apply(d,a):e.merge(d,a),d.prevObject=this,d.context=this.context,b==="find"?d.selector=this.selector+(this.selector?" ":"")+c:b&&(d.selector=this.selector+"."+b+"("+c+")");return d},each:function(a,b){return e.each(this,a,b)},ready:function(a){e.bindReady(),A.done(a);return this},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(F.apply(this,arguments),"slice",F.call(arguments).join(","))},map:function(a){return this.pushStack(e.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:E,sort:[].sort,splice:[].splice},e.fn.init.prototype=e.fn,e.extend=e.fn.extend=function(){var a,c,d,f,g,h,i=arguments[0]||{},j=1,k=arguments.length,l=!1;typeof i=="boolean"&&(l=i,i=arguments[1]||{},j=2),typeof i!="object"&&!e.isFunction(i)&&(i={}),k===j&&(i=this,--j);for(;j<k;j++)if((a=arguments[j])!=null)for(c in a){d=i[c],f=a[c];if(i===f)continue;l&&f&&(e.isPlainObject(f)||(g=e.isArray(f)))?(g?(g=!1,h=d&&e.isArray(d)?d:[]):h=d&&e.isPlainObject(d)?d:{},i[c]=e.extend(l,h,f)):f!==b&&(i[c]=f)}return i},e.extend({noConflict:function(b){a.$===e&&(a.$=g),b&&a.jQuery===e&&(a.jQuery=f);return e},isReady:!1,readyWait:1,holdReady:function(a){a?e.readyWait++:e.ready(!0)},ready:function(a){if(a===!0&&!--e.readyWait||a!==!0&&!e.isReady){if(!c.body)return setTimeout(e.ready,1);e.isReady=!0;if(a!==!0&&--e.readyWait>0)return;A.resolveWith(c,[e]),e.fn.trigger&&e(c).trigger("ready").unbind("ready")}},bindReady:function(){if(!A){A=e._Deferred();if(c.readyState==="complete")return setTimeout(e.ready,1);if(c.addEventListener)c.addEventListener("DOMContentLoaded",B,!1),a.addEventListener("load",e.ready,!1);else if(c.attachEvent){c.attachEvent("onreadystatechange",B),a.attachEvent("onload",e.ready);var b=!1;try{b=a.frameElement==null}catch(d){}c.documentElement.doScroll&&b&&J()}}},isFunction:function(a){return e.type(a)==="function"},isArray:Array.isArray||function(a){return e.type(a)==="array"},isWindow:function(a){return a&&typeof a=="object"&&"setInterval"in a},isNaN:function(a){return a==null||!m.test(a)||isNaN(a)},type:function(a){return a==null?String(a):I[C.call(a)]||"object"},isPlainObject:function(a){if(!a||e.type(a)!=="object"||a.nodeType||e.isWindow(a))return!1;if(a.constructor&&!D.call(a,"constructor")&&!D.call(a.constructor.prototype,"isPrototypeOf"))return!1;var c;for(c in a);return c===b||D.call(a,c)},isEmptyObject:function(a){for(var b in a)return!1;return!0},error:function(a){throw a},parseJSON:function(b){if(typeof b!="string"||!b)return null;b=e.trim(b);if(a.JSON&&a.JSON.parse)return a.JSON.parse(b);if(o.test(b.replace(p,"@").replace(q,"]").replace(r,"")))return(new Function("return "+b))();e.error("Invalid JSON: "+b)},parseXML:function(b,c,d){a.DOMParser?(d=new DOMParser,c=d.parseFromString(b,"text/xml")):(c=new ActiveXObject("Microsoft.XMLDOM"),c.async="false",c.loadXML(b)),d=c.documentElement,(!d||!d.nodeName||d.nodeName==="parsererror")&&e.error("Invalid XML: "+b);return c},noop:function(){},globalEval:function(b){b&&j.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(w,x)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,c,d){var f,g=0,h=a.length,i=h===b||e.isFunction(a);if(d){if(i){for(f in a)if(c.apply(a[f],d)===!1)break}else for(;g<h;)if(c.apply(a[g++],d)===!1)break}else if(i){for(f in a)if(c.call(a[f],f,a[f])===!1)break}else for(;g<h;)if(c.call(a[g],g,a[g++])===!1)break;return a},trim:G?function(a){return a==null?"":G.call(a)}:function(a){return a==null?"":(a+"").replace(k,"").replace(l,"")},makeArray:function(a,b){var c=b||[];if(a!=null){var d=e.type(a);a.length==null||d==="string"||d==="function"||d==="regexp"||e.isWindow(a)?E.call(c,a):e.merge(c,a)}return c},inArray:function(a,b){if(H)return H.call(b,a);for(var c=0,d=b.length;c<d;c++)if(b[c]===a)return c;return-1},merge:function(a,c){var d=a.length,e=0;if(typeof c.length=="number")for(var f=c.length;e<f;e++)a[d++]=c[e];else while(c[e]!==b)a[d++]=c[e++];a.length=d;return a},grep:function(a,b,c){var d=[],e;c=!!c;for(var f=0,g=a.length;f<g;f++)e=!!b(a[f],f),c!==e&&d.push(a[f]);return d},map:function(a,c,d){var f,g,h=[],i=0,j=a.length,k=a instanceof e||j!==b&&typeof j=="number"&&(j>0&&a[0]&&a[j-1]||j===0||e.isArray(a));if(k)for(;i<j;i++)f=c(a[i],i,d),f!=null&&(h[h.length]=f);else for(g in a)f=c(a[g],g,d),f!=null&&(h[h.length]=f);return h.concat.apply([],h)},guid:1,proxy:function(a,c){if(typeof c=="string"){var d=a[c];c=a,a=d}if(!e.isFunction(a))return b;var f=F.call(arguments,2),g=function(){return a.apply(c,f.concat(F.call(arguments)))};g.guid=a.guid=a.guid||g.guid||e.guid++;return g},access:function(a,c,d,f,g,h){var i=a.length;if(typeof c=="object"){for(var j in c)e.access(a,j,c[j],f,g,d);return a}if(d!==b){f=!h&&f&&e.isFunction(d);for(var k=0;k<i;k++)g(a[k],c,f?d.call(a[k],k,g(a[k],c)):d,h);return a}return i?g(a[0],c):b},now:function(){return(new Date).getTime()},uaMatch:function(a){a=a.toLowerCase();var b=s.exec(a)||t.exec(a)||u.exec(a)||a.indexOf("compatible")<0&&v.exec(a)||[];return{browser:b[1]||"",version:b[2]||"0"}},sub:function(){function a(b,c){return new a.fn.init(b,c)}e.extend(!0,a,this),a.superclass=this,a.fn=a.prototype=this(),a.fn.constructor=a,a.sub=this.sub,a.fn.init=function(d,f){f&&f instanceof e&&!(f instanceof a)&&(f=a(f));return e.fn.init.call(this,d,f,b)},a.fn.init.prototype=a.fn;var b=a(c);return a},browser:{}}),e.each("Boolean Number String Function Array Date RegExp Object".split(" "),function(a,b){I["[object "+b+"]"]=b.toLowerCase()}),z=e.uaMatch(y),z.browser&&(e.browser[z.browser]=!0,e.browser.version=z.version),e.browser.webkit&&(e.browser.safari=!0),j.test(" ")&&(k=/^[\s\xA0]+/,l=/[\s\xA0]+$/),h=e(c),c.addEventListener?B=function(){c.removeEventListener("DOMContentLoaded",B,!1),e.ready()}:c.attachEvent&&(B=function(){c.readyState==="complete"&&(c.detachEvent("onreadystatechange",B),e.ready())});return e}(),g="done fail isResolved isRejected promise then always pipe".split(" "),h=[].slice;f.extend({_Deferred:function(){var a=[],b,c,d,e={done:function(){if(!d){var c=arguments,g,h,i,j,k;b&&(k=b,b=0);for(g=0,h=c.length;g<h;g++)i=c[g],j=f.type(i),j==="array"?e.done.apply(e,i):j==="function"&&a.push(i);k&&e.resolveWith(k[0],k[1])}return this},resolveWith:function(e,f){if(!d&&!b&&!c){f=f||[],c=1;try{while(a[0])a.shift().apply(e,f)}finally{b=[e,f],c=0}}return this},resolve:function(){e.resolveWith(this,arguments);return this},isResolved:function(){return!!c||!!b},cancel:function(){d=1,a=[];return this}};return e},Deferred:function(a){var b=f._Deferred(),c=f._Deferred(),d;f.extend(b,{then:function(a,c){b.done(a).fail(c);return this},always:function(){return b.done.apply(b,arguments).fail.apply(this,arguments)},fail:c.done,rejectWith:c.resolveWith,reject:c.resolve,isRejected:c.isResolved,pipe:function(a,c){return f.Deferred(function(d){f.each({done:[a,"resolve"],fail:[c,"reject"]},function(a,c){var e=c[0],g=c[1],h;f.isFunction(e)?b[a](function(){h=e.apply(this,arguments),h&&f.isFunction(h.promise)?h.promise().then(d.resolve,d.reject):d[g](h)}):b[a](d[g])})}).promise()},promise:function(a){if(a==null){if(d)return d;d=a={}}var c=g.length;while(c--)a[g[c]]=b[g[c]];return a}}),b.done(c.cancel).fail(b.cancel),delete b.cancel,a&&a.call(b,b);return b},when:function(a){function i(a){return function(c){b[a]=arguments.length>1?h.call(arguments,0):c,--e||g.resolveWith(g,h.call(b,0))}}var b=arguments,c=0,d=b.length,e=d,g=d<=1&&a&&f.isFunction(a.promise)?a:f.Deferred();if(d>1){for(;c<d;c++)b[c]&&f.isFunction(b[c].promise)?b[c].promise().then(i(c),g.reject):--e;e||g.resolveWith(g,b)}else g!==a&&g.resolveWith(g,d?[a]:[]);return g.promise()}}),f.support=function(){var a=c.createElement("div"),b=c.documentElement,d,e,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u;a.setAttribute("className","t"),a.innerHTML="   <link/><table></table><a href='/a' style='top:1px;float:left;opacity:.55;'>a</a><input type='checkbox'/>",d=a.getElementsByTagName("*"),e=a.getElementsByTagName("a")[0];if(!d||!d.length||!e)return{};g=c.createElement("select"),h=g.appendChild(c.createElement("option")),i=a.getElementsByTagName("input")[0],k={leadingWhitespace:a.firstChild.nodeType===3,tbody:!a.getElementsByTagName("tbody").length,htmlSerialize:!!a.getElementsByTagName("link").length,style:/top/.test(e.getAttribute("style")),hrefNormalized:e.getAttribute("href")==="/a",opacity:/^0.55$/.test(e.style.opacity),cssFloat:!!e.style.cssFloat,checkOn:i.value==="on",optSelected:h.selected,getSetAttribute:a.className!=="t",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0},i.checked=!0,k.noCloneChecked=i.cloneNode(!0).checked,g.disabled=!0,k.optDisabled=!h.disabled;try{delete a.test}catch(v){k.deleteExpando=!1}!a.addEventListener&&a.attachEvent&&a.fireEvent&&(a.attachEvent("onclick",function(){k.noCloneEvent=!1}),a.cloneNode(!0).fireEvent("onclick")),i=c.createElement("input"),i.value="t",i.setAttribute("type","radio"),k.radioValue=i.value==="t",i.setAttribute("checked","checked"),a.appendChild(i),l=c.createDocumentFragment(),l.appendChild(a.firstChild),k.checkClone=l.cloneNode(!0).cloneNode(!0).lastChild.checked,a.innerHTML="",a.style.width=a.style.paddingLeft="1px",m=c.getElementsByTagName("body")[0],o=c.createElement(m?"div":"body"),p={visibility:"hidden",width:0,height:0,border:0,margin:0},m&&f.extend(p,{position:"absolute",left:-1e3,top:-1e3});for(t in p)o.style[t]=p[t];o.appendChild(a),n=m||b,n.insertBefore(o,n.firstChild),k.appendChecked=i.checked,k.boxModel=a.offsetWidth===2,"zoom"in a.style&&(a.style.display="inline",a.style.zoom=1,k.inlineBlockNeedsLayout=a.offsetWidth===2,a.style.display="",a.innerHTML="<div style='width:4px;'></div>",k.shrinkWrapBlocks=a.offsetWidth!==2),a.innerHTML="<table><tr><td style='padding:0;border:0;display:none'></td><td>t</td></tr></table>",q=a.getElementsByTagName("td"),u=q[0].offsetHeight===0,q[0].style.display="",q[1].style.display="none",k.reliableHiddenOffsets=u&&q[0].offsetHeight===0,a.innerHTML="",c.defaultView&&c.defaultView.getComputedStyle&&(j=c.createElement("div"),j.style.width="0",j.style.marginRight="0",a.appendChild(j),k.reliableMarginRight=(parseInt((c.defaultView.getComputedStyle(j,null)||{marginRight:0}).marginRight,10)||0)===0),o.innerHTML="",n.removeChild(o);if(a.attachEvent)for(t in{submit:1,change:1,focusin:1})s="on"+t,u=s in a,u||(a.setAttribute(s,"return;"),u=typeof a[s]=="function"),k[t+"Bubbles"]=u;o=l=g=h=m=j=a=i=null;return k}(),f.boxModel=f.support.boxModel;var i=/^(?:\{.*\}|\[.*\])$/,j=/([a-z])([A-Z])/g;f.extend({cache:{},uuid:0,expando:"jQuery"+(f.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){a=a.nodeType?f.cache[a[f.expando]]:a[f.expando];return!!a&&!l(a)},data:function(a,c,d,e){if(!!f.acceptData(a)){var g=f.expando,h=typeof c=="string",i,j=a.nodeType,k=j?f.cache:a,l=j?a[f.expando]:a[f.expando]&&f.expando;if((!l||e&&l&&!k[l][g])&&h&&d===b)return;l||(j?a[f.expando]=l=++f.uuid:l=f.expando),k[l]||(k[l]={},j||(k[l].toJSON=f.noop));if(typeof c=="object"||typeof c=="function")e?k[l][g]=f.extend(k[l][g],c):k[l]=f.extend(k[l],c);i=k[l],e&&(i[g]||(i[g]={}),i=i[g]),d!==b&&(i[f.camelCase(c)]=d);if(c==="events"&&!i[c])return i[g]&&i[g].events;return h?i[f.camelCase(c)]||i[c]:i}},removeData:function(b,c,d){if(!!f.acceptData(b)){var e=f.expando,g=b.nodeType,h=g?f.cache:b,i=g?b[f.expando]:f.expando;if(!h[i])return;if(c){var j=d?h[i][e]:h[i];if(j){delete j[c];if(!l(j))return}}if(d){delete h[i][e];if(!l(h[i]))return}var k=h[i][e];f.support.deleteExpando||h!=a?delete h[i]:h[i]=null,k?(h[i]={},g||(h[i].toJSON=f.noop),h[i][e]=k):g&&(f.support.deleteExpando?delete b[f.expando]:b.removeAttribute?b.removeAttribute(f.expando):b[f.expando]=null)}},_data:function(a,b,c){return f.data(a,b,c,!0)},acceptData:function(a){if(a.nodeName){var b=f.noData[a.nodeName.toLowerCase()];if(b)return b!==!0&&a.getAttribute("classid")===b}return!0}}),f.fn.extend({data:function(a,c){var d=null;if(typeof a=="undefined"){if(this.length){d=f.data(this[0]);if(this[0].nodeType===1){var e=this[0].attributes,g;for(var h=0,i=e.length;h<i;h++)g=e[h].name,g.indexOf("data-")===0&&(g=f.camelCase(g.substring(5)),k(this[0],g,d[g]))}}return d}if(typeof a=="object")return this.each(function(){f.data(this,a)});var j=a.split(".");j[1]=j[1]?"."+j[1]:"";if(c===b){d=this.triggerHandler("getData"+j[1]+"!",[j[0]]),d===b&&this.length&&(d=f.data(this[0],a),d=k(this[0],a,d));return d===b&&j[1]?this.data(j[0]):d}return this.each(function(){var b=f(this),d=[j[0],c];b.triggerHandler("setData"+j[1]+"!",d),f.data(this,a,c),b.triggerHandler("changeData"+j[1]+"!",d)})},removeData:function(a){return this.each(function(){f.removeData(this,a)})}}),f.extend({_mark:function(a,c){a&&(c=(c||"fx")+"mark",f.data(a,c,(f.data(a,c,b,!0)||0)+1,!0))},_unmark:function(a,c,d){a!==!0&&(d=c,c=a,a=!1);if(c){d=d||"fx";var e=d+"mark",g=a?0:(f.data(c,e,b,!0)||1)-1;g?f.data(c,e,g,!0):(f.removeData(c,e,!0),m(c,d,"mark"))}},queue:function(a,c,d){if(a){c=(c||"fx")+"queue";var e=f.data(a,c,b,!0);d&&(!e||f.isArray(d)?e=f.data(a,c,f.makeArray(d),!0):e.push(d));return e||[]}},dequeue:function(a,b){b=b||"fx";var c=f.queue(a,b),d=c.shift(),e;d==="inprogress"&&(d=c.shift()),d&&(b==="fx"&&c.unshift("inprogress"),d.call(a,function(){f.dequeue(a,b)})),c.length||(f.removeData(a,b+"queue",!0),m(a,b,"queue"))}}),f.fn.extend({queue:function(a,c){typeof a!="string"&&(c=a,a="fx");if(c===b)return f.queue(this[0],a);return this.each(function(){var b=f.queue(this,a,c);a==="fx"&&b[0]!=="inprogress"&&f.dequeue(this,a)})},dequeue:function(a){return this.each(function(){f.dequeue(this,a)})},delay:function(a,b){a=f.fx?f.fx.speeds[a]||a:a,b=b||"fx";return this.queue(b,function(){var c=this;setTimeout(function(){f.dequeue(c,b)},a)})},clearQueue:function(a){return this.queue(a||"fx",[])},promise:function(a,c){function m(){--h||d.resolveWith(e,[e])}typeof a!="string"&&(c=a,a=b),a=a||"fx";var d=f.Deferred(),e=this,g=e.length,h=1,i=a+"defer",j=a+"queue",k=a+"mark",l;while(g--)if(l=f.data(e[g],i,b,!0)||(f.data(e[g],j,b,!0)||f.data(e[g],k,b,!0))&&f.data(e[g],i,f._Deferred(),!0))h++,l.done(m);m();return d.promise()}});var n=/[\n\t\r]/g,o=/\s+/,p=/\r/g,q=/^(?:button|input)$/i,r=/^(?:button|input|object|select|textarea)$/i,s=/^a(?:rea)?$/i,t=/^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,u=/\:|^on/,v,w;f.fn.extend({attr:function(a,b){return f.access(this,a,b,!0,f.attr)},removeAttr:function(a){return this.each(function(){f.removeAttr(this,a)})},prop:function(a,b){return f.access(this,a,b,!0,f.prop)},removeProp:function(a){a=f.propFix[a]||a;return this.each(function(){try{this[a]=b,delete this[a]}catch(c){}})},addClass:function(a){var b,c,d,e,g,h,i;if(f.isFunction(a))return this.each(function(b){f(this).addClass(a.call(this,b,this.className))});if(a&&typeof a=="string"){b=a.split(o);for(c=0,d=this.length;c<d;c++){e=this[c];if(e.nodeType===1)if(!e.className&&b.length===1)e.className=a;else{g=" "+e.className+" ";for(h=0,i=b.length;h<i;h++)~g.indexOf(" "+b[h]+" ")||(g+=b[h]+" ");e.className=f.trim(g)}}}return this},removeClass:function(a){var c,d,e,g,h,i,j;if(f.isFunction(a))return this.each(function(b){f(this).removeClass(a.call(this,b,this.className))});if(a&&typeof a=="string"||a===b){c=(a||"").split(o);for(d=0,e=this.length;d<e;d++){g=this[d];if(g.nodeType===1&&g.className)if(a){h=(" "+g.className+" ").replace(n," ");for(i=0,j=c.length;i<j;i++)h=h.replace(" "+c[i]+" "," ");g.className=f.trim(h)}else g.className=""}}return this},toggleClass:function(a,b){var c=typeof a,d=typeof b=="boolean";if(f.isFunction(a))return this.each(function(c){f(this).toggleClass(a.call(this,c,this.className,b),b)});return this.each(function(){if(c==="string"){var e,g=0,h=f(this),i=b,j=a.split(o);while(e=j[g++])i=d?i:!h.hasClass(e),h[i?"addClass":"removeClass"](e)}else if(c==="undefined"||c==="boolean")this.className&&f._data(this,"__className__",this.className),this.className=this.className||a===!1?"":f._data(this,"__className__")||""})},hasClass:function(a){var b=" "+a+" ";for(var c=0,d=this.length;c<d;c++)if((" "+this[c].className+" ").replace(n," ").indexOf(b)>-1)return!0;return!1},val:function(a){var c,d,e=this[0];if(!arguments.length){if(e){c=f.valHooks[e.nodeName.toLowerCase()]||f.valHooks[e.type];if(c&&"get"in c&&(d=c.get(e,"value"))!==b)return d;d=e.value;return typeof d=="string"?d.replace(p,""):d==null?"":d}return b}var g=f.isFunction(a);return this.each(function(d){var e=f(this),h;if(this.nodeType===1){g?h=a.call(this,d,e.val()):h=a,h==null?h="":typeof h=="number"?h+="":f.isArray(h)&&(h=f.map(h,function(a){return a==null?"":a+""})),c=f.valHooks[this.nodeName.toLowerCase()]||f.valHooks[this.type];if(!c||!("set"in c)||c.set(this,h,"value")===b)this.value=h}})}}),f.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return!b||b.specified?a.value:a.text}},select:{get:function(a){var b,c=a.selectedIndex,d=[],e=a.options,g=a.type==="select-one";if(c<0)return null;for(var h=g?c:0,i=g?c+1:e.length;h<i;h++){var j=e[h];if(j.selected&&(f.support.optDisabled?!j.disabled:j.getAttribute("disabled")===null)&&(!j.parentNode.disabled||!f.nodeName(j.parentNode,"optgroup"))){b=f(j).val();if(g)return b;d.push(b)}}if(g&&!d.length&&e.length)return f(e[c]).val();return d},set:function(a,b){var c=f.makeArray(b);f(a).find("option").each(function(){this.selected=f.inArray(f(this).val(),c)>=0}),c.length||(a.selectedIndex=-1);return c}}},attrFn:{val:!0,css:!0,html:!0,text:!0,data:!0,width:!0,height:!0,offset:!0},attrFix:{tabindex:"tabIndex"},attr:function(a,c,d,e){var g=a.nodeType;if(!a||g===3||g===8||g===2)return b;if(e&&c in f.attrFn)return f(a)[c](d);if(!("getAttribute"in a))return f.prop(a,c,d);var h,i,j=g!==1||!f.isXMLDoc(a);j&&(c=f.attrFix[c]||c,i=f.attrHooks[c],i||(t.test(c)?i=w:v&&c!=="className"&&(f.nodeName(a,"form")||u.test(c))&&(i=v)));if(d!==b){if(d===null){f.removeAttr(a,c);return b}if(i&&"set"in i&&j&&(h=i.set(a,d,c))!==b)return h;a.setAttribute(c,""+d);return d}if(i&&"get"in i&&j&&(h=i.get(a,c))!==null)return h;h=a.getAttribute(c);return h===null?b:h},removeAttr:function(a,b){var c;a.nodeType===1&&(b=f.attrFix[b]||b,f.support.getSetAttribute?a.removeAttribute(b):(f.attr(a,b,""),a.removeAttributeNode(a.getAttributeNode(b))),t.test(b)&&(c=f.propFix[b]||b)in a&&(a[c]=!1))},attrHooks:{type:{set:function(a,b){if(q.test(a.nodeName)&&a.parentNode)f.error("type property can't be changed");else if(!f.support.radioValue&&b==="radio"&&f.nodeName(a,"input")){var c=a.value;a.setAttribute("type",b),c&&(a.value=c);return b}}},tabIndex:{get:function(a){var c=a.getAttributeNode("tabIndex");return c&&c.specified?parseInt(c.value,10):r.test(a.nodeName)||s.test(a.nodeName)&&a.href?0:b}},value:{get:function(a,b){if(v&&f.nodeName(a,"button"))return v.get(a,b);return b in a?a.value:null},set:function(a,b,c){if(v&&f.nodeName(a,"button"))return v.set(a,b,c);a.value=b}}},propFix:{tabindex:"tabIndex",readonly:"readOnly","for":"htmlFor","class":"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"},prop:function(a,c,d){var e=a.nodeType;if(!a||e===3||e===8||e===2)return b;var g,h,i=e!==1||!f.isXMLDoc(a);i&&(c=f.propFix[c]||c,h=f.propHooks[c]);return d!==b?h&&"set"in h&&(g=h.set(a,d,c))!==b?g:a[c]=d:h&&"get"in h&&(g=h.get(a,c))!==b?g:a[c]},propHooks:{}}),w={get:function(a,c){return f.prop(a,c)?c.toLowerCase():b},set:function(a,b,c){var d;b===!1?f.removeAttr(a,c):(d=f.propFix[c]||c,d in a&&(a[d]=!0),a.setAttribute(c,c.toLowerCase()));return c}},f.support.getSetAttribute||(f.attrFix=f.propFix,v=f.attrHooks.name=f.attrHooks.title=f.valHooks.button={get:function(a,c){var d;d=a.getAttributeNode(c);return d&&d.nodeValue!==""?d.nodeValue:b},set:function(a,b,c){var d=a.getAttributeNode(c);if(d){d.nodeValue=b;return b}}},f.each(["width","height"],function(a,b){f.attrHooks[b]=f.extend(f.attrHooks[b],{set:function(a,c){if(c===""){a.setAttribute(b,"auto");return c}}})})),f.support.hrefNormalized||f.each(["href","src","width","height"],function(a,c){f.attrHooks[c]=f.extend(f.attrHooks[c],{get:function(a){var d=a.getAttribute(c,2);return d===null?b:d}})}),f.support.style||(f.attrHooks.style={get:function(a){return a.style.cssText.toLowerCase()||b},set:function(a,b){return a.style.cssText=""+b}}),f.support.optSelected||(f.propHooks.selected=f.extend(f.propHooks.selected,{get:function(a){var b=a.parentNode;b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex)}})),f.support.checkOn||f.each(["radio","checkbox"],function(){f.valHooks[this]={get:function(a){return a.getAttribute("value")===null?"on":a.value}}}),f.each(["radio","checkbox"],function(){f.valHooks[this]=f.extend(f.valHooks[this],{set:function(a,b){if(f.isArray(b))return a.checked=f.inArray(f(a).val(),b)>=0}})});var x=/\.(.*)$/,y=/^(?:textarea|input|select)$/i,z=/\./g,A=/ /g,B=/[^\w\s.|`]/g,C=function(a){return a.replace(B,"\\$&")};f.event={add:function(a,c,d,e){if(a.nodeType!==3&&a.nodeType!==8){if(d===!1)d=D;else if(!d)return;var g,h;d.handler&&(g=d,d=g.handler),d.guid||(d.guid=f.guid++);var i=f._data(a);if(!i)return;var j=i.events,k=i.handle;j||(i.events=j={}),k||(i.handle=k=function(a){return typeof f!="undefined"&&(!a||f.event.triggered!==a.type)?f.event.handle.apply(k.elem,arguments):b}),k.elem=a,c=c.split(" ");var l,m=0,n;while(l=c[m++]){h=g?f.extend({},g):{handler:d,data:e},l.indexOf(".")>-1?(n=l.split("."),l=n.shift(),h.namespace=n.slice(0).sort().join(".")):(n=[],h.namespace=""),h.type=l,h.guid||(h.guid=d.guid);var o=j[l],p=f.event.special[l]||{};if(!o){o=j[l]=[];if(!p.setup||p.setup.call(a,e,n,k)===!1)a.addEventListener?a.addEventListener(l,k,!1):a.attachEvent&&a.attachEvent("on"+l,k)}p.add&&(p.add.call(a,h),h.handler.guid||(h.handler.guid=d.guid)),o.push(h),f.event.global[l]=!0}a=null}},global:{},remove:function(a,c,d,e){if(a.nodeType!==3&&a.nodeType!==8){d===!1&&(d=D);var g,h,i,j,k=0,l,m,n,o,p,q,r,s=f.hasData(a)&&f._data(a),t=s&&s.events;if(!s||!t)return;c&&c.type&&(d=c.handler,c=c.type);if(!c||typeof c=="string"&&c.charAt(0)==="."){c=c||"";for(h in t)f.event.remove(a,h+c);return}c=c.split(" ");while(h=c[k++]){r=h,q=null,l=h.indexOf(".")<0,m=[],l||(m=h.split("."),h=m.shift(),n=new RegExp("(^|\\.)"+f.map(m.slice(0).sort(),C).join("\\.(?:.*\\.)?")+"(\\.|$)")),p=t[h];if(!p)continue;if(!d){for(j=0;j<p.length;j++){q=p[j];if(l||n.test(q.namespace))f.event.remove(a,r,q.handler,j),p.splice(j--,1)}continue}o=f.event.special[h]||{};for(j=e||0;j<p.length;j++){q=p[j];if(d.guid===q.guid){if(l||n.test(q.namespace))e==null&&p.splice(j--,1),o.remove&&o.remove.call(a,q);if(e!=null)break}}if(p.length===0||e!=null&&p.length===1)(!o.teardown||o.teardown.call(a,m)===!1)&&f.removeEvent(a,h,s.handle),g=null,delete t[h]}if(f.isEmptyObject(t)){var u=s.handle;u&&(u.elem=null),delete s.events,delete s.handle,f.isEmptyObject(s)&&f.removeData(a,b,!0)}}},customEvent:{getData:!0,setData:!0,changeData:!0},trigger:function(c,d,e,g){var h=c.type||c,i=[],j;h.indexOf("!")>=0&&(h=h.slice(0,-1),j=!0),h.indexOf(".")>=0&&(i=h.split("."),h=i.
-shift(),i.sort());if(!!e&&!f.event.customEvent[h]||!!f.event.global[h]){c=typeof c=="object"?c[f.expando]?c:new f.Event(h,c):new f.Event(h),c.type=h,c.exclusive=j,c.namespace=i.join("."),c.namespace_re=new RegExp("(^|\\.)"+i.join("\\.(?:.*\\.)?")+"(\\.|$)");if(g||!e)c.preventDefault(),c.stopPropagation();if(!e){f.each(f.cache,function(){var a=f.expando,b=this[a];b&&b.events&&b.events[h]&&f.event.trigger(c,d,b.handle.elem)});return}if(e.nodeType===3||e.nodeType===8)return;c.result=b,c.target=e,d=d!=null?f.makeArray(d):[],d.unshift(c);var k=e,l=h.indexOf(":")<0?"on"+h:"";do{var m=f._data(k,"handle");c.currentTarget=k,m&&m.apply(k,d),l&&f.acceptData(k)&&k[l]&&k[l].apply(k,d)===!1&&(c.result=!1,c.preventDefault()),k=k.parentNode||k.ownerDocument||k===c.target.ownerDocument&&a}while(k&&!c.isPropagationStopped());if(!c.isDefaultPrevented()){var n,o=f.event.special[h]||{};if((!o._default||o._default.call(e.ownerDocument,c)===!1)&&(h!=="click"||!f.nodeName(e,"a"))&&f.acceptData(e)){try{l&&e[h]&&(n=e[l],n&&(e[l]=null),f.event.triggered=h,e[h]())}catch(p){}n&&(e[l]=n),f.event.triggered=b}}return c.result}},handle:function(c){c=f.event.fix(c||a.event);var d=((f._data(this,"events")||{})[c.type]||[]).slice(0),e=!c.exclusive&&!c.namespace,g=Array.prototype.slice.call(arguments,0);g[0]=c,c.currentTarget=this;for(var h=0,i=d.length;h<i;h++){var j=d[h];if(e||c.namespace_re.test(j.namespace)){c.handler=j.handler,c.data=j.data,c.handleObj=j;var k=j.handler.apply(this,g);k!==b&&(c.result=k,k===!1&&(c.preventDefault(),c.stopPropagation()));if(c.isImmediatePropagationStopped())break}}return c.result},props:"altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),fix:function(a){if(a[f.expando])return a;var d=a;a=f.Event(d);for(var e=this.props.length,g;e;)g=this.props[--e],a[g]=d[g];a.target||(a.target=a.srcElement||c),a.target.nodeType===3&&(a.target=a.target.parentNode),!a.relatedTarget&&a.fromElement&&(a.relatedTarget=a.fromElement===a.target?a.toElement:a.fromElement);if(a.pageX==null&&a.clientX!=null){var h=a.target.ownerDocument||c,i=h.documentElement,j=h.body;a.pageX=a.clientX+(i&&i.scrollLeft||j&&j.scrollLeft||0)-(i&&i.clientLeft||j&&j.clientLeft||0),a.pageY=a.clientY+(i&&i.scrollTop||j&&j.scrollTop||0)-(i&&i.clientTop||j&&j.clientTop||0)}a.which==null&&(a.charCode!=null||a.keyCode!=null)&&(a.which=a.charCode!=null?a.charCode:a.keyCode),!a.metaKey&&a.ctrlKey&&(a.metaKey=a.ctrlKey),!a.which&&a.button!==b&&(a.which=a.button&1?1:a.button&2?3:a.button&4?2:0);return a},guid:1e8,proxy:f.proxy,special:{ready:{setup:f.bindReady,teardown:f.noop},live:{add:function(a){f.event.add(this,N(a.origType,a.selector),f.extend({},a,{handler:M,guid:a.handler.guid}))},remove:function(a){f.event.remove(this,N(a.origType,a.selector),a)}},beforeunload:{setup:function(a,b,c){f.isWindow(this)&&(this.onbeforeunload=c)},teardown:function(a,b){this.onbeforeunload===b&&(this.onbeforeunload=null)}}}},f.removeEvent=c.removeEventListener?function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c,!1)}:function(a,b,c){a.detachEvent&&a.detachEvent("on"+b,c)},f.Event=function(a,b){if(!this.preventDefault)return new f.Event(a,b);a&&a.type?(this.originalEvent=a,this.type=a.type,this.isDefaultPrevented=a.defaultPrevented||a.returnValue===!1||a.getPreventDefault&&a.getPreventDefault()?E:D):this.type=a,b&&f.extend(this,b),this.timeStamp=f.now(),this[f.expando]=!0},f.Event.prototype={preventDefault:function(){this.isDefaultPrevented=E;var a=this.originalEvent;!a||(a.preventDefault?a.preventDefault():a.returnValue=!1)},stopPropagation:function(){this.isPropagationStopped=E;var a=this.originalEvent;!a||(a.stopPropagation&&a.stopPropagation(),a.cancelBubble=!0)},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=E,this.stopPropagation()},isDefaultPrevented:D,isPropagationStopped:D,isImmediatePropagationStopped:D};var F=function(a){var b=a.relatedTarget,c=!1,d=a.type;a.type=a.data,b!==this&&(b&&(c=f.contains(this,b)),c||(f.event.handle.apply(this,arguments),a.type=d))},G=function(a){a.type=a.data,f.event.handle.apply(this,arguments)};f.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(a,b){f.event.special[a]={setup:function(c){f.event.add(this,b,c&&c.selector?G:F,a)},teardown:function(a){f.event.remove(this,b,a&&a.selector?G:F)}}}),f.support.submitBubbles||(f.event.special.submit={setup:function(a,b){if(!f.nodeName(this,"form"))f.event.add(this,"click.specialSubmit",function(a){var b=a.target,c=b.type;(c==="submit"||c==="image")&&f(b).closest("form").length&&K("submit",this,arguments)}),f.event.add(this,"keypress.specialSubmit",function(a){var b=a.target,c=b.type;(c==="text"||c==="password")&&f(b).closest("form").length&&a.keyCode===13&&K("submit",this,arguments)});else return!1},teardown:function(a){f.event.remove(this,".specialSubmit")}});if(!f.support.changeBubbles){var H,I=function(a){var b=a.type,c=a.value;b==="radio"||b==="checkbox"?c=a.checked:b==="select-multiple"?c=a.selectedIndex>-1?f.map(a.options,function(a){return a.selected}).join("-"):"":f.nodeName(a,"select")&&(c=a.selectedIndex);return c},J=function(c){var d=c.target,e,g;if(!!y.test(d.nodeName)&&!d.readOnly){e=f._data(d,"_change_data"),g=I(d),(c.type!=="focusout"||d.type!=="radio")&&f._data(d,"_change_data",g);if(e===b||g===e)return;if(e!=null||g)c.type="change",c.liveFired=b,f.event.trigger(c,arguments[1],d)}};f.event.special.change={filters:{focusout:J,beforedeactivate:J,click:function(a){var b=a.target,c=f.nodeName(b,"input")?b.type:"";(c==="radio"||c==="checkbox"||f.nodeName(b,"select"))&&J.call(this,a)},keydown:function(a){var b=a.target,c=f.nodeName(b,"input")?b.type:"";(a.keyCode===13&&!f.nodeName(b,"textarea")||a.keyCode===32&&(c==="checkbox"||c==="radio")||c==="select-multiple")&&J.call(this,a)},beforeactivate:function(a){var b=a.target;f._data(b,"_change_data",I(b))}},setup:function(a,b){if(this.type==="file")return!1;for(var c in H)f.event.add(this,c+".specialChange",H[c]);return y.test(this.nodeName)},teardown:function(a){f.event.remove(this,".specialChange");return y.test(this.nodeName)}},H=f.event.special.change.filters,H.focus=H.beforeactivate}f.support.focusinBubbles||f.each({focus:"focusin",blur:"focusout"},function(a,b){function e(a){var c=f.event.fix(a);c.type=b,c.originalEvent={},f.event.trigger(c,null,c.target),c.isDefaultPrevented()&&a.preventDefault()}var d=0;f.event.special[b]={setup:function(){d++===0&&c.addEventListener(a,e,!0)},teardown:function(){--d===0&&c.removeEventListener(a,e,!0)}}}),f.each(["bind","one"],function(a,c){f.fn[c]=function(a,d,e){var g;if(typeof a=="object"){for(var h in a)this[c](h,d,a[h],e);return this}if(arguments.length===2||d===!1)e=d,d=b;c==="one"?(g=function(a){f(this).unbind(a,g);return e.apply(this,arguments)},g.guid=e.guid||f.guid++):g=e;if(a==="unload"&&c!=="one")this.one(a,d,e);else for(var i=0,j=this.length;i<j;i++)f.event.add(this[i],a,g,d);return this}}),f.fn.extend({unbind:function(a,b){if(typeof a=="object"&&!a.preventDefault)for(var c in a)this.unbind(c,a[c]);else for(var d=0,e=this.length;d<e;d++)f.event.remove(this[d],a,b);return this},delegate:function(a,b,c,d){return this.live(b,c,d,a)},undelegate:function(a,b,c){return arguments.length===0?this.unbind("live"):this.die(b,null,c,a)},trigger:function(a,b){return this.each(function(){f.event.trigger(a,b,this)})},triggerHandler:function(a,b){if(this[0])return f.event.trigger(a,b,this[0],!0)},toggle:function(a){var b=arguments,c=a.guid||f.guid++,d=0,e=function(c){var e=(f.data(this,"lastToggle"+a.guid)||0)%d;f.data(this,"lastToggle"+a.guid,e+1),c.preventDefault();return b[e].apply(this,arguments)||!1};e.guid=c;while(d<b.length)b[d++].guid=c;return this.click(e)},hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}});var L={focus:"focusin",blur:"focusout",mouseenter:"mouseover",mouseleave:"mouseout"};f.each(["live","die"],function(a,c){f.fn[c]=function(a,d,e,g){var h,i=0,j,k,l,m=g||this.selector,n=g?this:f(this.context);if(typeof a=="object"&&!a.preventDefault){for(var o in a)n[c](o,d,a[o],m);return this}if(c==="die"&&!a&&g&&g.charAt(0)==="."){n.unbind(g);return this}if(d===!1||f.isFunction(d))e=d||D,d=b;a=(a||"").split(" ");while((h=a[i++])!=null){j=x.exec(h),k="",j&&(k=j[0],h=h.replace(x,""));if(h==="hover"){a.push("mouseenter"+k,"mouseleave"+k);continue}l=h,L[h]?(a.push(L[h]+k),h=h+k):h=(L[h]||h)+k;if(c==="live")for(var p=0,q=n.length;p<q;p++)f.event.add(n[p],"live."+N(h,m),{data:d,selector:m,handler:e,origType:h,origHandler:e,preType:l});else n.unbind("live."+N(h,m),e)}return this}}),f.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error".split(" "),function(a,b){f.fn[b]=function(a,c){c==null&&(c=a,a=null);return arguments.length>0?this.bind(b,a,c):this.trigger(b)},f.attrFn&&(f.attrFn[b]=!0)}),function(){function u(a,b,c,d,e,f){for(var g=0,h=d.length;g<h;g++){var i=d[g];if(i){var j=!1;i=i[a];while(i){if(i.sizcache===c){j=d[i.sizset];break}if(i.nodeType===1){f||(i.sizcache=c,i.sizset=g);if(typeof b!="string"){if(i===b){j=!0;break}}else if(k.filter(b,[i]).length>0){j=i;break}}i=i[a]}d[g]=j}}}function t(a,b,c,d,e,f){for(var g=0,h=d.length;g<h;g++){var i=d[g];if(i){var j=!1;i=i[a];while(i){if(i.sizcache===c){j=d[i.sizset];break}i.nodeType===1&&!f&&(i.sizcache=c,i.sizset=g);if(i.nodeName.toLowerCase()===b){j=i;break}i=i[a]}d[g]=j}}}var a=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,d=0,e=Object.prototype.toString,g=!1,h=!0,i=/\\/g,j=/\W/;[0,0].sort(function(){h=!1;return 0});var k=function(b,d,f,g){f=f||[],d=d||c;var h=d;if(d.nodeType!==1&&d.nodeType!==9)return[];if(!b||typeof b!="string")return f;var i,j,n,o,q,r,s,t,u=!0,w=k.isXML(d),x=[],y=b;do{a.exec(""),i=a.exec(y);if(i){y=i[3],x.push(i[1]);if(i[2]){o=i[3];break}}}while(i);if(x.length>1&&m.exec(b))if(x.length===2&&l.relative[x[0]])j=v(x[0]+x[1],d);else{j=l.relative[x[0]]?[d]:k(x.shift(),d);while(x.length)b=x.shift(),l.relative[b]&&(b+=x.shift()),j=v(b,j)}else{!g&&x.length>1&&d.nodeType===9&&!w&&l.match.ID.test(x[0])&&!l.match.ID.test(x[x.length-1])&&(q=k.find(x.shift(),d,w),d=q.expr?k.filter(q.expr,q.set)[0]:q.set[0]);if(d){q=g?{expr:x.pop(),set:p(g)}:k.find(x.pop(),x.length===1&&(x[0]==="~"||x[0]==="+")&&d.parentNode?d.parentNode:d,w),j=q.expr?k.filter(q.expr,q.set):q.set,x.length>0?n=p(j):u=!1;while(x.length)r=x.pop(),s=r,l.relative[r]?s=x.pop():r="",s==null&&(s=d),l.relative[r](n,s,w)}else n=x=[]}n||(n=j),n||k.error(r||b);if(e.call(n)==="[object Array]")if(!u)f.push.apply(f,n);else if(d&&d.nodeType===1)for(t=0;n[t]!=null;t++)n[t]&&(n[t]===!0||n[t].nodeType===1&&k.contains(d,n[t]))&&f.push(j[t]);else for(t=0;n[t]!=null;t++)n[t]&&n[t].nodeType===1&&f.push(j[t]);else p(n,f);o&&(k(o,h,f,g),k.uniqueSort(f));return f};k.uniqueSort=function(a){if(r){g=h,a.sort(r);if(g)for(var b=1;b<a.length;b++)a[b]===a[b-1]&&a.splice(b--,1)}return a},k.matches=function(a,b){return k(a,null,null,b)},k.matchesSelector=function(a,b){return k(b,null,null,[a]).length>0},k.find=function(a,b,c){var d;if(!a)return[];for(var e=0,f=l.order.length;e<f;e++){var g,h=l.order[e];if(g=l.leftMatch[h].exec(a)){var j=g[1];g.splice(1,1);if(j.substr(j.length-1)!=="\\"){g[1]=(g[1]||"").replace(i,""),d=l.find[h](g,b,c);if(d!=null){a=a.replace(l.match[h],"");break}}}}d||(d=typeof b.getElementsByTagName!="undefined"?b.getElementsByTagName("*"):[]);return{set:d,expr:a}},k.filter=function(a,c,d,e){var f,g,h=a,i=[],j=c,m=c&&c[0]&&k.isXML(c[0]);while(a&&c.length){for(var n in l.filter)if((f=l.leftMatch[n].exec(a))!=null&&f[2]){var o,p,q=l.filter[n],r=f[1];g=!1,f.splice(1,1);if(r.substr(r.length-1)==="\\")continue;j===i&&(i=[]);if(l.preFilter[n]){f=l.preFilter[n](f,j,d,i,e,m);if(!f)g=o=!0;else if(f===!0)continue}if(f)for(var s=0;(p=j[s])!=null;s++)if(p){o=q(p,f,s,j);var t=e^!!o;d&&o!=null?t?g=!0:j[s]=!1:t&&(i.push(p),g=!0)}if(o!==b){d||(j=i),a=a.replace(l.match[n],"");if(!g)return[];break}}if(a===h)if(g==null)k.error(a);else break;h=a}return j},k.error=function(a){throw"Syntax error, unrecognized expression: "+a};var l=k.selectors={order:["ID","NAME","TAG"],match:{ID:/#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,CLASS:/\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,NAME:/\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/,ATTR:/\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(?:(['"])(.*?)\3|(#?(?:[\w\u00c0-\uFFFF\-]|\\.)*)|)|)\s*\]/,TAG:/^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/,CHILD:/:(only|nth|last|first)-child(?:\(\s*(even|odd|(?:[+\-]?\d+|(?:[+\-]?\d*)?n\s*(?:[+\-]\s*\d+)?))\s*\))?/,POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/,PSEUDO:/:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/},leftMatch:{},attrMap:{"class":"className","for":"htmlFor"},attrHandle:{href:function(a){return a.getAttribute("href")},type:function(a){return a.getAttribute("type")}},relative:{"+":function(a,b){var c=typeof b=="string",d=c&&!j.test(b),e=c&&!d;d&&(b=b.toLowerCase());for(var f=0,g=a.length,h;f<g;f++)if(h=a[f]){while((h=h.previousSibling)&&h.nodeType!==1);a[f]=e||h&&h.nodeName.toLowerCase()===b?h||!1:h===b}e&&k.filter(b,a,!0)},">":function(a,b){var c,d=typeof b=="string",e=0,f=a.length;if(d&&!j.test(b)){b=b.toLowerCase();for(;e<f;e++){c=a[e];if(c){var g=c.parentNode;a[e]=g.nodeName.toLowerCase()===b?g:!1}}}else{for(;e<f;e++)c=a[e],c&&(a[e]=d?c.parentNode:c.parentNode===b);d&&k.filter(b,a,!0)}},"":function(a,b,c){var e,f=d++,g=u;typeof b=="string"&&!j.test(b)&&(b=b.toLowerCase(),e=b,g=t),g("parentNode",b,f,a,e,c)},"~":function(a,b,c){var e,f=d++,g=u;typeof b=="string"&&!j.test(b)&&(b=b.toLowerCase(),e=b,g=t),g("previousSibling",b,f,a,e,c)}},find:{ID:function(a,b,c){if(typeof b.getElementById!="undefined"&&!c){var d=b.getElementById(a[1]);return d&&d.parentNode?[d]:[]}},NAME:function(a,b){if(typeof b.getElementsByName!="undefined"){var c=[],d=b.getElementsByName(a[1]);for(var e=0,f=d.length;e<f;e++)d[e].getAttribute("name")===a[1]&&c.push(d[e]);return c.length===0?null:c}},TAG:function(a,b){if(typeof b.getElementsByTagName!="undefined")return b.getElementsByTagName(a[1])}},preFilter:{CLASS:function(a,b,c,d,e,f){a=" "+a[1].replace(i,"")+" ";if(f)return a;for(var g=0,h;(h=b[g])!=null;g++)h&&(e^(h.className&&(" "+h.className+" ").replace(/[\t\n\r]/g," ").indexOf(a)>=0)?c||d.push(h):c&&(b[g]=!1));return!1},ID:function(a){return a[1].replace(i,"")},TAG:function(a,b){return a[1].replace(i,"").toLowerCase()},CHILD:function(a){if(a[1]==="nth"){a[2]||k.error(a[0]),a[2]=a[2].replace(/^\+|\s*/g,"");var b=/(-?)(\d*)(?:n([+\-]?\d*))?/.exec(a[2]==="even"&&"2n"||a[2]==="odd"&&"2n+1"||!/\D/.test(a[2])&&"0n+"+a[2]||a[2]);a[2]=b[1]+(b[2]||1)-0,a[3]=b[3]-0}else a[2]&&k.error(a[0]);a[0]=d++;return a},ATTR:function(a,b,c,d,e,f){var g=a[1]=a[1].replace(i,"");!f&&l.attrMap[g]&&(a[1]=l.attrMap[g]),a[4]=(a[4]||a[5]||"").replace(i,""),a[2]==="~="&&(a[4]=" "+a[4]+" ");return a},PSEUDO:function(b,c,d,e,f){if(b[1]==="not")if((a.exec(b[3])||"").length>1||/^\w/.test(b[3]))b[3]=k(b[3],null,null,c);else{var g=k.filter(b[3],c,d,!0^f);d||e.push.apply(e,g);return!1}else if(l.match.POS.test(b[0])||l.match.CHILD.test(b[0]))return!0;return b},POS:function(a){a.unshift(!0);return a}},filters:{enabled:function(a){return a.disabled===!1&&a.type!=="hidden"},disabled:function(a){return a.disabled===!0},checked:function(a){return a.checked===!0},selected:function(a){a.parentNode&&a.parentNode.selectedIndex;return a.selected===!0},parent:function(a){return!!a.firstChild},empty:function(a){return!a.firstChild},has:function(a,b,c){return!!k(c[3],a).length},header:function(a){return/h\d/i.test(a.nodeName)},text:function(a){var b=a.getAttribute("type"),c=a.type;return a.nodeName.toLowerCase()==="input"&&"text"===c&&(b===c||b===null)},radio:function(a){return a.nodeName.toLowerCase()==="input"&&"radio"===a.type},checkbox:function(a){return a.nodeName.toLowerCase()==="input"&&"checkbox"===a.type},file:function(a){return a.nodeName.toLowerCase()==="input"&&"file"===a.type},password:function(a){return a.nodeName.toLowerCase()==="input"&&"password"===a.type},submit:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"submit"===a.type},image:function(a){return a.nodeName.toLowerCase()==="input"&&"image"===a.type},reset:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"reset"===a.type},button:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&"button"===a.type||b==="button"},input:function(a){return/input|select|textarea|button/i.test(a.nodeName)},focus:function(a){return a===a.ownerDocument.activeElement}},setFilters:{first:function(a,b){return b===0},last:function(a,b,c,d){return b===d.length-1},even:function(a,b){return b%2===0},odd:function(a,b){return b%2===1},lt:function(a,b,c){return b<c[3]-0},gt:function(a,b,c){return b>c[3]-0},nth:function(a,b,c){return c[3]-0===b},eq:function(a,b,c){return c[3]-0===b}},filter:{PSEUDO:function(a,b,c,d){var e=b[1],f=l.filters[e];if(f)return f(a,c,b,d);if(e==="contains")return(a.textContent||a.innerText||k.getText([a])||"").indexOf(b[3])>=0;if(e==="not"){var g=b[3];for(var h=0,i=g.length;h<i;h++)if(g[h]===a)return!1;return!0}k.error(e)},CHILD:function(a,b){var c=b[1],d=a;switch(c){case"only":case"first":while(d=d.previousSibling)if(d.nodeType===1)return!1;if(c==="first")return!0;d=a;case"last":while(d=d.nextSibling)if(d.nodeType===1)return!1;return!0;case"nth":var e=b[2],f=b[3];if(e===1&&f===0)return!0;var g=b[0],h=a.parentNode;if(h&&(h.sizcache!==g||!a.nodeIndex)){var i=0;for(d=h.firstChild;d;d=d.nextSibling)d.nodeType===1&&(d.nodeIndex=++i);h.sizcache=g}var j=a.nodeIndex-f;return e===0?j===0:j%e===0&&j/e>=0}},ID:function(a,b){return a.nodeType===1&&a.getAttribute("id")===b},TAG:function(a,b){return b==="*"&&a.nodeType===1||a.nodeName.toLowerCase()===b},CLASS:function(a,b){return(" "+(a.className||a.getAttribute("class"))+" ").indexOf(b)>-1},ATTR:function(a,b){var c=b[1],d=l.attrHandle[c]?l.attrHandle[c](a):a[c]!=null?a[c]:a.getAttribute(c),e=d+"",f=b[2],g=b[4];return d==null?f==="!=":f==="="?e===g:f==="*="?e.indexOf(g)>=0:f==="~="?(" "+e+" ").indexOf(g)>=0:g?f==="!="?e!==g:f==="^="?e.indexOf(g)===0:f==="$="?e.substr(e.length-g.length)===g:f==="|="?e===g||e.substr(0,g.length+1)===g+"-":!1:e&&d!==!1},POS:function(a,b,c,d){var e=b[2],f=l.setFilters[e];if(f)return f(a,c,b,d)}}},m=l.match.POS,n=function(a,b){return"\\"+(b-0+1)};for(var o in l.match)l.match[o]=new RegExp(l.match[o].source+/(?![^\[]*\])(?![^\(]*\))/.source),l.leftMatch[o]=new RegExp(/(^(?:.|\r|\n)*?)/.source+l.match[o].source.replace(/\\(\d+)/g,n));var p=function(a,b){a=Array.prototype.slice.call(a,0);if(b){b.push.apply(b,a);return b}return a};try{Array.prototype.slice.call(c.documentElement.childNodes,0)[0].nodeType}catch(q){p=function(a,b){var c=0,d=b||[];if(e.call(a)==="[object Array]")Array.prototype.push.apply(d,a);else if(typeof a.length=="number")for(var f=a.length;c<f;c++)d.push(a[c]);else for(;a[c];c++)d.push(a[c]);return d}}var r,s;c.documentElement.compareDocumentPosition?r=function(a,b){if(a===b){g=!0;return 0}if(!a.compareDocumentPosition||!b.compareDocumentPosition)return a.compareDocumentPosition?-1:1;return a.compareDocumentPosition(b)&4?-1:1}:(r=function(a,b){if(a===b){g=!0;return 0}if(a.sourceIndex&&b.sourceIndex)return a.sourceIndex-b.sourceIndex;var c,d,e=[],f=[],h=a.parentNode,i=b.parentNode,j=h;if(h===i)return s(a,b);if(!h)return-1;if(!i)return 1;while(j)e.unshift(j),j=j.parentNode;j=i;while(j)f.unshift(j),j=j.parentNode;c=e.length,d=f.length;for(var k=0;k<c&&k<d;k++)if(e[k]!==f[k])return s(e[k],f[k]);return k===c?s(a,f[k],-1):s(e[k],b,1)},s=function(a,b,c){if(a===b)return c;var d=a.nextSibling;while(d){if(d===b)return-1;d=d.nextSibling}return 1}),k.getText=function(a){var b="",c;for(var d=0;a[d];d++)c=a[d],c.nodeType===3||c.nodeType===4?b+=c.nodeValue:c.nodeType!==8&&(b+=k.getText(c.childNodes));return b},function(){var a=c.createElement("div"),d="script"+(new Date).getTime(),e=c.documentElement;a.innerHTML="<a name='"+d+"'/>",e.insertBefore(a,e.firstChild),c.getElementById(d)&&(l.find.ID=function(a,c,d){if(typeof c.getElementById!="undefined"&&!d){var e=c.getElementById(a[1]);return e?e.id===a[1]||typeof e.getAttributeNode!="undefined"&&e.getAttributeNode("id").nodeValue===a[1]?[e]:b:[]}},l.filter.ID=function(a,b){var c=typeof a.getAttributeNode!="undefined"&&a.getAttributeNode("id");return a.nodeType===1&&c&&c.nodeValue===b}),e.removeChild(a),e=a=null}(),function(){var a=c.createElement("div");a.appendChild(c.createComment("")),a.getElementsByTagName("*").length>0&&(l.find.TAG=function(a,b){var c=b.getElementsByTagName(a[1]);if(a[1]==="*"){var d=[];for(var e=0;c[e];e++)c[e].nodeType===1&&d.push(c[e]);c=d}return c}),a.innerHTML="<a href='#'></a>",a.firstChild&&typeof a.firstChild.getAttribute!="undefined"&&a.firstChild.getAttribute("href")!=="#"&&(l.attrHandle.href=function(a){return a.getAttribute("href",2)}),a=null}(),c.querySelectorAll&&function(){var a=k,b=c.createElement("div"),d="__sizzle__";b.innerHTML="<p class='TEST'></p>";if(!b.querySelectorAll||b.querySelectorAll(".TEST").length!==0){k=function(b,e,f,g){e=e||c;if(!g&&!k.isXML(e)){var h=/^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(b);if(h&&(e.nodeType===1||e.nodeType===9)){if(h[1])return p(e.getElementsByTagName(b),f);if(h[2]&&l.find.CLASS&&e.getElementsByClassName)return p(e.getElementsByClassName(h[2]),f)}if(e.nodeType===9){if(b==="body"&&e.body)return p([e.body],f);if(h&&h[3]){var i=e.getElementById(h[3]);if(!i||!i.parentNode)return p([],f);if(i.id===h[3])return p([i],f)}try{return p(e.querySelectorAll(b),f)}catch(j){}}else if(e.nodeType===1&&e.nodeName.toLowerCase()!=="object"){var m=e,n=e.getAttribute("id"),o=n||d,q=e.parentNode,r=/^\s*[+~]/.test(b);n?o=o.replace(/'/g,"\\$&"):e.setAttribute("id",o),r&&q&&(e=e.parentNode);try{if(!r||q)return p(e.querySelectorAll("[id='"+o+"'] "+b),f)}catch(s){}finally{n||m.removeAttribute("id")}}}return a(b,e,f,g)};for(var e in a)k[e]=a[e];b=null}}(),function(){var a=c.documentElement,b=a.matchesSelector||a.mozMatchesSelector||a.webkitMatchesSelector||a.msMatchesSelector;if(b){var d=!b.call(c.createElement("div"),"div"),e=!1;try{b.call(c.documentElement,"[test!='']:sizzle")}catch(f){e=!0}k.matchesSelector=function(a,c){c=c.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!k.isXML(a))try{if(e||!l.match.PSEUDO.test(c)&&!/!=/.test(c)){var f=b.call(a,c);if(f||!d||a.document&&a.document.nodeType!==11)return f}}catch(g){}return k(c,null,null,[a]).length>0}}}(),function(){var a=c.createElement("div");a.innerHTML="<div class='test e'></div><div class='test'></div>";if(!!a.getElementsByClassName&&a.getElementsByClassName("e").length!==0){a.lastChild.className="e";if(a.getElementsByClassName("e").length===1)return;l.order.splice(1,0,"CLASS"),l.find.CLASS=function(a,b,c){if(typeof b.getElementsByClassName!="undefined"&&!c)return b.getElementsByClassName(a[1])},a=null}}(),c.documentElement.contains?k.contains=function(a,b){return a!==b&&(a.contains?a.contains(b):!0)}:c.documentElement.compareDocumentPosition?k.contains=function(a,b){return!!(a.compareDocumentPosition(b)&16)}:k.contains=function(){return!1},k.isXML=function(a){var b=(a?a.ownerDocument||a:0).documentElement;return b?b.nodeName!=="HTML":!1};var v=function(a,b){var c,d=[],e="",f=b.nodeType?[b]:b;while(c=l.match.PSEUDO.exec(a))e+=c[0],a=a.replace(l.match.PSEUDO,"");a=l.relative[a]?a+"*":a;for(var g=0,h=f.length;g<h;g++)k(a,f[g],d);return k.filter(e,d)};f.find=k,f.expr=k.selectors,f.expr[":"]=f.expr.filters,f.unique=k.uniqueSort,f.text=k.getText,f.isXMLDoc=k.isXML,f.contains=k.contains}();var O=/Until$/,P=/^(?:parents|prevUntil|prevAll)/,Q=/,/,R=/^.[^:#\[\.,]*$/,S=Array.prototype.slice,T=f.expr.match.POS,U={children:!0,contents:!0,next:!0,prev:!0};f.fn.extend({find:function(a){var b=this,c,d;if(typeof a!="string")return f(a).filter(function(){for(c=0,d=b.length;c<d;c++)if(f.contains(b[c],this))return!0});var e=this.pushStack("","find",a),g,h,i;for(c=0,d=this.length;c<d;c++){g=e.length,f.find(a,this[c],e);if(c>0)for(h=g;h<e.length;h++)for(i=0;i<g;i++)if(e[i]===e[h]){e.splice(h--,1);break}}return e},has:function(a){var b=f(a);return this.filter(function(){for(var a=0,c=b.length;a<c;a++)if(f.contains(this,b[a]))return!0})},not:function(a){return this.pushStack(W(this,a,!1),"not",a)},filter:function(a){return this.pushStack(W(this,a,!0),"filter",a)},is:function(a){return!!a&&(typeof a=="string"?f.filter(a,this).length>0:this.filter(a).length>0)},closest:function(a,b){var c=[],d,e,g=this[0];if(f.isArray(a)){var h,i,j={},k=1;if(g&&a.length){for(d=0,e=a.length;d<e;d++)i=a[d],j[i]||(j[i]=T.test(i)?f(i,b||this.context):i);while(g&&g.ownerDocument&&g!==b){for(i in j)h=j[i],(h.jquery?h.index(g)>-1:f(g).is(h))&&c.push({selector:i,elem:g,level:k});g=g.parentNode,k++}}return c}var l=T.test(a)||typeof a!="string"?f(a,b||this.context):0;for(d=0,e=this.length;d<e;d++){g=this[d];while(g){if(l?l.index(g)>-1:f.find.matchesSelector(g,a)){c.push(g);break}g=g.parentNode;if(!g||!g.ownerDocument||g===b||g.nodeType===11)break}}c=c.length>1?f.unique(c):c;return this.pushStack(c,"closest",a)},index:function(a){if(!a||typeof a=="string")return f.inArray(this[0],a?f(a):this.parent().children());return f.inArray(a.jquery?a[0]:a,this)},add:function(a,b){var c=typeof a=="string"?f(a,b):f.makeArray(a&&a.nodeType?[a]:a),d=f.merge(this.get(),c);return this.pushStack(V(c[0])||V(d[0])?d:f.unique(d))},andSelf:function(){return this.add(this.prevObject)}}),f.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return f.dir(a,"parentNode")},parentsUntil:function(a,b,c){return f.dir(a,"parentNode",c)},next:function(a){return f.nth(a,2,"nextSibling")},prev:function(a){return f.nth(a,2,"previousSibling")},nextAll:function(a){return f.dir(a,"nextSibling")},prevAll:function(a){return f.dir(a,"previousSibling")},nextUntil:function(a,b,c){return f.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return f.dir(a,"previousSibling",c)},siblings:function(a){return f.sibling(a.parentNode.firstChild,a)},children:function(a){return f.sibling(a.firstChild)},contents:function(a){return f.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:f.makeArray(a.childNodes)}},function(a,b){f.fn[a]=function(c,d){var e=f.map(this,b,c),g=S.call(arguments);O.test(a)||(d=c),d&&typeof d=="string"&&(e=f.filter(d,e)),e=this.length>1&&!U[a]?f.unique(e):e,(this.length>1||Q.test(d))&&P.test(a)&&(e=e.reverse());return this.pushStack(e,a,g.join(","))}}),f.extend({filter:function(a,b,c){c&&(a=":not("+a+")");return b.length===1?f.find.matchesSelector(b[0],a)?[b[0]]:[]:f.find.matches(a,b)},dir:function(a,c,d){var e=[],g=a[c];while(g&&g.nodeType!==9&&(d===b||g.nodeType!==1||!f(g).is(d)))g.nodeType===1&&e.push(g),g=g[c];return e},nth:function(a,b,c,d){b=b||1;var e=0;for(;a;a=a[c])if(a.nodeType===1&&++e===b)break;return a},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var X=/ jQuery\d+="(?:\d+|null)"/g,Y=/^\s+/,Z=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,$=/<([\w:]+)/,_=/<tbody/i,ba=/<|&#?\w+;/,bb=/<(?:script|object|embed|option|style)/i,bc=/checked\s*(?:[^=]|=\s*.checked.)/i,bd=/\/(java|ecma)script/i,be=/^\s*<!(?:\[CDATA\[|\-\-)/,bf={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_default:[0,"",""]};bf.optgroup=bf.option,bf.tbody=bf.tfoot=bf.colgroup=bf.caption=bf.thead,bf.th=bf.td,f.support.htmlSerialize||(bf._default=[1,"div<div>","</div>"]),f.fn.extend({text:function(a){if(f.isFunction(a))return this.each(function(b){var c=f(this);c.text(a.call(this,b,c.text()))});if(typeof a!="object"&&a!==b)return this.empty().append((this[0]&&this[0].ownerDocument||c).createTextNode(a));return f.text(this)},wrapAll:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapAll(a.call(this,b))});if(this[0]){var b=f(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapInner(a.call(this,b))});return this.each(function(){var b=f(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){f(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){f.nodeName(this,"body")||f(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=f(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,f(arguments[0]).toArray());return a}},remove:function(a,b){for(var c=0,d;(d=this[c])!=null;c++)if(!a||f.filter(a,[d]).length)!b&&d.nodeType===1&&(f.cleanData(d.getElementsByTagName("*")),f.cleanData([d])),d.parentNode&&d.parentNode.removeChild(d);return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++){b.nodeType===1&&f.cleanData(b.getElementsByTagName("*"));while(b.firstChild)b.removeChild(b.firstChild)}return this},clone:function(a,b){a=a==null?!1:a,b=b==null?a:b;return this.map(function(){return f.clone(this,a,b)})},html:function(a){if(a===b)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(X,""):null;if(typeof a=="string"&&!bb.test(a)&&(f.support.leadingWhitespace||!Y.test(a))&&!bf[($.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Z,"<$1></$2>");try{for(var c=0,d=this.length;c<d;c++)this[c].nodeType===1&&(f.cleanData(this[c].getElementsByTagName("*")),this[c].innerHTML=a)}catch(e){this.empty().append(a)}}else f.isFunction(a)?this.each(function(b){var c=f(this);c.html(a.call(this,b,c.html()))}):this.empty().append(a);return this},replaceWith:function(a){if(this[0]&&this[0].parentNode){if(f.isFunction(a))return this.each(function(b){var c=f(this),d=c.html();c.replaceWith(a.call(this,b,d))});typeof a!="string"&&(a=f(a).detach());return this.each(function(){var b=this.nextSibling,c=this.parentNode;f(this).remove(),b?f(b).before(a):f(c).append(a)})}return this.length?this.pushStack(f(f.isFunction(a)?a():a),"replaceWith",a):this},detach:function(a){return this.remove(a,!0)},domManip:function(a,c,d){var e,g,h,i,j=a[0],k=[];if(!f.support.checkClone&&arguments.length===3&&typeof j=="string"&&bc.test(j))return this.each(function(){f(this).domManip(a,c,d,!0)});if(f.isFunction(j))return this.each(function(e){var g=f(this);a[0]=j.call(this,e,c?g.html():b),g.domManip(a,c,d)});if(this[0]){i=j&&j.parentNode,f.support.parentNode&&i&&i.nodeType===11&&i.childNodes.length===this.length?e={fragment:i}:e=f.buildFragment(a,this,k),h=e.fragment,h.childNodes.length===1?g=h=h.firstChild:g=h.firstChild;if(g){c=c&&f.nodeName(g,"tr");for(var l=0,m=this.length,n=m-1;l<m;l++)d.call(c?bg(this[l],g):this[l],e.cacheable||m>1&&l<n?f.clone(h,!0,!0):h)}k.length&&f.each(k,bm)}return this}}),f.buildFragment=function(a,b,d){var e,g,h,i;b&&b[0]&&(i=b[0].ownerDocument||b[0]),i.createDocumentFragment||(i=c),a.length===1&&typeof a[0]=="string"&&a[0].length<512&&i===c&&a[0].charAt(0)==="<"&&!bb.test(a[0])&&(f.support.checkClone||!bc.test(a[0]))&&(g=!0,h=f.fragments[a[0]],h&&h!==1&&(e=h)),e||(e=i.createDocumentFragment(),f.clean(a,i,e,d)),g&&(f.fragments[a[0]]=h?e:1);return{fragment:e,cacheable:g}},f.fragments={},f.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){f.fn[a]=function(c){var d=[],e=f(c),g=this.length===1&&this[0].parentNode;if(g&&g.nodeType===11&&g.childNodes.length===1&&e.length===1){e[b](this[0]);return this}for(var h=0,i=e.length;h<i;h++){var j=(h>0?this.clone(!0):this).get();f(e[h])[b](j),d=d.concat(j
-)}return this.pushStack(d,a,e.selector)}}),f.extend({clone:function(a,b,c){var d=a.cloneNode(!0),e,g,h;if((!f.support.noCloneEvent||!f.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!f.isXMLDoc(a)){bi(a,d),e=bj(a),g=bj(d);for(h=0;e[h];++h)bi(e[h],g[h])}if(b){bh(a,d);if(c){e=bj(a),g=bj(d);for(h=0;e[h];++h)bh(e[h],g[h])}}e=g=null;return d},clean:function(a,b,d,e){var g;b=b||c,typeof b.createElement=="undefined"&&(b=b.ownerDocument||b[0]&&b[0].ownerDocument||c);var h=[],i;for(var j=0,k;(k=a[j])!=null;j++){typeof k=="number"&&(k+="");if(!k)continue;if(typeof k=="string")if(!ba.test(k))k=b.createTextNode(k);else{k=k.replace(Z,"<$1></$2>");var l=($.exec(k)||["",""])[1].toLowerCase(),m=bf[l]||bf._default,n=m[0],o=b.createElement("div");o.innerHTML=m[1]+k+m[2];while(n--)o=o.lastChild;if(!f.support.tbody){var p=_.test(k),q=l==="table"&&!p?o.firstChild&&o.firstChild.childNodes:m[1]==="<table>"&&!p?o.childNodes:[];for(i=q.length-1;i>=0;--i)f.nodeName(q[i],"tbody")&&!q[i].childNodes.length&&q[i].parentNode.removeChild(q[i])}!f.support.leadingWhitespace&&Y.test(k)&&o.insertBefore(b.createTextNode(Y.exec(k)[0]),o.firstChild),k=o.childNodes}var r;if(!f.support.appendChecked)if(k[0]&&typeof (r=k.length)=="number")for(i=0;i<r;i++)bl(k[i]);else bl(k);k.nodeType?h.push(k):h=f.merge(h,k)}if(d){g=function(a){return!a.type||bd.test(a.type)};for(j=0;h[j];j++)if(e&&f.nodeName(h[j],"script")&&(!h[j].type||h[j].type.toLowerCase()==="text/javascript"))e.push(h[j].parentNode?h[j].parentNode.removeChild(h[j]):h[j]);else{if(h[j].nodeType===1){var s=f.grep(h[j].getElementsByTagName("script"),g);h.splice.apply(h,[j+1,0].concat(s))}d.appendChild(h[j])}}return h},cleanData:function(a){var b,c,d=f.cache,e=f.expando,g=f.event.special,h=f.support.deleteExpando;for(var i=0,j;(j=a[i])!=null;i++){if(j.nodeName&&f.noData[j.nodeName.toLowerCase()])continue;c=j[f.expando];if(c){b=d[c]&&d[c][e];if(b&&b.events){for(var k in b.events)g[k]?f.event.remove(j,k):f.removeEvent(j,k,b.handle);b.handle&&(b.handle.elem=null)}h?delete j[f.expando]:j.removeAttribute&&j.removeAttribute(f.expando),delete d[c]}}}});var bn=/alpha\([^)]*\)/i,bo=/opacity=([^)]*)/,bp=/([A-Z]|^ms)/g,bq=/^-?\d+(?:px)?$/i,br=/^-?\d/,bs=/^[+\-]=/,bt=/[^+\-\.\de]+/g,bu={position:"absolute",visibility:"hidden",display:"block"},bv=["Left","Right"],bw=["Top","Bottom"],bx,by,bz;f.fn.css=function(a,c){if(arguments.length===2&&c===b)return this;return f.access(this,a,c,!0,function(a,c,d){return d!==b?f.style(a,c,d):f.css(a,c)})},f.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=bx(a,"opacity","opacity");return c===""?"1":c}return a.style.opacity}}},cssNumber:{fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":f.support.cssFloat?"cssFloat":"styleFloat"},style:function(a,c,d,e){if(!!a&&a.nodeType!==3&&a.nodeType!==8&&!!a.style){var g,h,i=f.camelCase(c),j=a.style,k=f.cssHooks[i];c=f.cssProps[i]||i;if(d===b){if(k&&"get"in k&&(g=k.get(a,!1,e))!==b)return g;return j[c]}h=typeof d;if(h==="number"&&isNaN(d)||d==null)return;h==="string"&&bs.test(d)&&(d=+d.replace(bt,"")+parseFloat(f.css(a,c)),h="number"),h==="number"&&!f.cssNumber[i]&&(d+="px");if(!k||!("set"in k)||(d=k.set(a,d))!==b)try{j[c]=d}catch(l){}}},css:function(a,c,d){var e,g;c=f.camelCase(c),g=f.cssHooks[c],c=f.cssProps[c]||c,c==="cssFloat"&&(c="float");if(g&&"get"in g&&(e=g.get(a,!0,d))!==b)return e;if(bx)return bx(a,c)},swap:function(a,b,c){var d={};for(var e in b)d[e]=a.style[e],a.style[e]=b[e];c.call(a);for(e in b)a.style[e]=d[e]}}),f.curCSS=f.css,f.each(["height","width"],function(a,b){f.cssHooks[b]={get:function(a,c,d){var e;if(c){if(a.offsetWidth!==0)return bA(a,b,d);f.swap(a,bu,function(){e=bA(a,b,d)});return e}},set:function(a,b){if(!bq.test(b))return b;b=parseFloat(b);if(b>=0)return b+"px"}}}),f.support.opacity||(f.cssHooks.opacity={get:function(a,b){return bo.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?parseFloat(RegExp.$1)/100+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle;c.zoom=1;var e=f.isNaN(b)?"":"alpha(opacity="+b*100+")",g=d&&d.filter||c.filter||"";c.filter=bn.test(g)?g.replace(bn,e):g+" "+e}}),f(function(){f.support.reliableMarginRight||(f.cssHooks.marginRight={get:function(a,b){var c;f.swap(a,{display:"inline-block"},function(){b?c=bx(a,"margin-right","marginRight"):c=a.style.marginRight});return c}})}),c.defaultView&&c.defaultView.getComputedStyle&&(by=function(a,c){var d,e,g;c=c.replace(bp,"-$1").toLowerCase();if(!(e=a.ownerDocument.defaultView))return b;if(g=e.getComputedStyle(a,null))d=g.getPropertyValue(c),d===""&&!f.contains(a.ownerDocument.documentElement,a)&&(d=f.style(a,c));return d}),c.documentElement.currentStyle&&(bz=function(a,b){var c,d=a.currentStyle&&a.currentStyle[b],e=a.runtimeStyle&&a.runtimeStyle[b],f=a.style;!bq.test(d)&&br.test(d)&&(c=f.left,e&&(a.runtimeStyle.left=a.currentStyle.left),f.left=b==="fontSize"?"1em":d||0,d=f.pixelLeft+"px",f.left=c,e&&(a.runtimeStyle.left=e));return d===""?"auto":d}),bx=by||bz,f.expr&&f.expr.filters&&(f.expr.filters.hidden=function(a){var b=a.offsetWidth,c=a.offsetHeight;return b===0&&c===0||!f.support.reliableHiddenOffsets&&(a.style.display||f.css(a,"display"))==="none"},f.expr.filters.visible=function(a){return!f.expr.filters.hidden(a)});var bB=/%20/g,bC=/\[\]$/,bD=/\r?\n/g,bE=/#.*$/,bF=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,bG=/^(?:color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,bH=/^(?:about|app|app\-storage|.+\-extension|file|widget):$/,bI=/^(?:GET|HEAD)$/,bJ=/^\/\//,bK=/\?/,bL=/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,bM=/^(?:select|textarea)/i,bN=/\s+/,bO=/([?&])_=[^&]*/,bP=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,bQ=f.fn.load,bR={},bS={},bT,bU;try{bT=e.href}catch(bV){bT=c.createElement("a"),bT.href="",bT=bT.href}bU=bP.exec(bT.toLowerCase())||[],f.fn.extend({load:function(a,c,d){if(typeof a!="string"&&bQ)return bQ.apply(this,arguments);if(!this.length)return this;var e=a.indexOf(" ");if(e>=0){var g=a.slice(e,a.length);a=a.slice(0,e)}var h="GET";c&&(f.isFunction(c)?(d=c,c=b):typeof c=="object"&&(c=f.param(c,f.ajaxSettings.traditional),h="POST"));var i=this;f.ajax({url:a,type:h,dataType:"html",data:c,complete:function(a,b,c){c=a.responseText,a.isResolved()&&(a.done(function(a){c=a}),i.html(g?f("<div>").append(c.replace(bL,"")).find(g):c)),d&&i.each(d,[c,b,a])}});return this},serialize:function(){return f.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?f.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||bM.test(this.nodeName)||bG.test(this.type))}).map(function(a,b){var c=f(this).val();return c==null?null:f.isArray(c)?f.map(c,function(a,c){return{name:b.name,value:a.replace(bD,"\r\n")}}):{name:b.name,value:c.replace(bD,"\r\n")}}).get()}}),f.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){f.fn[b]=function(a){return this.bind(b,a)}}),f.each(["get","post"],function(a,c){f[c]=function(a,d,e,g){f.isFunction(d)&&(g=g||e,e=d,d=b);return f.ajax({type:c,url:a,data:d,success:e,dataType:g})}}),f.extend({getScript:function(a,c){return f.get(a,b,c,"script")},getJSON:function(a,b,c){return f.get(a,b,c,"json")},ajaxSetup:function(a,b){b?f.extend(!0,a,f.ajaxSettings,b):(b=a,a=f.extend(!0,f.ajaxSettings,b));for(var c in{context:1,url:1})c in b?a[c]=b[c]:c in f.ajaxSettings&&(a[c]=f.ajaxSettings[c]);return a},ajaxSettings:{url:bT,isLocal:bH.test(bU[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":"*/*"},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String,"text html":!0,"text json":f.parseJSON,"text xml":f.parseXML}},ajaxPrefilter:bW(bR),ajaxTransport:bW(bS),ajax:function(a,c){function w(a,c,l,m){if(s!==2){s=2,q&&clearTimeout(q),p=b,n=m||"",v.readyState=a?4:0;var o,r,u,w=l?bZ(d,v,l):b,x,y;if(a>=200&&a<300||a===304){if(d.ifModified){if(x=v.getResponseHeader("Last-Modified"))f.lastModified[k]=x;if(y=v.getResponseHeader("Etag"))f.etag[k]=y}if(a===304)c="notmodified",o=!0;else try{r=b$(d,w),c="success",o=!0}catch(z){c="parsererror",u=z}}else{u=c;if(!c||a)c="error",a<0&&(a=0)}v.status=a,v.statusText=c,o?h.resolveWith(e,[r,c,v]):h.rejectWith(e,[v,c,u]),v.statusCode(j),j=b,t&&g.trigger("ajax"+(o?"Success":"Error"),[v,d,o?r:u]),i.resolveWith(e,[v,c]),t&&(g.trigger("ajaxComplete",[v,d]),--f.active||f.event.trigger("ajaxStop"))}}typeof a=="object"&&(c=a,a=b),c=c||{};var d=f.ajaxSetup({},c),e=d.context||d,g=e!==d&&(e.nodeType||e instanceof f)?f(e):f.event,h=f.Deferred(),i=f._Deferred(),j=d.statusCode||{},k,l={},m={},n,o,p,q,r,s=0,t,u,v={readyState:0,setRequestHeader:function(a,b){if(!s){var c=a.toLowerCase();a=m[c]=m[c]||a,l[a]=b}return this},getAllResponseHeaders:function(){return s===2?n:null},getResponseHeader:function(a){var c;if(s===2){if(!o){o={};while(c=bF.exec(n))o[c[1].toLowerCase()]=c[2]}c=o[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){s||(d.mimeType=a);return this},abort:function(a){a=a||"abort",p&&p.abort(a),w(0,a);return this}};h.promise(v),v.success=v.done,v.error=v.fail,v.complete=i.done,v.statusCode=function(a){if(a){var b;if(s<2)for(b in a)j[b]=[j[b],a[b]];else b=a[v.status],v.then(b,b)}return this},d.url=((a||d.url)+"").replace(bE,"").replace(bJ,bU[1]+"//"),d.dataTypes=f.trim(d.dataType||"*").toLowerCase().split(bN),d.crossDomain==null&&(r=bP.exec(d.url.toLowerCase()),d.crossDomain=!(!r||r[1]==bU[1]&&r[2]==bU[2]&&(r[3]||(r[1]==="http:"?80:443))==(bU[3]||(bU[1]==="http:"?80:443)))),d.data&&d.processData&&typeof d.data!="string"&&(d.data=f.param(d.data,d.traditional)),bX(bR,d,c,v);if(s===2)return!1;t=d.global,d.type=d.type.toUpperCase(),d.hasContent=!bI.test(d.type),t&&f.active++===0&&f.event.trigger("ajaxStart");if(!d.hasContent){d.data&&(d.url+=(bK.test(d.url)?"&":"?")+d.data),k=d.url;if(d.cache===!1){var x=f.now(),y=d.url.replace(bO,"$1_="+x);d.url=y+(y===d.url?(bK.test(d.url)?"&":"?")+"_="+x:"")}}(d.data&&d.hasContent&&d.contentType!==!1||c.contentType)&&v.setRequestHeader("Content-Type",d.contentType),d.ifModified&&(k=k||d.url,f.lastModified[k]&&v.setRequestHeader("If-Modified-Since",f.lastModified[k]),f.etag[k]&&v.setRequestHeader("If-None-Match",f.etag[k])),v.setRequestHeader("Accept",d.dataTypes[0]&&d.accepts[d.dataTypes[0]]?d.accepts[d.dataTypes[0]]+(d.dataTypes[0]!=="*"?", */*; q=0.01":""):d.accepts["*"]);for(u in d.headers)v.setRequestHeader(u,d.headers[u]);if(d.beforeSend&&(d.beforeSend.call(e,v,d)===!1||s===2)){v.abort();return!1}for(u in{success:1,error:1,complete:1})v[u](d[u]);p=bX(bS,d,c,v);if(!p)w(-1,"No Transport");else{v.readyState=1,t&&g.trigger("ajaxSend",[v,d]),d.async&&d.timeout>0&&(q=setTimeout(function(){v.abort("timeout")},d.timeout));try{s=1,p.send(l,w)}catch(z){status<2?w(-1,z):f.error(z)}}return v},param:function(a,c){var d=[],e=function(a,b){b=f.isFunction(b)?b():b,d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=f.ajaxSettings.traditional);if(f.isArray(a)||a.jquery&&!f.isPlainObject(a))f.each(a,function(){e(this.name,this.value)});else for(var g in a)bY(g,a[g],c,e);return d.join("&").replace(bB,"+")}}),f.extend({active:0,lastModified:{},etag:{}});var b_=f.now(),ca=/(\=)\?(&|$)|\?\?/i;f.ajaxSetup({jsonp:"callback",jsonpCallback:function(){return f.expando+"_"+b_++}}),f.ajaxPrefilter("json jsonp",function(b,c,d){var e=b.contentType==="application/x-www-form-urlencoded"&&typeof b.data=="string";if(b.dataTypes[0]==="jsonp"||b.jsonp!==!1&&(ca.test(b.url)||e&&ca.test(b.data))){var g,h=b.jsonpCallback=f.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,i=a[h],j=b.url,k=b.data,l="$1"+h+"$2";b.jsonp!==!1&&(j=j.replace(ca,l),b.url===j&&(e&&(k=k.replace(ca,l)),b.data===k&&(j+=(/\?/.test(j)?"&":"?")+b.jsonp+"="+h))),b.url=j,b.data=k,a[h]=function(a){g=[a]},d.always(function(){a[h]=i,g&&f.isFunction(i)&&a[h](g[0])}),b.converters["script json"]=function(){g||f.error(h+" was not called");return g[0]},b.dataTypes[0]="json";return"script"}}),f.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(a){f.globalEval(a);return a}}}),f.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),f.ajaxTransport("script",function(a){if(a.crossDomain){var d,e=c.head||c.getElementsByTagName("head")[0]||c.documentElement;return{send:function(f,g){d=c.createElement("script"),d.async="async",a.scriptCharset&&(d.charset=a.scriptCharset),d.src=a.url,d.onload=d.onreadystatechange=function(a,c){if(c||!d.readyState||/loaded|complete/.test(d.readyState))d.onload=d.onreadystatechange=null,e&&d.parentNode&&e.removeChild(d),d=b,c||g(200,"success")},e.insertBefore(d,e.firstChild)},abort:function(){d&&d.onload(0,1)}}}});var cb=a.ActiveXObject?function(){for(var a in cd)cd[a](0,1)}:!1,cc=0,cd;f.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&ce()||cf()}:ce,function(a){f.extend(f.support,{ajax:!!a,cors:!!a&&"withCredentials"in a})}(f.ajaxSettings.xhr()),f.support.ajax&&f.ajaxTransport(function(c){if(!c.crossDomain||f.support.cors){var d;return{send:function(e,g){var h=c.xhr(),i,j;c.username?h.open(c.type,c.url,c.async,c.username,c.password):h.open(c.type,c.url,c.async);if(c.xhrFields)for(j in c.xhrFields)h[j]=c.xhrFields[j];c.mimeType&&h.overrideMimeType&&h.overrideMimeType(c.mimeType),!c.crossDomain&&!e["X-Requested-With"]&&(e["X-Requested-With"]="XMLHttpRequest");try{for(j in e)h.setRequestHeader(j,e[j])}catch(k){}h.send(c.hasContent&&c.data||null),d=function(a,e){var j,k,l,m,n;try{if(d&&(e||h.readyState===4)){d=b,i&&(h.onreadystatechange=f.noop,cb&&delete cd[i]);if(e)h.readyState!==4&&h.abort();else{j=h.status,l=h.getAllResponseHeaders(),m={},n=h.responseXML,n&&n.documentElement&&(m.xml=n),m.text=h.responseText;try{k=h.statusText}catch(o){k=""}!j&&c.isLocal&&!c.crossDomain?j=m.text?200:404:j===1223&&(j=204)}}}catch(p){e||g(-1,p)}m&&g(j,k,m,l)},!c.async||h.readyState===4?d():(i=++cc,cb&&(cd||(cd={},f(a).unload(cb)),cd[i]=d),h.onreadystatechange=d)},abort:function(){d&&d(0,1)}}}});var cg={},ch,ci,cj=/^(?:toggle|show|hide)$/,ck=/^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i,cl,cm=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]],cn,co=a.webkitRequestAnimationFrame||a.mozRequestAnimationFrame||a.oRequestAnimationFrame;f.fn.extend({show:function(a,b,c){var d,e;if(a||a===0)return this.animate(cr("show",3),a,b,c);for(var g=0,h=this.length;g<h;g++)d=this[g],d.style&&(e=d.style.display,!f._data(d,"olddisplay")&&e==="none"&&(e=d.style.display=""),e===""&&f.css(d,"display")==="none"&&f._data(d,"olddisplay",cs(d.nodeName)));for(g=0;g<h;g++){d=this[g];if(d.style){e=d.style.display;if(e===""||e==="none")d.style.display=f._data(d,"olddisplay")||""}}return this},hide:function(a,b,c){if(a||a===0)return this.animate(cr("hide",3),a,b,c);for(var d=0,e=this.length;d<e;d++)if(this[d].style){var g=f.css(this[d],"display");g!=="none"&&!f._data(this[d],"olddisplay")&&f._data(this[d],"olddisplay",g)}for(d=0;d<e;d++)this[d].style&&(this[d].style.display="none");return this},_toggle:f.fn.toggle,toggle:function(a,b,c){var d=typeof a=="boolean";f.isFunction(a)&&f.isFunction(b)?this._toggle.apply(this,arguments):a==null||d?this.each(function(){var b=d?a:f(this).is(":hidden");f(this)[b?"show":"hide"]()}):this.animate(cr("toggle",3),a,b,c);return this},fadeTo:function(a,b,c,d){return this.filter(":hidden").css("opacity",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,d){var e=f.speed(b,c,d);if(f.isEmptyObject(a))return this.each(e.complete,[!1]);a=f.extend({},a);return this[e.queue===!1?"each":"queue"](function(){e.queue===!1&&f._mark(this);var b=f.extend({},e),c=this.nodeType===1,d=c&&f(this).is(":hidden"),g,h,i,j,k,l,m,n,o;b.animatedProperties={};for(i in a){g=f.camelCase(i),i!==g&&(a[g]=a[i],delete a[i]),h=a[g],f.isArray(h)?(b.animatedProperties[g]=h[1],h=a[g]=h[0]):b.animatedProperties[g]=b.specialEasing&&b.specialEasing[g]||b.easing||"swing";if(h==="hide"&&d||h==="show"&&!d)return b.complete.call(this);c&&(g==="height"||g==="width")&&(b.overflow=[this.style.overflow,this.style.overflowX,this.style.overflowY],f.css(this,"display")==="inline"&&f.css(this,"float")==="none"&&(f.support.inlineBlockNeedsLayout?(j=cs(this.nodeName),j==="inline"?this.style.display="inline-block":(this.style.display="inline",this.style.zoom=1)):this.style.display="inline-block"))}b.overflow!=null&&(this.style.overflow="hidden");for(i in a)k=new f.fx(this,b,i),h=a[i],cj.test(h)?k[h==="toggle"?d?"show":"hide":h]():(l=ck.exec(h),m=k.cur(),l?(n=parseFloat(l[2]),o=l[3]||(f.cssNumber[i]?"":"px"),o!=="px"&&(f.style(this,i,(n||1)+o),m=(n||1)/k.cur()*m,f.style(this,i,m+o)),l[1]&&(n=(l[1]==="-="?-1:1)*n+m),k.custom(m,n,o)):k.custom(m,h,""));return!0})},stop:function(a,b){a&&this.queue([]),this.each(function(){var a=f.timers,c=a.length;b||f._unmark(!0,this);while(c--)a[c].elem===this&&(b&&a[c](!0),a.splice(c,1))}),b||this.dequeue();return this}}),f.each({slideDown:cr("show",1),slideUp:cr("hide",1),slideToggle:cr("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){f.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),f.extend({speed:function(a,b,c){var d=a&&typeof a=="object"?f.extend({},a):{complete:c||!c&&b||f.isFunction(a)&&a,duration:a,easing:c&&b||b&&!f.isFunction(b)&&b};d.duration=f.fx.off?0:typeof d.duration=="number"?d.duration:d.duration in f.fx.speeds?f.fx.speeds[d.duration]:f.fx.speeds._default,d.old=d.complete,d.complete=function(a){f.isFunction(d.old)&&d.old.call(this),d.queue!==!1?f.dequeue(this):a!==!1&&f._unmark(this)};return d},easing:{linear:function(a,b,c,d){return c+d*a},swing:function(a,b,c,d){return(-Math.cos(a*Math.PI)/2+.5)*d+c}},timers:[],fx:function(a,b,c){this.options=b,this.elem=a,this.prop=c,b.orig=b.orig||{}}}),f.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this),(f.fx.step[this.prop]||f.fx.step._default)(this)},cur:function(){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];var a,b=f.css(this.elem,this.prop);return isNaN(a=parseFloat(b))?!b||b==="auto"?0:b:a},custom:function(a,b,c){function h(a){return d.step(a)}var d=this,e=f.fx,g;this.startTime=cn||cp(),this.start=a,this.end=b,this.unit=c||this.unit||(f.cssNumber[this.prop]?"":"px"),this.now=this.start,this.pos=this.state=0,h.elem=this.elem,h()&&f.timers.push(h)&&!cl&&(co?(cl=!0,g=function(){cl&&(co(g),e.tick())},co(g)):cl=setInterval(e.tick,e.interval))},show:function(){this.options.orig[this.prop]=f.style(this.elem,this.prop),this.options.show=!0,this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur()),f(this.elem).show()},hide:function(){this.options.orig[this.prop]=f.style(this.elem,this.prop),this.options.hide=!0,this.custom(this.cur(),0)},step:function(a){var b=cn||cp(),c=!0,d=this.elem,e=this.options,g,h;if(a||b>=e.duration+this.startTime){this.now=this.end,this.pos=this.state=1,this.update(),e.animatedProperties[this.prop]=!0;for(g in e.animatedProperties)e.animatedProperties[g]!==!0&&(c=!1);if(c){e.overflow!=null&&!f.support.shrinkWrapBlocks&&f.each(["","X","Y"],function(a,b){d.style["overflow"+b]=e.overflow[a]}),e.hide&&f(d).hide();if(e.hide||e.show)for(var i in e.animatedProperties)f.style(d,i,e.orig[i]);e.complete.call(d)}return!1}e.duration==Infinity?this.now=b:(h=b-this.startTime,this.state=h/e.duration,this.pos=f.easing[e.animatedProperties[this.prop]](this.state,h,0,1,e.duration),this.now=this.start+(this.end-this.start)*this.pos),this.update();return!0}},f.extend(f.fx,{tick:function(){for(var a=f.timers,b=0;b<a.length;++b)a[b]()||a.splice(b--,1);a.length||f.fx.stop()},interval:13,stop:function(){clearInterval(cl),cl=null},speeds:{slow:600,fast:200,_default:400},step:{opacity:function(a){f.style(a.elem,"opacity",a.now)},_default:function(a){a.elem.style&&a.elem.style[a.prop]!=null?a.elem.style[a.prop]=(a.prop==="width"||a.prop==="height"?Math.max(0,a.now):a.now)+a.unit:a.elem[a.prop]=a.now}}}),f.expr&&f.expr.filters&&(f.expr.filters.animated=function(a){return f.grep(f.timers,function(b){return a===b.elem}).length});var ct=/^t(?:able|d|h)$/i,cu=/^(?:body|html)$/i;"getBoundingClientRect"in c.documentElement?f.fn.offset=function(a){var b=this[0],c;if(a)return this.each(function(b){f.offset.setOffset(this,a,b)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return f.offset.bodyOffset(b);try{c=b.getBoundingClientRect()}catch(d){}var e=b.ownerDocument,g=e.documentElement;if(!c||!f.contains(g,b))return c?{top:c.top,left:c.left}:{top:0,left:0};var h=e.body,i=cv(e),j=g.clientTop||h.clientTop||0,k=g.clientLeft||h.clientLeft||0,l=i.pageYOffset||f.support.boxModel&&g.scrollTop||h.scrollTop,m=i.pageXOffset||f.support.boxModel&&g.scrollLeft||h.scrollLeft,n=c.top+l-j,o=c.left+m-k;return{top:n,left:o}}:f.fn.offset=function(a){var b=this[0];if(a)return this.each(function(b){f.offset.setOffset(this,a,b)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return f.offset.bodyOffset(b);f.offset.initialize();var c,d=b.offsetParent,e=b,g=b.ownerDocument,h=g.documentElement,i=g.body,j=g.defaultView,k=j?j.getComputedStyle(b,null):b.currentStyle,l=b.offsetTop,m=b.offsetLeft;while((b=b.parentNode)&&b!==i&&b!==h){if(f.offset.supportsFixedPosition&&k.position==="fixed")break;c=j?j.getComputedStyle(b,null):b.currentStyle,l-=b.scrollTop,m-=b.scrollLeft,b===d&&(l+=b.offsetTop,m+=b.offsetLeft,f.offset.doesNotAddBorder&&(!f.offset.doesAddBorderForTableAndCells||!ct.test(b.nodeName))&&(l+=parseFloat(c.borderTopWidth)||0,m+=parseFloat(c.borderLeftWidth)||0),e=d,d=b.offsetParent),f.offset.subtractsBorderForOverflowNotVisible&&c.overflow!=="visible"&&(l+=parseFloat(c.borderTopWidth)||0,m+=parseFloat(c.borderLeftWidth)||0),k=c}if(k.position==="relative"||k.position==="static")l+=i.offsetTop,m+=i.offsetLeft;f.offset.supportsFixedPosition&&k.position==="fixed"&&(l+=Math.max(h.scrollTop,i.scrollTop),m+=Math.max(h.scrollLeft,i.scrollLeft));return{top:l,left:m}},f.offset={initialize:function(){var a=c.body,b=c.createElement("div"),d,e,g,h,i=parseFloat(f.css(a,"marginTop"))||0,j="<div style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;'><div></div></div><table style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;' cellpadding='0' cellspacing='0'><tr><td></td></tr></table>";f.extend(b.style,{position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",height:"1px",visibility:"hidden"}),b.innerHTML=j,a.insertBefore(b,a.firstChild),d=b.firstChild,e=d.firstChild,h=d.nextSibling.firstChild.firstChild,this.doesNotAddBorder=e.offsetTop!==5,this.doesAddBorderForTableAndCells=h.offsetTop===5,e.style.position="fixed",e.style.top="20px",this.supportsFixedPosition=e.offsetTop===20||e.offsetTop===15,e.style.position=e.style.top="",d.style.overflow="hidden",d.style.position="relative",this.subtractsBorderForOverflowNotVisible=e.offsetTop===-5,this.doesNotIncludeMarginInBodyOffset=a.offsetTop!==i,a.removeChild(b),f.offset.initialize=f.noop},bodyOffset:function(a){var b=a.offsetTop,c=a.offsetLeft;f.offset.initialize(),f.offset.doesNotIncludeMarginInBodyOffset&&(b+=parseFloat(f.css(a,"marginTop"))||0,c+=parseFloat(f.css(a,"marginLeft"))||0);return{top:b,left:c}},setOffset:function(a,b,c){var d=f.css(a,"position");d==="static"&&(a.style.position="relative");var e=f(a),g=e.offset(),h=f.css(a,"top"),i=f.css(a,"left"),j=(d==="absolute"||d==="fixed")&&f.inArray("auto",[h,i])>-1,k={},l={},m,n;j?(l=e.position(),m=l.top,n=l.left):(m=parseFloat(h)||0,n=parseFloat(i)||0),f.isFunction(b)&&(b=b.call(a,c,g)),b.top!=null&&(k.top=b.top-g.top+m),b.left!=null&&(k.left=b.left-g.left+n),"using"in b?b.using.call(a,k):e.css(k)}},f.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),c=this.offset(),d=cu.test(b[0].nodeName)?{top:0,left:0}:b.offset();c.top-=parseFloat(f.css(a,"marginTop"))||0,c.left-=parseFloat(f.css(a,"marginLeft"))||0,d.top+=parseFloat(f.css(b[0],"borderTopWidth"))||0,d.left+=parseFloat(f.css(b[0],"borderLeftWidth"))||0;return{top:c.top-d.top,left:c.left-d.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||c.body;while(a&&!cu.test(a.nodeName)&&f.css(a,"position")==="static")a=a.offsetParent;return a})}}),f.each(["Left","Top"],function(a,c){var d="scroll"+c;f.fn[d]=function(c){var e,g;if(c===b){e=this[0];if(!e)return null;g=cv(e);return g?"pageXOffset"in g?g[a?"pageYOffset":"pageXOffset"]:f.support.boxModel&&g.document.documentElement[d]||g.document.body[d]:e[d]}return this.each(function(){g=cv(this),g?g.scrollTo(a?f(g).scrollLeft():c,a?c:f(g).scrollTop()):this[d]=c})}}),f.each(["Height","Width"],function(a,c){var d=c.toLowerCase();f.fn["inner"+c]=function(){var a=this[0];return a&&a.style?parseFloat(f.css(a,d,"padding")):null},f.fn["outer"+c]=function(a){var b=this[0];return b&&b.style?parseFloat(f.css(b,d,a?"margin":"border")):null},f.fn[d]=function(a){var e=this[0];if(!e)return a==null?null:this;if(f.isFunction(a))return this.each(function(b){var c=f(this);c[d](a.call(this,b,c[d]()))});if(f.isWindow(e)){var g=e.document.documentElement["client"+c];return e.document.compatMode==="CSS1Compat"&&g||e.document.body["client"+c]||g}if(e.nodeType===9)return Math.max(e.documentElement["client"+c],e.body["scroll"+c],e.documentElement["scroll"+c],e.body["offset"+c],e.documentElement["offset"+c]);if(a===b){var h=f.css(e,d),i=parseFloat(h);return f.isNaN(i)?h:i}return this.css(d,typeof a=="string"?a:a+"px")}}),a.jQuery=a.$=f})(window);
\ No newline at end of file
diff --git a/docs/html/design/static/open_new_page.png b/docs/html/design/static/open_new_page.png
deleted file mode 100644
index 6197e3a..0000000
--- a/docs/html/design/static/open_new_page.png
+++ /dev/null
Binary files differ
diff --git a/docs/html/design/static/yui-3.3.0-reset-min.css b/docs/html/design/static/yui-3.3.0-reset-min.css
deleted file mode 100644
index 00c3892..0000000
--- a/docs/html/design/static/yui-3.3.0-reset-min.css
+++ /dev/null
@@ -1,8 +0,0 @@
-/*
-Copyright (c) 2010, Yahoo! Inc. All rights reserved.
-Code licensed under the BSD License:
-http://developer.yahoo.com/yui/license.html
-version: 3.3.0
-build: 3167
-*/
-html{color:#000;background:#FFF;}body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,code,form,fieldset,legend,input,textarea,p,blockquote,th,td{margin:0;padding:0;}table{border-collapse:collapse;border-spacing:0;}fieldset,img{border:0;}address,caption,cite,code,dfn,em,strong,th,var{font-style:normal;font-weight:normal;}li{list-style:none;}caption,th{text-align:left;}h1,h2,h3,h4,h5,h6{font-size:100%;font-weight:normal;}q:before,q:after{content:'';}abbr,acronym{border:0;font-variant:normal;}sup{vertical-align:text-top;}sub{vertical-align:text-bottom;}input,textarea,select{font-family:inherit;font-size:inherit;font-weight:inherit;}input,textarea,select{*font-size:100%;}legend{color:#000;}
\ No newline at end of file
diff --git a/docs/html/design/style/color.html b/docs/html/design/style/color.html
deleted file mode 100644
index bca3c45..0000000
--- a/docs/html/design/style/color.html
+++ /dev/null
@@ -1,296 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-  <head>
-    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
-    <title>
-
-Android Design - Color
-    </title>
-    <link rel="shortcut icon" type="image/x-icon" href="/favicon.ico">
-    <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Roboto:regular,medium,thin,italic,mediumitalic">
-    <link rel="stylesheet" href="../static/yui-3.3.0-reset-min.css">
-    <link rel="stylesheet" href="../static/default.css">
-
-<style>
-  .color-row {
-    width: 740px;
-    margin-left: 10px !important;
-    margin-right: 10px !important;
-
-    display:         box;
-    display: -webkit-box;
-    display:    -moz-box;
-
-            box-orient: horizontal;
-    -webkit-box-orient: horizontal;
-       -moz-box-orient: horizontal;
-
-    cursor: pointer;
-
-            user-select: none;
-    -webkit-user-select: none;
-    /* nested user-select in FF is broken as of Jan 2012, don't use it */
-  }
-
-  .color-row-container {
-    line-height: 0; /* to remove more top space in FF for -moz-box elements */
-  }
-
-  .color-row-container + .color-row-container {
-    margin-top: -10px !important;
-  }
-
-  .color-row li {
-    margin-left: 0 !important;
-    position: relative;
-    list-style-type: none;
-    height: 80px;
-    display: block;
-
-            box-flex: 1;
-    -webkit-box-flex: 1;
-       -moz-box-flex: 1;
-  }
-
-  .color-row li:before {
-    display: none;
-  }
-
-  .color-row li.thin {
-    height: 40px;
-  }
-
-  .color-row li span {
-    display: none;
-    position: absolute;
-    top: -30px;
-    left: 50%;
-    margin-left: -2.5em;
-    width: 5em;
-    background-color: #fff;
-    padding: 10px;
-    font-weight: 600;
-    line-height: 20px;
-    text-align: center;
-    box-shadow: 0 5px 5px rgba(0,0,0,0.1);
-    cursor: text;
-
-            user-select: text;
-    -webkit-user-select: text;
-    /* nested user-select in FF is broken as of Jan 2012, don't use it */
-  }
-
-  .color-row li:hover span {
-    display: block;
-  }
-
-  /*.color-row li span:before {
-    color: #999;
-    content: 'copy ';
-  }*/
-
-  /* triangle callout */
-  .color-row li span:after {
-    content: '';
-    display: block;
-    position: absolute;
-    left: 50%;
-    bottom: -16px;
-    border: 8px solid transparent;
-    border-top-color: #fff;
-    width: 0;
-    height: 0;
-    margin-left: -8px;
-  }
-</style>
-
-  </head>
-  <body>
-
-    <div id="page-container">
-
-      <div id="page-header"><a href="../index.html">Android Design</a></div>
-
-      <div id="main-row">
-
-        <ul id="nav">
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../index.html">Get Started</a></div>
-            <ul>
-              <li><a href="../get-started/creative-vision.html">Creative Vision</a></li>
-              <li><a href="../get-started/principles.html">Design Principles</a></li>
-              <li><a href="../get-started/ui-overview.html">UI Overview</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../style/index.html">Style</a></div>
-            <ul>
-              <li><a href="../style/devices-displays.html">Devices and Displays</a></li>
-              <li><a href="../style/themes.html">Themes</a></li>
-              <li><a href="../style/touch-feedback.html">Touch Feedback</a></li>
-              <li><a href="../style/metrics-grids.html">Metrics and Grids</a></li>
-              <li><a href="../style/typography.html">Typography</a></li>
-              <li><a href="../style/color.html">Color</a></li>
-              <li><a href="../style/iconography.html">Iconography</a></li>
-              <li><a href="../style/writing.html">Writing Style</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../patterns/index.html">Patterns</a></div>
-            <ul>
-              <li><a href="../patterns/new-4-0.html">New in Android 4.0</a></li>
-              <li><a href="../patterns/gestures.html">Gestures</a></li>
-              <li><a href="../patterns/app-structure.html">App Structure</a></li>
-              <li><a href="../patterns/navigation.html">Navigation</a></li>
-              <li><a href="../patterns/actionbar.html">Action Bar</a></li>
-              <li><a href="../patterns/multi-pane-layouts.html">Multi-pane Layouts</a></li>
-              <li><a href="../patterns/swipe-views.html">Swipe Views</a></li>
-              <li><a href="../patterns/selection.html">Selection</a></li>
-              <li><a href="../patterns/notifications.html">Notifications</a></li>
-              <li><a href="../patterns/compatibility.html">Compatibility</a></li>
-              <li><a href="../patterns/pure-android.html">Pure Android</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../building-blocks/index.html">Building Blocks</a></div>
-            <ul>
-              <li><a href="../building-blocks/tabs.html">Tabs</a></li>
-              <li><a href="../building-blocks/lists.html">Lists</a></li>
-              <li><a href="../building-blocks/grid-lists.html">Grid Lists</a></li>
-              <li><a href="../building-blocks/scrolling.html">Scrolling</a></li>
-              <li><a href="../building-blocks/spinners.html">Spinners</a></li>
-              <li><a href="../building-blocks/buttons.html">Buttons</a></li>
-              <li><a href="../building-blocks/text-fields.html">Text Fields</a></li>
-              <li><a href="../building-blocks/seek-bars.html">Seek Bars</a></li>
-              <li><a href="../building-blocks/progress.html">Progress &amp; Activity</a></li>
-              <li><a href="../building-blocks/switches.html">Switches</a></li>
-              <li><a href="../building-blocks/dialogs.html">Dialogs</a></li>
-              <li><a href="../building-blocks/pickers.html">Pickers</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header empty"><a href="../downloads/index.html">Downloads</a></div>
-          </li>
-
-          <li>
-            <div id="back-dac-section"><a href="../../index.html">Developers</a></div>
-          </li>
-
-        </ul>
-
-        <div id="content">
-
-          
-          <div class="layout-content-row content-header">
-            <div class="layout-content-col span-9">
-              <h2>Color</h2>
-            </div>
-            <div class="paging-links layout-content-col span-4">
-              <a href="#" class="prev-page-link">Previous</a>
-              <a href="#" class="next-page-link">Next</a>
-            </div>
-          </div>
-          
-
-          
-
-<p>Use color primarily for emphasis. Choose colors that fit with your brand and provide good contrast
-between visual components. Note that red and green may be indistinguishable to color-blind users.</p>
-
-    <div class="color-row-container">
-      <ul class="color-row">
-        <li><span>#33b5e5</span></li>
-        <li><span>#aa66cc</span></li>
-        <li><span>#99cc00</span></li>
-        <li><span>#ffbb33</span></li>
-        <li><span>#ff4444</span></li>
-      </ul>
-    </div>
-
-    <div class="color-row-container">
-      <ul class="color-row">
-        <li class="thin"><span>#0099cc</span></li>
-        <li class="thin"><span>#9933cc</span></li>
-        <li class="thin"><span>#669900</span></li>
-        <li class="thin"><span>#ff8800</span></li>
-        <li class="thin"><span>#cc0000</span></li>
-      </ul>
-    </div>
-
-<h2 id="palette">Palette</h2>
-
-<p>Blue is the standard accent color in Android's color palette. Each color has a corresponding darker
-shade that can be used as a complement when needed.</p>
-<p><a href="https://dl-ssl.google.com/android/design/Android_Design_Color_Swatches_20120229.zip">Download the swatches</a></p>
-
-<img src="../static/content/color_spectrum.png">
-
-
-
-          
-          <div class="layout-content-row content-footer">
-            <div class="paging-links layout-content-col span-9">&nbsp;</div>
-            <div class="paging-links layout-content-col span-4">
-              <a href="#" class="prev-page-link">Previous</a>
-              <a href="#" class="next-page-link">Next</a>
-            </div>
-          </div>
-          
-        </div>
-
-      </div>
-
-      <div id="page-footer">
-
-        <p id="copyright">
-          Except as noted, this content is licensed under
-          <a href="http://creativecommons.org/licenses/by/2.5/">
-          Creative Commons Attribution 2.5</a>.<br>
-          For details and restrictions, see the
-          <a href="http://developer.android.com/license.html">Content License</a>.
-        </p>
-
-        <p>
-          <a href="http://www.android.com/terms.html">Site Terms of Service</a> &ndash;
-          <a href="http://www.android.com/privacy.html">Privacy Policy</a> &ndash;
-          <a href="http://www.android.com/branding.html">Brand Guidelines</a>
-        </p>
-
-      </div>
-    </div>
-
-    <script src="../static/jquery-1.6.2.min.js"></script>
-    <script>
-    var SITE_ROOT = '../';
-    </script>
-    <script src="../static/default.js"></script>
-
-<script>
-  $(document).ready(function() {
-    $('.color-row li').each(function() {
-      var color = $(this).text();
-      $(this).css('background-color', color);
-      $(this).find('span')
-          .css('color', color)
-          .text(color.toUpperCase());
-    });
-    
-  });
-</script>
-
-
-    <script type="text/javascript">
-    var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
-    document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
-    </script>
-    <script type="text/javascript">
-    var pageTracker = _gat._getTracker("UA-5831155-1");
-    pageTracker._trackPageview();
-    </script>
-  </body>
-</html>
diff --git a/docs/html/design/style/color.jd b/docs/html/design/style/color.jd
new file mode 100644
index 0000000..e25f7c6
--- /dev/null
+++ b/docs/html/design/style/color.jd
@@ -0,0 +1,134 @@
+page.title=Color
+@jd:body
+
+<style>
+  .color-row {
+    width: 740px;
+    margin-left: 10px !important;
+    margin-right: 10px !important;
+
+    display: -webkit-box;
+    display:    -moz-box;
+    display:         box;
+
+    -webkit-box-orient: horizontal;
+       -moz-box-orient: horizontal;
+            box-orient: horizontal;
+
+    cursor: pointer;
+
+    -webkit-user-select: none;
+            user-select: none;
+    /* nested user-select in FF is broken as of Jan 2012, don't use it */
+  }
+
+  .color-row-container {
+    line-height: 0; /* to remove more top space in FF for -moz-box elements */
+  }
+
+  .color-row-container + .color-row-container {
+    margin-top: -10px !important;
+  }
+
+  .color-row li {
+    margin-left: 0 !important;
+    position: relative;
+    list-style-type: none;
+    height: 80px;
+    display: block;
+
+    -webkit-box-flex: 1;
+       -moz-box-flex: 1;
+            box-flex: 1;
+  }
+
+  .color-row li:before {
+    display: none;
+  }
+
+  .color-row li.thin {
+    height: 40px;
+  }
+
+  .color-row li span {
+    display: none;
+    position: absolute;
+    top: -30px;
+    left: 50%;
+    margin-left: -2.5em;
+    width: 5em;
+    background-color: #fff;
+    padding: 10px;
+    font-weight: 600;
+    line-height: 20px;
+    text-align: center;
+    box-shadow: 0 5px 5px rgba(0,0,0,0.1);
+    cursor: text;
+
+    -webkit-user-select: text;
+            user-select: text;
+    /* nested user-select in FF is broken as of Jan 2012, don't use it */
+  }
+
+  .color-row li:hover span {
+    display: block;
+  }
+
+  /* triangle callout */
+  .color-row li span:after {
+    content: '';
+    display: block;
+    position: absolute;
+    left: 50%;
+    bottom: -16px;
+    border: 8px solid transparent;
+    border-top-color: #fff;
+    width: 0;
+    height: 0;
+    margin-left: -8px;
+  }
+</style>
+
+<p>Use color primarily for emphasis. Choose colors that fit with your brand and provide good contrast
+between visual components. Note that red and green may be indistinguishable to color-blind users.</p>
+
+    <div class="color-row-container">
+      <ul class="color-row">
+        <li><span>#33b5e5</span></li>
+        <li><span>#aa66cc</span></li>
+        <li><span>#99cc00</span></li>
+        <li><span>#ffbb33</span></li>
+        <li><span>#ff4444</span></li>
+      </ul>
+    </div>
+
+    <div class="color-row-container">
+      <ul class="color-row">
+        <li class="thin"><span>#0099cc</span></li>
+        <li class="thin"><span>#9933cc</span></li>
+        <li class="thin"><span>#669900</span></li>
+        <li class="thin"><span>#ff8800</span></li>
+        <li class="thin"><span>#cc0000</span></li>
+      </ul>
+    </div>
+
+<h2 id="palette">Palette</h2>
+
+<p>Blue is the standard accent color in Android's color palette. Each color has a corresponding darker
+shade that can be used as a complement when needed.</p>
+<p><a href="https://dl-ssl.google.com/android/design/Android_Design_Color_Swatches_20120229.zip">Download the swatches</a></p>
+
+<img src="{@docRoot}design/media/color_spectrum.png">
+
+<script>
+  $(document).ready(function() {
+    $('.color-row li').each(function() {
+      var color = $(this).text();
+      $(this).css('background-color', color);
+      $(this).find('span')
+          .css('color', color)
+          .text(color.toUpperCase());
+    });
+    
+  });
+</script>
diff --git a/docs/html/design/style/devices-displays.html b/docs/html/design/style/devices-displays.html
deleted file mode 100644
index 89e0876..0000000
--- a/docs/html/design/style/devices-displays.html
+++ /dev/null
@@ -1,202 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-  <head>
-    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
-    <title>
-
-Android Design - Devices and Displays
-    </title>
-    <link rel="shortcut icon" type="image/x-icon" href="/favicon.ico">
-    <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Roboto:regular,medium,thin,italic,mediumitalic">
-    <link rel="stylesheet" href="../static/yui-3.3.0-reset-min.css">
-    <link rel="stylesheet" href="../static/default.css">
-
-  </head>
-  <body>
-
-    <div id="page-container">
-
-      <div id="page-header"><a href="../index.html">Android Design</a></div>
-
-      <div id="main-row">
-
-        <ul id="nav">
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../index.html">Get Started</a></div>
-            <ul>
-              <li><a href="../get-started/creative-vision.html">Creative Vision</a></li>
-              <li><a href="../get-started/principles.html">Design Principles</a></li>
-              <li><a href="../get-started/ui-overview.html">UI Overview</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../style/index.html">Style</a></div>
-            <ul>
-              <li><a href="../style/devices-displays.html">Devices and Displays</a></li>
-              <li><a href="../style/themes.html">Themes</a></li>
-              <li><a href="../style/touch-feedback.html">Touch Feedback</a></li>
-              <li><a href="../style/metrics-grids.html">Metrics and Grids</a></li>
-              <li><a href="../style/typography.html">Typography</a></li>
-              <li><a href="../style/color.html">Color</a></li>
-              <li><a href="../style/iconography.html">Iconography</a></li>
-              <li><a href="../style/writing.html">Writing Style</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../patterns/index.html">Patterns</a></div>
-            <ul>
-              <li><a href="../patterns/new-4-0.html">New in Android 4.0</a></li>
-              <li><a href="../patterns/gestures.html">Gestures</a></li>
-              <li><a href="../patterns/app-structure.html">App Structure</a></li>
-              <li><a href="../patterns/navigation.html">Navigation</a></li>
-              <li><a href="../patterns/actionbar.html">Action Bar</a></li>
-              <li><a href="../patterns/multi-pane-layouts.html">Multi-pane Layouts</a></li>
-              <li><a href="../patterns/swipe-views.html">Swipe Views</a></li>
-              <li><a href="../patterns/selection.html">Selection</a></li>
-              <li><a href="../patterns/notifications.html">Notifications</a></li>
-              <li><a href="../patterns/compatibility.html">Compatibility</a></li>
-              <li><a href="../patterns/pure-android.html">Pure Android</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../building-blocks/index.html">Building Blocks</a></div>
-            <ul>
-              <li><a href="../building-blocks/tabs.html">Tabs</a></li>
-              <li><a href="../building-blocks/lists.html">Lists</a></li>
-              <li><a href="../building-blocks/grid-lists.html">Grid Lists</a></li>
-              <li><a href="../building-blocks/scrolling.html">Scrolling</a></li>
-              <li><a href="../building-blocks/spinners.html">Spinners</a></li>
-              <li><a href="../building-blocks/buttons.html">Buttons</a></li>
-              <li><a href="../building-blocks/text-fields.html">Text Fields</a></li>
-              <li><a href="../building-blocks/seek-bars.html">Seek Bars</a></li>
-              <li><a href="../building-blocks/progress.html">Progress &amp; Activity</a></li>
-              <li><a href="../building-blocks/switches.html">Switches</a></li>
-              <li><a href="../building-blocks/dialogs.html">Dialogs</a></li>
-              <li><a href="../building-blocks/pickers.html">Pickers</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header empty"><a href="../downloads/index.html">Downloads</a></div>
-          </li>
-
-          <li>
-            <div id="back-dac-section"><a href="../../index.html">Developers</a></div>
-          </li>
-
-        </ul>
-
-        <div id="content">
-
-          
-          <div class="layout-content-row content-header">
-            <div class="layout-content-col span-9">
-              <h2>Devices and Displays</h2>
-            </div>
-            <div class="paging-links layout-content-col span-4">
-              <a href="#" class="prev-page-link">Previous</a>
-              <a href="#" class="next-page-link">Next</a>
-            </div>
-          </div>
-          
-
-          
-
-<p>Android powers millions of phones, tablets, and other devices in a wide variety of screen sizes and
-form factors. By taking advantage of Android's flexible layout system, you can create apps that
-gracefully scale from large tablets to smaller phones.</p>
-
-<img src="../static/content/devices_displays_main.png">
-
-<div class="vspace size-2">&nbsp;</div>
-
-<div class="layout-content-row">
-  <div class="layout-content-col span-4">
-
-<h4>Be flexible</h4>
-<p>Stretch and compress your layouts to accommodate various heights and widths.</p>
-
-  </div>
-  <div class="layout-content-col span-5">
-
-<h4>Optimize layouts</h4>
-<p>On larger devices, take advantage of extra screen real estate. Create compound views that combine
-multiple views to reveal more content and ease navigation.</p>
-
-  </div>
-  <div class="layout-content-col span-4">
-
-<h4>Assets for all</h4>
-<p>Provide resources for different screen densities (<acronym title="Dots per inch">DPI</acronym>) to
-ensure that your app looks great on any device.</p>
-
-  </div>
-</div>
-
-<div style="text-align:center">
-  <img src="../static/content/devices_displays_density.png">
-</div>
-
-<h4>Strategies</h4>
-<p>So where do you begin when designing for multiple screens? One approach is to work in the base
-standard (medium size, <acronym title="Medium density (160 dpi)">MDPI</acronym>) and scale it up or
-down for the other buckets. Another approach is to start with the device with the largest screen
-size, and then scale down and figure out the UI compromises you'll need to make on smaller screens.</p>
-<p>For more detailed information on this topic, please visit <a href="http://developer.android.com/guide/practices/screens_support.html">Supporting Multiple
-Screens</a>.</p>
-
-
-
-          
-          <div class="layout-content-row content-footer">
-            <div class="paging-links layout-content-col span-9">&nbsp;</div>
-            <div class="paging-links layout-content-col span-4">
-              <a href="#" class="prev-page-link">Previous</a>
-              <a href="#" class="next-page-link">Next</a>
-            </div>
-          </div>
-          
-        </div>
-
-      </div>
-
-      <div id="page-footer">
-
-        <p id="copyright">
-          Except as noted, this content is licensed under
-          <a href="http://creativecommons.org/licenses/by/2.5/">
-          Creative Commons Attribution 2.5</a>.<br>
-          For details and restrictions, see the
-          <a href="http://developer.android.com/license.html">Content License</a>.
-        </p>
-
-        <p>
-          <a href="http://www.android.com/terms.html">Site Terms of Service</a> &ndash;
-          <a href="http://www.android.com/privacy.html">Privacy Policy</a> &ndash;
-          <a href="http://www.android.com/branding.html">Brand Guidelines</a>
-        </p>
-
-      </div>
-    </div>
-
-    <script src="../static/jquery-1.6.2.min.js"></script>
-    <script>
-    var SITE_ROOT = '../';
-    </script>
-    <script src="../static/default.js"></script>
-
-
-    <script type="text/javascript">
-    var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
-    document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
-    </script>
-    <script type="text/javascript">
-    var pageTracker = _gat._getTracker("UA-5831155-1");
-    pageTracker._trackPageview();
-    </script>
-  </body>
-</html>
diff --git a/docs/html/design/style/devices-displays.jd b/docs/html/design/style/devices-displays.jd
new file mode 100644
index 0000000..e5fe26d
--- /dev/null
+++ b/docs/html/design/style/devices-displays.jd
@@ -0,0 +1,45 @@
+page.title=Devices and Displays
+@jd:body
+
+<p>Android powers millions of phones, tablets, and other devices in a wide variety of screen sizes and
+form factors. By taking advantage of Android's flexible layout system, you can create apps that
+gracefully scale from large tablets to smaller phones.</p>
+
+<img src="{@docRoot}design/media/devices_displays_main.png">
+
+<div class="vspace size-2">&nbsp;</div>
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-4">
+
+<h4>Be flexible</h4>
+<p>Stretch and compress your layouts to accommodate various heights and widths.</p>
+
+  </div>
+  <div class="layout-content-col span-5">
+
+<h4>Optimize layouts</h4>
+<p>On larger devices, take advantage of extra screen real estate. Create compound views that combine
+multiple views to reveal more content and ease navigation.</p>
+
+  </div>
+  <div class="layout-content-col span-4">
+
+<h4>Assets for all</h4>
+<p>Provide resources for different screen densities (<acronym title="Dots per inch">DPI</acronym>) to
+ensure that your app looks great on any device.</p>
+
+  </div>
+</div>
+
+<div style="text-align:center">
+  <img src="{@docRoot}design/media/devices_displays_density.png">
+</div>
+
+<h4>Strategies</h4>
+<p>So where do you begin when designing for multiple screens? One approach is to work in the base
+standard (medium size, <acronym title="Medium density (160 dpi)">MDPI</acronym>) and scale it up or
+down for the other buckets. Another approach is to start with the device with the largest screen
+size, and then scale down and figure out the UI compromises you'll need to make on smaller screens.</p>
+<p>For more detailed information on this topic, please visit <a href="http://developer.android.com/guide/practices/screens_support.html">Supporting Multiple
+Screens</a>.</p>
diff --git a/docs/html/design/style/iconography.html b/docs/html/design/style/iconography.html
deleted file mode 100644
index 96954de..0000000
--- a/docs/html/design/style/iconography.html
+++ /dev/null
@@ -1,497 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-  <head>
-    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
-    <title>
-
-Android Design - Iconography
-    </title>
-    <link rel="shortcut icon" type="image/x-icon" href="/favicon.ico">
-    <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Roboto:regular,medium,thin,italic,mediumitalic">
-    <link rel="stylesheet" href="../static/yui-3.3.0-reset-min.css">
-    <link rel="stylesheet" href="../static/default.css">
-
-  </head>
-  <body>
-
-    <div id="page-container">
-
-      <div id="page-header"><a href="../index.html">Android Design</a></div>
-
-      <div id="main-row">
-
-        <ul id="nav">
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../index.html">Get Started</a></div>
-            <ul>
-              <li><a href="../get-started/creative-vision.html">Creative Vision</a></li>
-              <li><a href="../get-started/principles.html">Design Principles</a></li>
-              <li><a href="../get-started/ui-overview.html">UI Overview</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../style/index.html">Style</a></div>
-            <ul>
-              <li><a href="../style/devices-displays.html">Devices and Displays</a></li>
-              <li><a href="../style/themes.html">Themes</a></li>
-              <li><a href="../style/touch-feedback.html">Touch Feedback</a></li>
-              <li><a href="../style/metrics-grids.html">Metrics and Grids</a></li>
-              <li><a href="../style/typography.html">Typography</a></li>
-              <li><a href="../style/color.html">Color</a></li>
-              <li><a href="../style/iconography.html">Iconography</a></li>
-              <li><a href="../style/writing.html">Writing Style</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../patterns/index.html">Patterns</a></div>
-            <ul>
-              <li><a href="../patterns/new-4-0.html">New in Android 4.0</a></li>
-              <li><a href="../patterns/gestures.html">Gestures</a></li>
-              <li><a href="../patterns/app-structure.html">App Structure</a></li>
-              <li><a href="../patterns/navigation.html">Navigation</a></li>
-              <li><a href="../patterns/actionbar.html">Action Bar</a></li>
-              <li><a href="../patterns/multi-pane-layouts.html">Multi-pane Layouts</a></li>
-              <li><a href="../patterns/swipe-views.html">Swipe Views</a></li>
-              <li><a href="../patterns/selection.html">Selection</a></li>
-              <li><a href="../patterns/notifications.html">Notifications</a></li>
-              <li><a href="../patterns/compatibility.html">Compatibility</a></li>
-              <li><a href="../patterns/pure-android.html">Pure Android</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../building-blocks/index.html">Building Blocks</a></div>
-            <ul>
-              <li><a href="../building-blocks/tabs.html">Tabs</a></li>
-              <li><a href="../building-blocks/lists.html">Lists</a></li>
-              <li><a href="../building-blocks/grid-lists.html">Grid Lists</a></li>
-              <li><a href="../building-blocks/scrolling.html">Scrolling</a></li>
-              <li><a href="../building-blocks/spinners.html">Spinners</a></li>
-              <li><a href="../building-blocks/buttons.html">Buttons</a></li>
-              <li><a href="../building-blocks/text-fields.html">Text Fields</a></li>
-              <li><a href="../building-blocks/seek-bars.html">Seek Bars</a></li>
-              <li><a href="../building-blocks/progress.html">Progress &amp; Activity</a></li>
-              <li><a href="../building-blocks/switches.html">Switches</a></li>
-              <li><a href="../building-blocks/dialogs.html">Dialogs</a></li>
-              <li><a href="../building-blocks/pickers.html">Pickers</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header empty"><a href="../downloads/index.html">Downloads</a></div>
-          </li>
-
-          <li>
-            <div id="back-dac-section"><a href="../../index.html">Developers</a></div>
-          </li>
-
-        </ul>
-
-        <div id="content">
-
-          
-          <div class="layout-content-row content-header">
-            <div class="layout-content-col span-9">
-              <h2>Iconography</h2>
-            </div>
-            <div class="paging-links layout-content-col span-4">
-              <a href="#" class="prev-page-link">Previous</a>
-              <a href="#" class="next-page-link">Next</a>
-            </div>
-          </div>
-          
-
-          
-
-<img src="../static/content/iconography_overview.png">
-
-<p>An icon is a graphic that takes up a small portion of screen real estate and provides a quick,
-intuitive representation of an action, a status, or an app.</p>
-
-
-
-<h2 id="launcher">Launcher</h2>
-
-<p>The launcher icon is the visual representation of your app on the Home or All Apps screen. Since the
-user can change the Home screen's wallpaper, make sure that your launcher icon is clearly visible on
-any type of background.</p>
-
-<div class="layout-content-row">
-  <div class="layout-content-col span-4">
-
-    <img src="../static/content/iconography_launcher_size.png">
-
-  </div>
-  <div class="layout-content-col span-4">
-
-    <img src="../static/content/iconography_launcher_focal.png">
-
-  </div>
-  <div class="layout-content-col span-4">
-
-    <img src="../static/content/iconography_launcher_style.png">
-
-  </div>
-</div>
-
-<div class="layout-content-row">
-  <div class="layout-content-col span-4">
-
-    <h4>Sizes &amp; scale</h4>
-
-    <ul>
-      <li class="no-bullet with-icon tablet">
-        <p>Launcher icons on a mobile device must be <strong>48x48 <acronym title="Density-independent pixels. One dp is one pixel on a 160 dpi screen.">dp</acronym></strong>.</p></li>
-      <li class="no-bullet with-icon web">
-        <p>Launcher icons for display in Market must be <strong>512x512 pixels</strong>.</p></li>
-    </ul>
-
-  </div>
-  <div class="layout-content-col span-4">
-
-    <h4>Proportions</h4>
-
-    <ul>
-      <li class="no-bullet with-icon tablet">
-        <p>Full asset, <strong>48x48 dp</strong></p>
-      </li>
-    </ul>
-
-  </div>
-  <div class="layout-content-col span-4">
-
-<h4>Style</h4>
-<p>Use a distinct silhouette. Three-dimensional, front view, with a slight perspective as if viewed
-from above, so that users perceive some depth.</p>
-
-  </div>
-</div>
-
-
-<div class="layout-content-row">
-  <div class="layout-content-col span-4">
-    &nbsp;
-  </div>
-  <div class="layout-content-col span-7">
-
-    <img src="../static/content/iconography_launcher_example.png">
-
-  </div>
-  <!-- 2 free columns -->
-</div>
-
-<div class="layout-content-row">
-  <div class="layout-content-col span-12">
-
-    <img src="../static/content/iconography_launcher_example2.png">
-
-    <div class="vspace size-2">&nbsp;</div>
-
-  </div>
-  <!-- 1 free columns -->
-</div>
-
-
-<h2 id="action-bar">Action Bar</h2>
-
-<p>
-
-Action bar icons are graphic buttons that represent the most important actions people can take
-within your app. Each one should employ a simple metaphor representing a single concept that most
-people can grasp at a glance.
-
-</p>
-<p>
-
-Pre-defined glyphs should be used for certain common actions such as "refresh" and "share." The
-download link below provides a package with icons that are scaled for various screen densities and
-are suitable for use with the Holo Light and Holo Dark themes. The package also includes unstyled
-icons that you can modify to match your theme, in addition to Adobe&reg; Illustrator&reg; source
-files for further customization.
-
-</p>
-<p>
-
-<a href="https://dl-ssl.google.com/android/design/Android_Design_Icons_20120229.zip">Download the Action Bar Icon Pack</a>
-
-</p>
-
-<div class="layout-content-row">
-  <div class="layout-content-col span-4">
-
-    <img src="../static/content/iconography_actionbar_size.png">
-
-  </div>
-  <div class="layout-content-col span-4">
-
-    <img src="../static/content/iconography_actionbar_focal.png">
-
-  </div>
-  <div class="layout-content-col span-4">
-
-    <img src="../static/content/iconography_actionbar_style.png">
-
-  </div>
-</div>
-
-<div class="layout-content-row">
-  <div class="layout-content-col span-4">
-
-    <h4>Sizes &amp; scale</h4>
-
-    <ul>
-      <li class="no-bullet with-icon tablet">
-        <p>Action bar icons for phones should be <strong>32x32 <acronym title="Density-independent pixels. One dp is one pixel on a 160 dpi screen.">dp</acronym></strong>.</p></li>
-    </ul>
-
-  </div>
-  <div class="layout-content-col span-4">
-
-    <h4>Focal area &amp; proportions</h4>
-
-    <ul>
-      <li class="no-bullet with-icon tablet">
-        <p>Full asset, <strong>32x32 dp</strong></p>
-        <p>Optical square, <strong>24x24 dp</strong></p>
-      </li>
-    </ul>
-
-  </div>
-  <div class="layout-content-col span-4">
-
-<h4>Style</h4>
-<p>Pictographic, flat, not too detailed, with smooth curves or sharp shapes. If the graphic is thin,
-rotate it 45&deg; left or right to fill the focal space. The thickness of the strokes and negative
-spaces should be a minimum of 2 dp.</p>
-
-  </div>
-</div>
-
-
-<div class="layout-content-row">
-  <div class="layout-content-col span-3">
-
-<h4>Colors</h4>
-<p>Colors: <strong>#333333</strong><br />
-Enabled: <strong>60%</strong> opacity<br />
-Disabled: <strong>30%</strong> opacity</p>
-<div class="vspace size-1">&nbsp;</div>
-
-<p>Colors: <strong>#FFFFFF</strong><br />
-Enabled: <strong>80%</strong> opacity<br />
-Disabled: <strong>30%</strong> opacity</p>
-
-  </div>
-  <div class="layout-content-col span-9">
-
-    <img src="../static/content/iconography_actionbar_colors.png">
-
-  </div>
-</div>
-
-
-<h2 id="small-contextual">Small / Contextual Icons</h2>
-
-<p>Within the body of your app, use small icons to surface actions and/or provide status for specific
-items. For example, in the Gmail app, each message has a star icon that marks the message as
-important.</p>
-
-
-<div class="layout-content-row">
-  <div class="layout-content-col span-4">
-
-    <img src="../static/content/iconography_small_size.png">
-
-  </div>
-  <div class="layout-content-col span-4">
-
-    <img src="../static/content/iconography_small_focal.png">
-
-  </div>
-  <div class="layout-content-col span-4">
-
-    <img src="../static/content/iconography_small_style.png">
-
-  </div>
-</div>
-
-<div class="layout-content-row">
-  <div class="layout-content-col span-4">
-
-    <h4>Sizes &amp; scale</h4>
-
-    <ul>
-      <li class="no-bullet with-icon tablet">
-        <p>Small icons should be <strong>16x16 <acronym title="Density-independent pixels. One dp is one pixel on a 160 dpi screen.">dp</acronym></strong>.</p></li>
-    </ul>
-
-  </div>
-  <div class="layout-content-col span-4">
-
-    <h4>Focal area &amp; proportions</h4>
-
-    <ul>
-      <li class="no-bullet with-icon tablet">
-        <p>Full asset, <strong>16x16 dp</strong></p>
-        <p>Optical square, <strong>12x12 dp</strong></p>
-      </li>
-    </ul>
-
-  </div>
-  <div class="layout-content-col span-4">
-
-<h4>Style</h4>
-<p>Neutral, flat, and simple. Filled shapes are easier to see than thin strokes. Use a single visual
-metaphor so that a user can easily recognize and understand its purpose.</p>
-
-  </div>
-</div>
-
-
-<div class="layout-content-row">
-  <div class="layout-content-col span-4">
-
-    <img src="../static/content/iconography_small_colors.png">
-
-    <div class="vspace size-2">&nbsp;</div>
-
-<h4>Colors</h4>
-<p>Use non-neutral colors sparingly and with purpose. For example, Gmail uses yellow in the star icon
-to indicate a bookmarked message. If an icon is actionable, choose a color that contrasts well with
-the background.</p>
-
-  </div>
-  <div class="layout-content-col span-7">
-
-    <img src="../static/content/iconography_small_example.png">
-
-  </div>
-  <!-- 2 free columns -->
-</div>
-
-
-<h2 id="notification">Notification Icons</h2>
-
-<p>If your app generates notifications, provide an icon that the system can display in the status bar
-whenever a new notification is available.</p>
-
-
-<div class="layout-content-row">
-  <div class="layout-content-col span-4">
-
-    <img src="../static/content/iconography_notification_size.png">
-
-  </div>
-  <div class="layout-content-col span-4">
-
-    <img src="../static/content/iconography_notification_focal.png">
-
-  </div>
-  <div class="layout-content-col span-4">
-
-    <img src="../static/content/iconography_notification_style.png">
-
-  </div>
-</div>
-
-<div class="layout-content-row">
-  <div class="layout-content-col span-4">
-
-    <h4>Sizes &amp; scale</h4>
-
-    <ul>
-      <li class="no-bullet with-icon tablet">
-        <p>Notification icons must be <strong>24x24 <acronym title="Density-independent pixels. One dp is one pixel on a 160 dpi screen.">dp</acronym></strong>.</p></li>
-    </ul>
-
-  </div>
-  <div class="layout-content-col span-4">
-
-    <h4>Focal area &amp; proportions</h4>
-
-    <ul>
-      <li class="no-bullet with-icon tablet">
-        <p>Full asset, <strong>24x24 dp</strong></p>
-        <p>Optical square, <strong>22x22 dp</strong></p>
-      </li>
-    </ul>
-
-  </div>
-  <div class="layout-content-col span-4">
-
-<h4>Style</h4>
-<p>Keep the style flat and simple, using the same single, visual metaphor as your launcher icon.</p>
-
-  </div>
-</div>
-
-
-<div class="layout-content-row">
-  <div class="layout-content-col span-4">
-
-<h4>Colors</h4>
-<p>Notification icons must be entirely white. Also, the system may scale down and/or darken the icons.</p>
-
-  </div>
-  <div class="layout-content-col span-7">
-
-    <img src="../static/content/iconography_notification_example.png">
-
-  </div>
-  <!-- 2 free columns -->
-</div>
-
-
-
-          
-          <div class="layout-content-row content-footer">
-            <div class="paging-links layout-content-col span-9">&nbsp;</div>
-            <div class="paging-links layout-content-col span-4">
-              <a href="#" class="prev-page-link">Previous</a>
-              <a href="#" class="next-page-link">Next</a>
-            </div>
-          </div>
-          
-        </div>
-
-      </div>
-
-      <div id="page-footer">
-
-        <p id="copyright">
-          Except as noted, this content is licensed under
-          <a href="http://creativecommons.org/licenses/by/2.5/">
-          Creative Commons Attribution 2.5</a>.<br>
-          For details and restrictions, see the
-          <a href="http://developer.android.com/license.html">Content License</a>.
-        </p>
-
-        <p>
-          <a href="http://www.android.com/terms.html">Site Terms of Service</a> &ndash;
-          <a href="http://www.android.com/privacy.html">Privacy Policy</a> &ndash;
-          <a href="http://www.android.com/branding.html">Brand Guidelines</a>
-        </p>
-
-      </div>
-    </div>
-
-    <script src="../static/jquery-1.6.2.min.js"></script>
-    <script>
-    var SITE_ROOT = '../';
-    </script>
-    <script src="../static/default.js"></script>
-
-
-    <script type="text/javascript">
-    var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
-    document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
-    </script>
-    <script type="text/javascript">
-    var pageTracker = _gat._getTracker("UA-5831155-1");
-    pageTracker._trackPageview();
-    </script>
-  </body>
-</html>
diff --git a/docs/html/design/style/iconography.jd b/docs/html/design/style/iconography.jd
new file mode 100644
index 0000000..775e45d
--- /dev/null
+++ b/docs/html/design/style/iconography.jd
@@ -0,0 +1,340 @@
+page.title=Iconography
+@jd:body
+
+<img src="{@docRoot}design/media/iconography_overview.png">
+
+<p>An icon is a graphic that takes up a small portion of screen real estate and provides a quick,
+intuitive representation of an action, a status, or an app.</p>
+
+
+
+<h2 id="launcher">Launcher</h2>
+
+<p>The launcher icon is the visual representation of your app on the Home or All Apps screen. Since the
+user can change the Home screen's wallpaper, make sure that your launcher icon is clearly visible on
+any type of background.</p>
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-4">
+
+    <img src="{@docRoot}design/media/iconography_launcher_size.png">
+
+  </div>
+  <div class="layout-content-col span-4">
+
+    <img src="{@docRoot}design/media/iconography_launcher_focal.png">
+
+  </div>
+  <div class="layout-content-col span-4">
+
+    <img src="{@docRoot}design/media/iconography_launcher_style.png">
+
+  </div>
+</div>
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-4">
+
+    <h4>Sizes &amp; scale</h4>
+
+    <ul>
+      <li class="no-bullet with-icon tablet">
+        <p>Launcher icons on a mobile device must be <strong>48x48 <acronym title="Density-independent pixels. One dp is one pixel on a 160 dpi screen.">dp</acronym></strong>.</p></li>
+      <li class="no-bullet with-icon web">
+        <p>Launcher icons for display on Google Play must be <strong>512x512 pixels</strong>.</p></li>
+    </ul>
+
+  </div>
+  <div class="layout-content-col span-4">
+
+    <h4>Proportions</h4>
+
+    <ul>
+      <li class="no-bullet with-icon tablet">
+        <p>Full asset, <strong>48x48 dp</strong></p>
+      </li>
+    </ul>
+
+  </div>
+  <div class="layout-content-col span-4">
+
+<h4>Style</h4>
+<p>Use a distinct silhouette. Three-dimensional, front view, with a slight perspective as if viewed
+from above, so that users perceive some depth.</p>
+
+  </div>
+</div>
+
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-4">
+    &nbsp;
+  </div>
+  <div class="layout-content-col span-7">
+
+    <img src="{@docRoot}design/media/iconography_launcher_example.png">
+
+  </div>
+  <!-- 2 free columns -->
+</div>
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-12">
+
+    <img src="{@docRoot}design/media/iconography_launcher_example2.png">
+
+    <div class="vspace size-2">&nbsp;</div>
+
+  </div>
+  <!-- 1 free columns -->
+</div>
+
+
+<h2 id="action-bar">Action Bar</h2>
+
+<p>
+
+Action bar icons are graphic buttons that represent the most important actions people can take
+within your app. Each one should employ a simple metaphor representing a single concept that most
+people can grasp at a glance.
+
+</p>
+<p>
+
+Pre-defined glyphs should be used for certain common actions such as "refresh" and "share." The
+download link below provides a package with icons that are scaled for various screen densities and
+are suitable for use with the Holo Light and Holo Dark themes. The package also includes unstyled
+icons that you can modify to match your theme, in addition to Adobe&reg; Illustrator&reg; source
+files for further customization.
+
+</p>
+<p>
+
+<a href="https://dl-ssl.google.com/android/design/Android_Design_Icons_20120229.zip">Download the Action Bar Icon Pack</a>
+
+</p>
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-4">
+
+    <img src="{@docRoot}design/media/iconography_actionbar_size.png">
+
+  </div>
+  <div class="layout-content-col span-4">
+
+    <img src="{@docRoot}design/media/iconography_actionbar_focal.png">
+
+  </div>
+  <div class="layout-content-col span-4">
+
+    <img src="{@docRoot}design/media/iconography_actionbar_style.png">
+
+  </div>
+</div>
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-4">
+
+    <h4>Sizes &amp; scale</h4>
+
+    <ul>
+      <li class="no-bullet with-icon tablet">
+        <p>Action bar icons for phones should be <strong>32x32 <acronym title="Density-independent pixels. One dp is one pixel on a 160 dpi screen.">dp</acronym></strong>.</p></li>
+    </ul>
+
+  </div>
+  <div class="layout-content-col span-4">
+
+    <h4>Focal area &amp; proportions</h4>
+
+    <ul>
+      <li class="no-bullet with-icon tablet">
+        <p>Full asset, <strong>32x32 dp</strong></p>
+        <p>Optical square, <strong>24x24 dp</strong></p>
+      </li>
+    </ul>
+
+  </div>
+  <div class="layout-content-col span-4">
+
+<h4>Style</h4>
+<p>Pictographic, flat, not too detailed, with smooth curves or sharp shapes. If the graphic is thin,
+rotate it 45&deg; left or right to fill the focal space. The thickness of the strokes and negative
+spaces should be a minimum of 2 dp.</p>
+
+  </div>
+</div>
+
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-3">
+
+<h4>Colors</h4>
+<p>Colors: <strong>#333333</strong><br />
+Enabled: <strong>60%</strong> opacity<br />
+Disabled: <strong>30%</strong> opacity</p>
+<div class="vspace size-1">&nbsp;</div>
+
+<p>Colors: <strong>#FFFFFF</strong><br />
+Enabled: <strong>80%</strong> opacity<br />
+Disabled: <strong>30%</strong> opacity</p>
+
+  </div>
+  <div class="layout-content-col span-9">
+
+    <img src="{@docRoot}design/media/iconography_actionbar_colors.png">
+
+  </div>
+</div>
+
+
+<h2 id="small-contextual">Small / Contextual Icons</h2>
+
+<p>Within the body of your app, use small icons to surface actions and/or provide status for specific
+items. For example, in the Gmail app, each message has a star icon that marks the message as
+important.</p>
+
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-4">
+
+    <img src="{@docRoot}design/media/iconography_small_size.png">
+
+  </div>
+  <div class="layout-content-col span-4">
+
+    <img src="{@docRoot}design/media/iconography_small_focal.png">
+
+  </div>
+  <div class="layout-content-col span-4">
+
+    <img src="{@docRoot}design/media/iconography_small_style.png">
+
+  </div>
+</div>
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-4">
+
+    <h4>Sizes &amp; scale</h4>
+
+    <ul>
+      <li class="no-bullet with-icon tablet">
+        <p>Small icons should be <strong>16x16 <acronym title="Density-independent pixels. One dp is one pixel on a 160 dpi screen.">dp</acronym></strong>.</p></li>
+    </ul>
+
+  </div>
+  <div class="layout-content-col span-4">
+
+    <h4>Focal area &amp; proportions</h4>
+
+    <ul>
+      <li class="no-bullet with-icon tablet">
+        <p>Full asset, <strong>16x16 dp</strong></p>
+        <p>Optical square, <strong>12x12 dp</strong></p>
+      </li>
+    </ul>
+
+  </div>
+  <div class="layout-content-col span-4">
+
+<h4>Style</h4>
+<p>Neutral, flat, and simple. Filled shapes are easier to see than thin strokes. Use a single visual
+metaphor so that a user can easily recognize and understand its purpose.</p>
+
+  </div>
+</div>
+
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-4">
+
+    <img src="{@docRoot}design/media/iconography_small_colors.png">
+
+    <div class="vspace size-2">&nbsp;</div>
+
+<h4>Colors</h4>
+<p>Use non-neutral colors sparingly and with purpose. For example, Gmail uses yellow in the star icon
+to indicate a bookmarked message. If an icon is actionable, choose a color that contrasts well with
+the background.</p>
+
+  </div>
+  <div class="layout-content-col span-7">
+
+    <img src="{@docRoot}design/media/iconography_small_example.png">
+
+  </div>
+  <!-- 2 free columns -->
+</div>
+
+
+<h2 id="notification">Notification Icons</h2>
+
+<p>If your app generates notifications, provide an icon that the system can display in the status bar
+whenever a new notification is available.</p>
+
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-4">
+
+    <img src="{@docRoot}design/media/iconography_notification_size.png">
+
+  </div>
+  <div class="layout-content-col span-4">
+
+    <img src="{@docRoot}design/media/iconography_notification_focal.png">
+
+  </div>
+  <div class="layout-content-col span-4">
+
+    <img src="{@docRoot}design/media/iconography_notification_style.png">
+
+  </div>
+</div>
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-4">
+
+    <h4>Sizes &amp; scale</h4>
+
+    <ul>
+      <li class="no-bullet with-icon tablet">
+        <p>Notification icons must be <strong>24x24 <acronym title="Density-independent pixels. One dp is one pixel on a 160 dpi screen.">dp</acronym></strong>.</p></li>
+    </ul>
+
+  </div>
+  <div class="layout-content-col span-4">
+
+    <h4>Focal area &amp; proportions</h4>
+
+    <ul>
+      <li class="no-bullet with-icon tablet">
+        <p>Full asset, <strong>24x24 dp</strong></p>
+        <p>Optical square, <strong>22x22 dp</strong></p>
+      </li>
+    </ul>
+
+  </div>
+  <div class="layout-content-col span-4">
+
+<h4>Style</h4>
+<p>Keep the style flat and simple, using the same single, visual metaphor as your launcher icon.</p>
+
+  </div>
+</div>
+
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-4">
+
+<h4>Colors</h4>
+<p>Notification icons must be entirely white. Also, the system may scale down and/or darken the icons.</p>
+
+  </div>
+  <div class="layout-content-col span-7">
+
+    <img src="{@docRoot}design/media/iconography_notification_example.png">
+
+  </div>
+  <!-- 2 free columns -->
+</div>
diff --git a/docs/html/design/style/index.html b/docs/html/design/style/index.html
deleted file mode 100644
index c7ac58f..0000000
--- a/docs/html/design/style/index.html
+++ /dev/null
@@ -1,175 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-  <head>
-    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
-    <title>
-
-Android Design - Design Elements
-    </title>
-    <link rel="shortcut icon" type="image/x-icon" href="/favicon.ico">
-    <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Roboto:regular,medium,thin,italic,mediumitalic">
-    <link rel="stylesheet" href="../static/yui-3.3.0-reset-min.css">
-    <link rel="stylesheet" href="../static/default.css">
-
-<style>
-#landing-graphic-container {
-  position: relative;
-}
-
-#text-overlay {
-  position: absolute;
-  left: 10px;
-  top: 402px;
-  width: 220px;
-}
-</style>
-
-  </head>
-  <body>
-
-    <div id="page-container">
-
-      <div id="page-header"><a href="../index.html">Android Design</a></div>
-
-      <div id="main-row">
-
-        <ul id="nav">
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../index.html">Get Started</a></div>
-            <ul>
-              <li><a href="../get-started/creative-vision.html">Creative Vision</a></li>
-              <li><a href="../get-started/principles.html">Design Principles</a></li>
-              <li><a href="../get-started/ui-overview.html">UI Overview</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../style/index.html">Style</a></div>
-            <ul>
-              <li><a href="../style/devices-displays.html">Devices and Displays</a></li>
-              <li><a href="../style/themes.html">Themes</a></li>
-              <li><a href="../style/touch-feedback.html">Touch Feedback</a></li>
-              <li><a href="../style/metrics-grids.html">Metrics and Grids</a></li>
-              <li><a href="../style/typography.html">Typography</a></li>
-              <li><a href="../style/color.html">Color</a></li>
-              <li><a href="../style/iconography.html">Iconography</a></li>
-              <li><a href="../style/writing.html">Writing Style</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../patterns/index.html">Patterns</a></div>
-            <ul>
-              <li><a href="../patterns/new-4-0.html">New in Android 4.0</a></li>
-              <li><a href="../patterns/gestures.html">Gestures</a></li>
-              <li><a href="../patterns/app-structure.html">App Structure</a></li>
-              <li><a href="../patterns/navigation.html">Navigation</a></li>
-              <li><a href="../patterns/actionbar.html">Action Bar</a></li>
-              <li><a href="../patterns/multi-pane-layouts.html">Multi-pane Layouts</a></li>
-              <li><a href="../patterns/swipe-views.html">Swipe Views</a></li>
-              <li><a href="../patterns/selection.html">Selection</a></li>
-              <li><a href="../patterns/notifications.html">Notifications</a></li>
-              <li><a href="../patterns/compatibility.html">Compatibility</a></li>
-              <li><a href="../patterns/pure-android.html">Pure Android</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../building-blocks/index.html">Building Blocks</a></div>
-            <ul>
-              <li><a href="../building-blocks/tabs.html">Tabs</a></li>
-              <li><a href="../building-blocks/lists.html">Lists</a></li>
-              <li><a href="../building-blocks/grid-lists.html">Grid Lists</a></li>
-              <li><a href="../building-blocks/scrolling.html">Scrolling</a></li>
-              <li><a href="../building-blocks/spinners.html">Spinners</a></li>
-              <li><a href="../building-blocks/buttons.html">Buttons</a></li>
-              <li><a href="../building-blocks/text-fields.html">Text Fields</a></li>
-              <li><a href="../building-blocks/seek-bars.html">Seek Bars</a></li>
-              <li><a href="../building-blocks/progress.html">Progress &amp; Activity</a></li>
-              <li><a href="../building-blocks/switches.html">Switches</a></li>
-              <li><a href="../building-blocks/dialogs.html">Dialogs</a></li>
-              <li><a href="../building-blocks/pickers.html">Pickers</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header empty"><a href="../downloads/index.html">Downloads</a></div>
-          </li>
-
-          <li>
-            <div id="back-dac-section"><a href="../../index.html">Developers</a></div>
-          </li>
-
-        </ul>
-
-        <div id="content">
-
-          
-<div class="layout-content-row content-header just-links">
-  <div class="layout-content-col span-9">&nbsp;</div>
-  <div class="paging-links layout-content-col span-4">
-    <a href="#" class="prev-page-link">Previous</a>
-    <a href="#" class="next-page-link">Next</a>
-  </div>
-</div>
-
-
-          
-
-<div id="landing-graphic-container">
-  <div id="text-overlay">
-    Build visually compelling apps that look great on any device. 
-    <br><br>
-    <a href="../style/devices-displays.html" class="landing-page-link">Devices and Displays</a>
-  </div>
-
-  <a href="../style/devices-displays.html">
-    <img src="../static/content/design_elements_landing.png">
-  </a>
-</div>
-
-
-
-          
-
-        </div>
-
-      </div>
-
-      <div id="page-footer">
-
-        <p id="copyright">
-          Except as noted, this content is licensed under
-          <a href="http://creativecommons.org/licenses/by/2.5/">
-          Creative Commons Attribution 2.5</a>.<br>
-          For details and restrictions, see the
-          <a href="http://developer.android.com/license.html">Content License</a>.
-        </p>
-
-        <p>
-          <a href="http://www.android.com/terms.html">Site Terms of Service</a> &ndash;
-          <a href="http://www.android.com/privacy.html">Privacy Policy</a> &ndash;
-          <a href="http://www.android.com/branding.html">Brand Guidelines</a>
-        </p>
-
-      </div>
-    </div>
-
-    <script src="../static/jquery-1.6.2.min.js"></script>
-    <script>
-    var SITE_ROOT = '../';
-    </script>
-    <script src="../static/default.js"></script>
-
-
-    <script type="text/javascript">
-    var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
-    document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
-    </script>
-    <script type="text/javascript">
-    var pageTracker = _gat._getTracker("UA-5831155-1");
-    pageTracker._trackPageview();
-    </script>
-  </body>
-</html>
diff --git a/docs/html/design/style/index.jd b/docs/html/design/style/index.jd
new file mode 100644
index 0000000..d346aea
--- /dev/null
+++ b/docs/html/design/style/index.jd
@@ -0,0 +1,29 @@
+page.title=Style
+header.justLinks=1
+footer.hide=1
+@jd:body
+
+<style>
+#landing-graphic-container {
+  position: relative;
+}
+
+#text-overlay {
+  position: absolute;
+  left: 10px;
+  top: 402px;
+  width: 220px;
+}
+</style>
+
+<div id="landing-graphic-container">
+  <div id="text-overlay">
+    Build visually compelling apps that look great on any device. 
+    <br><br>
+    <a href="{@docRoot}design/style/devices-displays.html" class="landing-page-link">Devices and Displays</a>
+  </div>
+
+  <a href="{@docRoot}design/style/devices-displays.html">
+    <img src="{@docRoot}design/media/design_elements_landing.png">
+  </a>
+</div>
diff --git a/docs/html/design/style/metrics-grids.html b/docs/html/design/style/metrics-grids.html
deleted file mode 100644
index 7bb9dd0..0000000
--- a/docs/html/design/style/metrics-grids.html
+++ /dev/null
@@ -1,218 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-  <head>
-    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
-    <title>
-
-Android Design - Metrics and Grids
-    </title>
-    <link rel="shortcut icon" type="image/x-icon" href="/favicon.ico">
-    <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Roboto:regular,medium,thin,italic,mediumitalic">
-    <link rel="stylesheet" href="../static/yui-3.3.0-reset-min.css">
-    <link rel="stylesheet" href="../static/default.css">
-
-  </head>
-  <body>
-
-    <div id="page-container">
-
-      <div id="page-header"><a href="../index.html">Android Design</a></div>
-
-      <div id="main-row">
-
-        <ul id="nav">
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../index.html">Get Started</a></div>
-            <ul>
-              <li><a href="../get-started/creative-vision.html">Creative Vision</a></li>
-              <li><a href="../get-started/principles.html">Design Principles</a></li>
-              <li><a href="../get-started/ui-overview.html">UI Overview</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../style/index.html">Style</a></div>
-            <ul>
-              <li><a href="../style/devices-displays.html">Devices and Displays</a></li>
-              <li><a href="../style/themes.html">Themes</a></li>
-              <li><a href="../style/touch-feedback.html">Touch Feedback</a></li>
-              <li><a href="../style/metrics-grids.html">Metrics and Grids</a></li>
-              <li><a href="../style/typography.html">Typography</a></li>
-              <li><a href="../style/color.html">Color</a></li>
-              <li><a href="../style/iconography.html">Iconography</a></li>
-              <li><a href="../style/writing.html">Writing Style</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../patterns/index.html">Patterns</a></div>
-            <ul>
-              <li><a href="../patterns/new-4-0.html">New in Android 4.0</a></li>
-              <li><a href="../patterns/gestures.html">Gestures</a></li>
-              <li><a href="../patterns/app-structure.html">App Structure</a></li>
-              <li><a href="../patterns/navigation.html">Navigation</a></li>
-              <li><a href="../patterns/actionbar.html">Action Bar</a></li>
-              <li><a href="../patterns/multi-pane-layouts.html">Multi-pane Layouts</a></li>
-              <li><a href="../patterns/swipe-views.html">Swipe Views</a></li>
-              <li><a href="../patterns/selection.html">Selection</a></li>
-              <li><a href="../patterns/notifications.html">Notifications</a></li>
-              <li><a href="../patterns/compatibility.html">Compatibility</a></li>
-              <li><a href="../patterns/pure-android.html">Pure Android</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../building-blocks/index.html">Building Blocks</a></div>
-            <ul>
-              <li><a href="../building-blocks/tabs.html">Tabs</a></li>
-              <li><a href="../building-blocks/lists.html">Lists</a></li>
-              <li><a href="../building-blocks/grid-lists.html">Grid Lists</a></li>
-              <li><a href="../building-blocks/scrolling.html">Scrolling</a></li>
-              <li><a href="../building-blocks/spinners.html">Spinners</a></li>
-              <li><a href="../building-blocks/buttons.html">Buttons</a></li>
-              <li><a href="../building-blocks/text-fields.html">Text Fields</a></li>
-              <li><a href="../building-blocks/seek-bars.html">Seek Bars</a></li>
-              <li><a href="../building-blocks/progress.html">Progress &amp; Activity</a></li>
-              <li><a href="../building-blocks/switches.html">Switches</a></li>
-              <li><a href="../building-blocks/dialogs.html">Dialogs</a></li>
-              <li><a href="../building-blocks/pickers.html">Pickers</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header empty"><a href="../downloads/index.html">Downloads</a></div>
-          </li>
-
-          <li>
-            <div id="back-dac-section"><a href="../../index.html">Developers</a></div>
-          </li>
-
-        </ul>
-
-        <div id="content">
-
-          
-          <div class="layout-content-row content-header">
-            <div class="layout-content-col span-9">
-              <h2>Metrics and Grids</h2>
-            </div>
-            <div class="paging-links layout-content-col span-4">
-              <a href="#" class="prev-page-link">Previous</a>
-              <a href="#" class="next-page-link">Next</a>
-            </div>
-          </div>
-          
-
-          
-
-<p>Devices vary not only in physical size, but also in screen density (<acronym title="Dots per
-inch">DPI</acronym>). To simplify the way you design for multiple screens, think of each device as
-falling into a particular size bucket and density bucket. The size buckets are <em>handset</em> (smaller than
-600<acronym title="Density-independent pixels. One dp is one pixel on a 160 dpi
-screen.">dp</acronym>) and <em>tablet</em> (larger than or equal 600dp). The density buckets are <acronym
-title="Low density (120 dpi)">LDPI</acronym>, <acronym title="Medium density (160
-dpi)">MDPI</acronym>, <acronym title="High density (240 dpi)">HDPI</acronym>, and <acronym title
-="Extra-high density (320 dpi)">XHDPI</acronym>. Optimize your application's UI by designing
-alternative layouts for some of the different size buckets, and provide alternative bitmap images
-for different density buckets.</p>
-
-<div class="layout-content-row">
-  <div class="layout-content-col span-8">
-
-    <img src="../static/content/metrics_diagram.png">
-
-  </div>
-  <div class="layout-content-col span-5">
-
-<h4>Space considerations</h4>
-<p>Devices vary in the amount of density-independent pixels (dp) they can display.</p>
-<p>To see more, visit the
-<a href="http://developer.android.com/resources/dashboard/screens.html" target="_blank">
-Screen Sizes and Densities Device Dashboard</a>.</p>
-
-  </div>
-</div>
-
-<h2 id="48dp-rhythm">48dp Rhythm</h2>
-
-<p>Touchable UI components are generally laid out along 48dp units.</p>
-
-<img src="../static/content/metrics_48.png">
-
-<div class="vspace size-2">&nbsp;</div>
-
-<h4>Why 48dp?</h4>
-<p>On average, 48dp translate to a physical size of about 9mm (with some variability). This is
-comfortably in the range of recommended target sizes (7-10 mm) for touchscreen objects and users
-will be able to reliably and accurately target them with their fingers.</p>
-<p>If you design your elements to be at least 48dp high and wide you can guarantee that:</p>
-<ul>
-<li>your targets will never be smaller than the minimum recommended target size of 7mm regardless of
-  what screen they are displayed on.</li>
-<li>you strike a good compromise between overall information density on the one hand, and
-  targetability of UI elements on the other.</li>
-</ul>
-
-<img src="../static/content/metrics_closeup.png">
-
-<div class="vspace size-2">&nbsp;</div>
-
-<h4>Mind the gaps</h4>
-<p>Spacing between each UI element is 8dp.</p>
-
-<h2 id="examples">Examples</h2>
-
-<img src="../static/content/metrics_forms.png">
-
-
-
-          
-          <div class="layout-content-row content-footer">
-            <div class="paging-links layout-content-col span-9">&nbsp;</div>
-            <div class="paging-links layout-content-col span-4">
-              <a href="#" class="prev-page-link">Previous</a>
-              <a href="#" class="next-page-link">Next</a>
-            </div>
-          </div>
-          
-        </div>
-
-      </div>
-
-      <div id="page-footer">
-
-        <p id="copyright">
-          Except as noted, this content is licensed under
-          <a href="http://creativecommons.org/licenses/by/2.5/">
-          Creative Commons Attribution 2.5</a>.<br>
-          For details and restrictions, see the
-          <a href="http://developer.android.com/license.html">Content License</a>.
-        </p>
-
-        <p>
-          <a href="http://www.android.com/terms.html">Site Terms of Service</a> &ndash;
-          <a href="http://www.android.com/privacy.html">Privacy Policy</a> &ndash;
-          <a href="http://www.android.com/branding.html">Brand Guidelines</a>
-        </p>
-
-      </div>
-    </div>
-
-    <script src="../static/jquery-1.6.2.min.js"></script>
-    <script>
-    var SITE_ROOT = '../';
-    </script>
-    <script src="../static/default.js"></script>
-
-
-    <script type="text/javascript">
-    var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
-    document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
-    </script>
-    <script type="text/javascript">
-    var pageTracker = _gat._getTracker("UA-5831155-1");
-    pageTracker._trackPageview();
-    </script>
-  </body>
-</html>
diff --git a/docs/html/design/style/metrics-grids.jd b/docs/html/design/style/metrics-grids.jd
new file mode 100644
index 0000000..e2b9ab5
--- /dev/null
+++ b/docs/html/design/style/metrics-grids.jd
@@ -0,0 +1,61 @@
+page.title=Metrics and Grids
+@jd:body
+
+<p>Devices vary not only in physical size, but also in screen density (<acronym title="Dots per
+inch">DPI</acronym>). To simplify the way you design for multiple screens, think of each device as
+falling into a particular size bucket and density bucket. The size buckets are <em>handset</em> (smaller than
+600<acronym title="Density-independent pixels. One dp is one pixel on a 160 dpi
+screen.">dp</acronym>) and <em>tablet</em> (larger than or equal 600dp). The density buckets are <acronym
+title="Low density (120 dpi)">LDPI</acronym>, <acronym title="Medium density (160
+dpi)">MDPI</acronym>, <acronym title="High density (240 dpi)">HDPI</acronym>, and <acronym title
+="Extra-high density (320 dpi)">XHDPI</acronym>. Optimize your application's UI by designing
+alternative layouts for some of the different size buckets, and provide alternative bitmap images
+for different density buckets.</p>
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-8">
+
+    <img src="{@docRoot}design/media/metrics_diagram.png">
+
+  </div>
+  <div class="layout-content-col span-5">
+
+<h4>Space considerations</h4>
+<p>Devices vary in the amount of density-independent pixels (dp) they can display.</p>
+<p>To see more, visit the
+<a href="http://developer.android.com/resources/dashboard/screens.html" target="_blank">
+Screen Sizes and Densities Device Dashboard</a>.</p>
+
+  </div>
+</div>
+
+<h2 id="48dp-rhythm">48dp Rhythm</h2>
+
+<p>Touchable UI components are generally laid out along 48dp units.</p>
+
+<img src="{@docRoot}design/media/metrics_48.png">
+
+<div class="vspace size-2">&nbsp;</div>
+
+<h4>Why 48dp?</h4>
+<p>On average, 48dp translate to a physical size of about 9mm (with some variability). This is
+comfortably in the range of recommended target sizes (7-10 mm) for touchscreen objects and users
+will be able to reliably and accurately target them with their fingers.</p>
+<p>If you design your elements to be at least 48dp high and wide you can guarantee that:</p>
+<ul>
+<li>your targets will never be smaller than the minimum recommended target size of 7mm regardless of
+  what screen they are displayed on.</li>
+<li>you strike a good compromise between overall information density on the one hand, and
+  targetability of UI elements on the other.</li>
+</ul>
+
+<img src="{@docRoot}design/media/metrics_closeup.png">
+
+<div class="vspace size-2">&nbsp;</div>
+
+<h4>Mind the gaps</h4>
+<p>Spacing between each UI element is 8dp.</p>
+
+<h2 id="examples">Examples</h2>
+
+<img src="{@docRoot}design/media/metrics_forms.png">
diff --git a/docs/html/design/style/themes.html b/docs/html/design/style/themes.html
deleted file mode 100644
index a629978..0000000
--- a/docs/html/design/style/themes.html
+++ /dev/null
@@ -1,199 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-  <head>
-    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
-    <title>
-
-Android Design - Themes
-    </title>
-    <link rel="shortcut icon" type="image/x-icon" href="/favicon.ico">
-    <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Roboto:regular,medium,thin,italic,mediumitalic">
-    <link rel="stylesheet" href="../static/yui-3.3.0-reset-min.css">
-    <link rel="stylesheet" href="../static/default.css">
-
-  </head>
-  <body>
-
-    <div id="page-container">
-
-      <div id="page-header"><a href="../index.html">Android Design</a></div>
-
-      <div id="main-row">
-
-        <ul id="nav">
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../index.html">Get Started</a></div>
-            <ul>
-              <li><a href="../get-started/creative-vision.html">Creative Vision</a></li>
-              <li><a href="../get-started/principles.html">Design Principles</a></li>
-              <li><a href="../get-started/ui-overview.html">UI Overview</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../style/index.html">Style</a></div>
-            <ul>
-              <li><a href="../style/devices-displays.html">Devices and Displays</a></li>
-              <li><a href="../style/themes.html">Themes</a></li>
-              <li><a href="../style/touch-feedback.html">Touch Feedback</a></li>
-              <li><a href="../style/metrics-grids.html">Metrics and Grids</a></li>
-              <li><a href="../style/typography.html">Typography</a></li>
-              <li><a href="../style/color.html">Color</a></li>
-              <li><a href="../style/iconography.html">Iconography</a></li>
-              <li><a href="../style/writing.html">Writing Style</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../patterns/index.html">Patterns</a></div>
-            <ul>
-              <li><a href="../patterns/new-4-0.html">New in Android 4.0</a></li>
-              <li><a href="../patterns/gestures.html">Gestures</a></li>
-              <li><a href="../patterns/app-structure.html">App Structure</a></li>
-              <li><a href="../patterns/navigation.html">Navigation</a></li>
-              <li><a href="../patterns/actionbar.html">Action Bar</a></li>
-              <li><a href="../patterns/multi-pane-layouts.html">Multi-pane Layouts</a></li>
-              <li><a href="../patterns/swipe-views.html">Swipe Views</a></li>
-              <li><a href="../patterns/selection.html">Selection</a></li>
-              <li><a href="../patterns/notifications.html">Notifications</a></li>
-              <li><a href="../patterns/compatibility.html">Compatibility</a></li>
-              <li><a href="../patterns/pure-android.html">Pure Android</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../building-blocks/index.html">Building Blocks</a></div>
-            <ul>
-              <li><a href="../building-blocks/tabs.html">Tabs</a></li>
-              <li><a href="../building-blocks/lists.html">Lists</a></li>
-              <li><a href="../building-blocks/grid-lists.html">Grid Lists</a></li>
-              <li><a href="../building-blocks/scrolling.html">Scrolling</a></li>
-              <li><a href="../building-blocks/spinners.html">Spinners</a></li>
-              <li><a href="../building-blocks/buttons.html">Buttons</a></li>
-              <li><a href="../building-blocks/text-fields.html">Text Fields</a></li>
-              <li><a href="../building-blocks/seek-bars.html">Seek Bars</a></li>
-              <li><a href="../building-blocks/progress.html">Progress &amp; Activity</a></li>
-              <li><a href="../building-blocks/switches.html">Switches</a></li>
-              <li><a href="../building-blocks/dialogs.html">Dialogs</a></li>
-              <li><a href="../building-blocks/pickers.html">Pickers</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header empty"><a href="../downloads/index.html">Downloads</a></div>
-          </li>
-
-          <li>
-            <div id="back-dac-section"><a href="../../index.html">Developers</a></div>
-          </li>
-
-        </ul>
-
-        <div id="content">
-
-          
-          <div class="layout-content-row content-header">
-            <div class="layout-content-col span-9">
-              <h2>Themes</h2>
-            </div>
-            <div class="paging-links layout-content-col span-4">
-              <a href="#" class="prev-page-link">Previous</a>
-              <a href="#" class="next-page-link">Next</a>
-            </div>
-          </div>
-          
-
-          
-
-<div class="layout-content-row">
-  <div class="layout-content-col span-5">
-
-    <img src="../static/content/themes_holo_light.png">
-    <div class="figure-caption">
-      Gmail in Holo Light.
-    </div>
-
-    <img src="../static/content/themes_holo_dark.png">
-    <div class="figure-caption">
-      Settings in Holo Dark.
-    </div>
-
-    <img src="../static/content/themes_holo_inverse.png">
-    <div class="figure-caption">
-      Talk in Holo Light with dark action bar.
-    </div>
-
-  </div>
-  <div class="layout-content-col span-7">
-
-<p>Themes are Android's mechanism for applying a consistent style to an app or activity. The style
-specifies the visual properties of the elements that make up your user interface, such as color,
-height, padding and font size. To promote greater cohesion between all apps on the platform, Android
-provides three system themes that you can choose from when building apps for Ice Cream Sandwich:</p>
-<ul>
-<li>Holo Light</li>
-<li>Holo Dark</li>
-<li>Holo Light with dark action bars</li>
-</ul>
-<p>Applying these themes will go a long way in helping you to build apps that fit right into the
-general visual language of Android.</p>
-<p>Pick the system theme that best matches the needs and design aesthetics for your app. If your
-desire is to have a more distinct look for your app, using one of the system themes as a starting
-point for your customizations is a good idea. The system themes provide a solid foundation on top
-of which you can selectively implement your own visual stylings.</p>
-
-  </div>
-</div>
-
-
-
-          
-          <div class="layout-content-row content-footer">
-            <div class="paging-links layout-content-col span-9">&nbsp;</div>
-            <div class="paging-links layout-content-col span-4">
-              <a href="#" class="prev-page-link">Previous</a>
-              <a href="#" class="next-page-link">Next</a>
-            </div>
-          </div>
-          
-        </div>
-
-      </div>
-
-      <div id="page-footer">
-
-        <p id="copyright">
-          Except as noted, this content is licensed under
-          <a href="http://creativecommons.org/licenses/by/2.5/">
-          Creative Commons Attribution 2.5</a>.<br>
-          For details and restrictions, see the
-          <a href="http://developer.android.com/license.html">Content License</a>.
-        </p>
-
-        <p>
-          <a href="http://www.android.com/terms.html">Site Terms of Service</a> &ndash;
-          <a href="http://www.android.com/privacy.html">Privacy Policy</a> &ndash;
-          <a href="http://www.android.com/branding.html">Brand Guidelines</a>
-        </p>
-
-      </div>
-    </div>
-
-    <script src="../static/jquery-1.6.2.min.js"></script>
-    <script>
-    var SITE_ROOT = '../';
-    </script>
-    <script src="../static/default.js"></script>
-
-
-    <script type="text/javascript">
-    var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
-    document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
-    </script>
-    <script type="text/javascript">
-    var pageTracker = _gat._getTracker("UA-5831155-1");
-    pageTracker._trackPageview();
-    </script>
-  </body>
-</html>
diff --git a/docs/html/design/style/themes.jd b/docs/html/design/style/themes.jd
new file mode 100644
index 0000000..d4a6acf
--- /dev/null
+++ b/docs/html/design/style/themes.jd
@@ -0,0 +1,42 @@
+page.title=Themes
+@jd:body
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-5">
+
+    <img src="{@docRoot}design/media/themes_holo_light.png">
+    <div class="figure-caption">
+      Gmail in Holo Light.
+    </div>
+
+    <img src="{@docRoot}design/media/themes_holo_dark.png">
+    <div class="figure-caption">
+      Settings in Holo Dark.
+    </div>
+
+    <img src="{@docRoot}design/media/themes_holo_inverse.png">
+    <div class="figure-caption">
+      Talk in Holo Light with dark action bar.
+    </div>
+
+  </div>
+  <div class="layout-content-col span-7">
+
+<p>Themes are Android's mechanism for applying a consistent style to an app or activity. The style
+specifies the visual properties of the elements that make up your user interface, such as color,
+height, padding and font size. To promote greater cohesion between all apps on the platform, Android
+provides three system themes that you can choose from when building apps for Ice Cream Sandwich:</p>
+<ul>
+<li>Holo Light</li>
+<li>Holo Dark</li>
+<li>Holo Light with dark action bars</li>
+</ul>
+<p>Applying these themes will go a long way in helping you to build apps that fit right into the
+general visual language of Android.</p>
+<p>Pick the system theme that best matches the needs and design aesthetics for your app. If your
+desire is to have a more distinct look for your app, using one of the system themes as a starting
+point for your customizations is a good idea. The system themes provide a solid foundation on top
+of which you can selectively implement your own visual stylings.</p>
+
+  </div>
+</div>
diff --git a/docs/html/design/style/touch-feedback.html b/docs/html/design/style/touch-feedback.html
deleted file mode 100644
index d1c08f8..0000000
--- a/docs/html/design/style/touch-feedback.html
+++ /dev/null
@@ -1,224 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-  <head>
-    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
-    <title>
-
-Android Design - Touch Feedback
-    </title>
-    <link rel="shortcut icon" type="image/x-icon" href="/favicon.ico">
-    <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Roboto:regular,medium,thin,italic,mediumitalic">
-    <link rel="stylesheet" href="../static/yui-3.3.0-reset-min.css">
-    <link rel="stylesheet" href="../static/default.css">
-
-  </head>
-  <body>
-
-    <div id="page-container">
-
-      <div id="page-header"><a href="../index.html">Android Design</a></div>
-
-      <div id="main-row">
-
-        <ul id="nav">
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../index.html">Get Started</a></div>
-            <ul>
-              <li><a href="../get-started/creative-vision.html">Creative Vision</a></li>
-              <li><a href="../get-started/principles.html">Design Principles</a></li>
-              <li><a href="../get-started/ui-overview.html">UI Overview</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../style/index.html">Style</a></div>
-            <ul>
-              <li><a href="../style/devices-displays.html">Devices and Displays</a></li>
-              <li><a href="../style/themes.html">Themes</a></li>
-              <li><a href="../style/touch-feedback.html">Touch Feedback</a></li>
-              <li><a href="../style/metrics-grids.html">Metrics and Grids</a></li>
-              <li><a href="../style/typography.html">Typography</a></li>
-              <li><a href="../style/color.html">Color</a></li>
-              <li><a href="../style/iconography.html">Iconography</a></li>
-              <li><a href="../style/writing.html">Writing Style</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../patterns/index.html">Patterns</a></div>
-            <ul>
-              <li><a href="../patterns/new-4-0.html">New in Android 4.0</a></li>
-              <li><a href="../patterns/gestures.html">Gestures</a></li>
-              <li><a href="../patterns/app-structure.html">App Structure</a></li>
-              <li><a href="../patterns/navigation.html">Navigation</a></li>
-              <li><a href="../patterns/actionbar.html">Action Bar</a></li>
-              <li><a href="../patterns/multi-pane-layouts.html">Multi-pane Layouts</a></li>
-              <li><a href="../patterns/swipe-views.html">Swipe Views</a></li>
-              <li><a href="../patterns/selection.html">Selection</a></li>
-              <li><a href="../patterns/notifications.html">Notifications</a></li>
-              <li><a href="../patterns/compatibility.html">Compatibility</a></li>
-              <li><a href="../patterns/pure-android.html">Pure Android</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../building-blocks/index.html">Building Blocks</a></div>
-            <ul>
-              <li><a href="../building-blocks/tabs.html">Tabs</a></li>
-              <li><a href="../building-blocks/lists.html">Lists</a></li>
-              <li><a href="../building-blocks/grid-lists.html">Grid Lists</a></li>
-              <li><a href="../building-blocks/scrolling.html">Scrolling</a></li>
-              <li><a href="../building-blocks/spinners.html">Spinners</a></li>
-              <li><a href="../building-blocks/buttons.html">Buttons</a></li>
-              <li><a href="../building-blocks/text-fields.html">Text Fields</a></li>
-              <li><a href="../building-blocks/seek-bars.html">Seek Bars</a></li>
-              <li><a href="../building-blocks/progress.html">Progress &amp; Activity</a></li>
-              <li><a href="../building-blocks/switches.html">Switches</a></li>
-              <li><a href="../building-blocks/dialogs.html">Dialogs</a></li>
-              <li><a href="../building-blocks/pickers.html">Pickers</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header empty"><a href="../downloads/index.html">Downloads</a></div>
-          </li>
-
-          <li>
-            <div id="back-dac-section"><a href="../../index.html">Developers</a></div>
-          </li>
-
-        </ul>
-
-        <div id="content">
-
-          
-          <div class="layout-content-row content-header">
-            <div class="layout-content-col span-9">
-              <h2>Touch Feedback</h2>
-            </div>
-            <div class="paging-links layout-content-col span-4">
-              <a href="#" class="prev-page-link">Previous</a>
-              <a href="#" class="next-page-link">Next</a>
-            </div>
-          </div>
-          
-
-          
-
-<div class="layout-content-row" style="margin-bottom: -100px">
-  <div class="layout-content-col span-7">
-
-<p>Use color and illumination to respond to touches, reinforce the resulting behaviors of gestures, and
-indicate what actions are enabled and disabled.</p>
-<p>Whenever a user touches an actionable area in your app, provide a visual response. This lets the
-user know which object was touched and that your app is "listening".</p>
-
-  </div>
-  <div class="layout-content-col span-6">
-
-    <img src="../static/content/touch_feedback_reaction_response.png">
-
-  </div>
-</div>
-
-<h4>States</h4>
-
-<div class="vspace size-1">&nbsp;</div>
-
-<img src="../static/content/touch_feedback_states.png">
-<div class="figure-caption">
-  Most of Android's UI elements have touch-feedback built in, including states that indicate
-  whether touching the element will have any effect.
-</div>
-
-<div class="vspace size-4">&nbsp;</div>
-
-<div class="layout-content-row">
-  <div class="layout-content-col span-4">
-
-<h4>Communication</h4>
-<p>When your objects react to more complex gestures, help users understand what the outcome of the
-operation will be. For example, in Recents, when you start swiping a thumbnail left or right, it
-starts to dim. This helps the user understand that swiping will cause the item to be removed.</p>
-
-  </div>
-  <div class="layout-content-col span-9">
-
-    <img src="../static/content/touch_feedback_manipulation.png">
-
-  </div>
-</div>
-
-<div class="layout-content-row">
-  <div class="layout-content-col span-6">
-
-    <img src="../static/content/touch_feedback_communication.png">
-
-  </div>
-  <div class="layout-content-col span-6">
-
-<div class="vspace size-3">&nbsp;</div>
-
-<h4>Boundaries</h4>
-<p>When users try to scroll past the upper or lower limit of a scrollable area, communicate the
-boundary with a visual cue. For example, if a user attempts to scroll past the first home screen
-panel, the screen content tilts to the right to indicate that further navigation in this direction
-is not possible. Many of Android's scrollable UI widgets (e.g. lists or grid lists) already have
-support for boundary feedback built in. If you are building custom, keep boundary feedback in mind
-and provide it from within your app.</p>
-
-  </div>
-</div>
-
-
-
-          
-          <div class="layout-content-row content-footer">
-            <div class="paging-links layout-content-col span-9">&nbsp;</div>
-            <div class="paging-links layout-content-col span-4">
-              <a href="#" class="prev-page-link">Previous</a>
-              <a href="#" class="next-page-link">Next</a>
-            </div>
-          </div>
-          
-        </div>
-
-      </div>
-
-      <div id="page-footer">
-
-        <p id="copyright">
-          Except as noted, this content is licensed under
-          <a href="http://creativecommons.org/licenses/by/2.5/">
-          Creative Commons Attribution 2.5</a>.<br>
-          For details and restrictions, see the
-          <a href="http://developer.android.com/license.html">Content License</a>.
-        </p>
-
-        <p>
-          <a href="http://www.android.com/terms.html">Site Terms of Service</a> &ndash;
-          <a href="http://www.android.com/privacy.html">Privacy Policy</a> &ndash;
-          <a href="http://www.android.com/branding.html">Brand Guidelines</a>
-        </p>
-
-      </div>
-    </div>
-
-    <script src="../static/jquery-1.6.2.min.js"></script>
-    <script>
-    var SITE_ROOT = '../';
-    </script>
-    <script src="../static/default.js"></script>
-
-
-    <script type="text/javascript">
-    var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
-    document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
-    </script>
-    <script type="text/javascript">
-    var pageTracker = _gat._getTracker("UA-5831155-1");
-    pageTracker._trackPageview();
-    </script>
-  </body>
-</html>
diff --git a/docs/html/design/style/touch-feedback.jd b/docs/html/design/style/touch-feedback.jd
new file mode 100644
index 0000000..5fe72a7
--- /dev/null
+++ b/docs/html/design/style/touch-feedback.jd
@@ -0,0 +1,67 @@
+page.title=Touch Feedback
+@jd:body
+
+<div class="layout-content-row" style="margin-bottom: -100px">
+  <div class="layout-content-col span-7">
+
+<p>Use color and illumination to respond to touches, reinforce the resulting behaviors of gestures, and
+indicate what actions are enabled and disabled.</p>
+<p>Whenever a user touches an actionable area in your app, provide a visual response. This lets the
+user know which object was touched and that your app is "listening".</p>
+
+  </div>
+  <div class="layout-content-col span-6">
+
+    <img src="{@docRoot}design/media/touch_feedback_reaction_response.png">
+
+  </div>
+</div>
+
+<h4>States</h4>
+
+<div class="vspace size-1">&nbsp;</div>
+
+<img src="{@docRoot}design/media/touch_feedback_states.png">
+<div class="figure-caption">
+  Most of Android's UI elements have touch-feedback built in, including states that indicate
+  whether touching the element will have any effect.
+</div>
+
+<div class="vspace size-4">&nbsp;</div>
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-4">
+
+<h4>Communication</h4>
+<p>When your objects react to more complex gestures, help users understand what the outcome of the
+operation will be. For example, in Recents, when you start swiping a thumbnail left or right, it
+starts to dim. This helps the user understand that swiping will cause the item to be removed.</p>
+
+  </div>
+  <div class="layout-content-col span-9">
+
+    <img src="{@docRoot}design/media/touch_feedback_manipulation.png">
+
+  </div>
+</div>
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-6">
+
+    <img src="{@docRoot}design/media/touch_feedback_communication.png">
+
+  </div>
+  <div class="layout-content-col span-6">
+
+<div class="vspace size-3">&nbsp;</div>
+
+<h4>Boundaries</h4>
+<p>When users try to scroll past the upper or lower limit of a scrollable area, communicate the
+boundary with a visual cue. For example, if a user attempts to scroll past the first home screen
+panel, the screen content tilts to the right to indicate that further navigation in this direction
+is not possible. Many of Android's scrollable UI widgets (e.g. lists or grid lists) already have
+support for boundary feedback built in. If you are building custom, keep boundary feedback in mind
+and provide it from within your app.</p>
+
+  </div>
+</div>
diff --git a/docs/html/design/style/typography.html b/docs/html/design/style/typography.html
deleted file mode 100644
index d9b6d4b..0000000
--- a/docs/html/design/style/typography.html
+++ /dev/null
@@ -1,214 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-  <head>
-    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
-    <title>
-
-Android Design - Typography
-    </title>
-    <link rel="shortcut icon" type="image/x-icon" href="/favicon.ico">
-    <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Roboto:regular,medium,thin,italic,mediumitalic">
-    <link rel="stylesheet" href="../static/yui-3.3.0-reset-min.css">
-    <link rel="stylesheet" href="../static/default.css">
-
-  </head>
-  <body>
-
-    <div id="page-container">
-
-      <div id="page-header"><a href="../index.html">Android Design</a></div>
-
-      <div id="main-row">
-
-        <ul id="nav">
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../index.html">Get Started</a></div>
-            <ul>
-              <li><a href="../get-started/creative-vision.html">Creative Vision</a></li>
-              <li><a href="../get-started/principles.html">Design Principles</a></li>
-              <li><a href="../get-started/ui-overview.html">UI Overview</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../style/index.html">Style</a></div>
-            <ul>
-              <li><a href="../style/devices-displays.html">Devices and Displays</a></li>
-              <li><a href="../style/themes.html">Themes</a></li>
-              <li><a href="../style/touch-feedback.html">Touch Feedback</a></li>
-              <li><a href="../style/metrics-grids.html">Metrics and Grids</a></li>
-              <li><a href="../style/typography.html">Typography</a></li>
-              <li><a href="../style/color.html">Color</a></li>
-              <li><a href="../style/iconography.html">Iconography</a></li>
-              <li><a href="../style/writing.html">Writing Style</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../patterns/index.html">Patterns</a></div>
-            <ul>
-              <li><a href="../patterns/new-4-0.html">New in Android 4.0</a></li>
-              <li><a href="../patterns/gestures.html">Gestures</a></li>
-              <li><a href="../patterns/app-structure.html">App Structure</a></li>
-              <li><a href="../patterns/navigation.html">Navigation</a></li>
-              <li><a href="../patterns/actionbar.html">Action Bar</a></li>
-              <li><a href="../patterns/multi-pane-layouts.html">Multi-pane Layouts</a></li>
-              <li><a href="../patterns/swipe-views.html">Swipe Views</a></li>
-              <li><a href="../patterns/selection.html">Selection</a></li>
-              <li><a href="../patterns/notifications.html">Notifications</a></li>
-              <li><a href="../patterns/compatibility.html">Compatibility</a></li>
-              <li><a href="../patterns/pure-android.html">Pure Android</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../building-blocks/index.html">Building Blocks</a></div>
-            <ul>
-              <li><a href="../building-blocks/tabs.html">Tabs</a></li>
-              <li><a href="../building-blocks/lists.html">Lists</a></li>
-              <li><a href="../building-blocks/grid-lists.html">Grid Lists</a></li>
-              <li><a href="../building-blocks/scrolling.html">Scrolling</a></li>
-              <li><a href="../building-blocks/spinners.html">Spinners</a></li>
-              <li><a href="../building-blocks/buttons.html">Buttons</a></li>
-              <li><a href="../building-blocks/text-fields.html">Text Fields</a></li>
-              <li><a href="../building-blocks/seek-bars.html">Seek Bars</a></li>
-              <li><a href="../building-blocks/progress.html">Progress &amp; Activity</a></li>
-              <li><a href="../building-blocks/switches.html">Switches</a></li>
-              <li><a href="../building-blocks/dialogs.html">Dialogs</a></li>
-              <li><a href="../building-blocks/pickers.html">Pickers</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header empty"><a href="../downloads/index.html">Downloads</a></div>
-          </li>
-
-          <li>
-            <div id="back-dac-section"><a href="../../index.html">Developers</a></div>
-          </li>
-
-        </ul>
-
-        <div id="content">
-
-          
-          <div class="layout-content-row content-header">
-            <div class="layout-content-col span-9">
-              <h2>Typography</h2>
-            </div>
-            <div class="paging-links layout-content-col span-4">
-              <a href="#" class="prev-page-link">Previous</a>
-              <a href="#" class="next-page-link">Next</a>
-            </div>
-          </div>
-          
-
-          
-
-<div class="layout-content-row">
-  <div class="layout-content-col span-8">
-
-    <img src="../static/content/typography_main.png">
-
-  </div>
-  <div class="layout-content-col span-5">
-
-<p>The Android design language relies on traditional typographic tools such as scale, space, rhythm,
-and alignment with an underlying grid. Successful deployment of these tools is essential to help
-users quickly understand a screen of information. To support such use of typography, Ice Cream
-Sandwich introduced a new type family named Roboto, created specifically for the requirements of UI
-and high-resolution screens. The current TextView framework supports regular, bold, italic, and bold
-italic weights by default.</p>
-
-    <img src="../static/content/typography_alphas.png">
-
-<p><a href="https://dl-ssl.google.com/android/design/Roboto_Hinted_20111129.zip">Download Roboto</a></p>
-<p><a href="https://dl-ssl.google.com/android/design/Roboto_Specimen_Book_20111129.pdf">Specimen Book</a></p>
-
-  </div>
-</div>
-
-<hr>
-
-<div class="layout-content-row">
-  <div class="layout-content-col span-6">
-
-<h4>Default type colors</h4>
-<p>The Android UI uses the following default color styles: <code>textColorPrimary</code> and
-<code>textColorSecondary</code>. For light themes use <code>textColorPrimaryInverse</code> and
-<code>textColorSecondaryInverse</code>. The framework text color styles also support variants for
-touch feedback states when used inside UI elements.</p>
-
-    <img src="../static/content/typography_defaults.png">
-
-  </div>
-  <div class="layout-content-col span-6">
-
-<h4>Typographic Scale</h4>
-<p>Contrast in type sizes can go a long way to create ordered, understandable layouts. However, too
-many different sizes in the same UI can be messy. The Android framework uses the following limited
-set of type sizes:</p>
-
-<img src="../static/content/typography_sizes.png">
-
-<p>Users can select a system-wide scaling factor for text in the Settings app. In order to support
-these accessibility features, type should be specified in scale-independent pixels
-(<acronym title="Scale-independent pixels. One sp is one pixel on a 160 dpi screen if the user's global text scale is set to 100%.">sp</acronym>)
-wherever possible. Layouts supporting scalable types should be tested against these settings.</p>
-
-  </div>
-</div>
-
-
-
-
-          
-          <div class="layout-content-row content-footer">
-            <div class="paging-links layout-content-col span-9">&nbsp;</div>
-            <div class="paging-links layout-content-col span-4">
-              <a href="#" class="prev-page-link">Previous</a>
-              <a href="#" class="next-page-link">Next</a>
-            </div>
-          </div>
-          
-        </div>
-
-      </div>
-
-      <div id="page-footer">
-
-        <p id="copyright">
-          Except as noted, this content is licensed under
-          <a href="http://creativecommons.org/licenses/by/2.5/">
-          Creative Commons Attribution 2.5</a>.<br>
-          For details and restrictions, see the
-          <a href="http://developer.android.com/license.html">Content License</a>.
-        </p>
-
-        <p>
-          <a href="http://www.android.com/terms.html">Site Terms of Service</a> &ndash;
-          <a href="http://www.android.com/privacy.html">Privacy Policy</a> &ndash;
-          <a href="http://www.android.com/branding.html">Brand Guidelines</a>
-        </p>
-
-      </div>
-    </div>
-
-    <script src="../static/jquery-1.6.2.min.js"></script>
-    <script>
-    var SITE_ROOT = '../';
-    </script>
-    <script src="../static/default.js"></script>
-
-
-    <script type="text/javascript">
-    var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
-    document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
-    </script>
-    <script type="text/javascript">
-    var pageTracker = _gat._getTracker("UA-5831155-1");
-    pageTracker._trackPageview();
-    </script>
-  </body>
-</html>
diff --git a/docs/html/design/style/typography.jd b/docs/html/design/style/typography.jd
new file mode 100644
index 0000000..db2fb5f
--- /dev/null
+++ b/docs/html/design/style/typography.jd
@@ -0,0 +1,56 @@
+page.title=Typography
+@jd:body
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-8">
+
+    <img src="{@docRoot}design/media/typography_main.png">
+
+  </div>
+  <div class="layout-content-col span-5">
+
+<p>The Android design language relies on traditional typographic tools such as scale, space, rhythm,
+and alignment with an underlying grid. Successful deployment of these tools is essential to help
+users quickly understand a screen of information. To support such use of typography, Ice Cream
+Sandwich introduced a new type family named Roboto, created specifically for the requirements of UI
+and high-resolution screens. The current TextView framework supports regular, bold, italic, and bold
+italic weights by default.</p>
+
+    <img src="{@docRoot}design/media/typography_alphas.png">
+
+<p><a href="https://dl-ssl.google.com/android/design/Roboto_Hinted_20111129.zip">Download Roboto</a></p>
+<p><a href="https://dl-ssl.google.com/android/design/Roboto_Specimen_Book_20111129.pdf">Specimen Book</a></p>
+
+  </div>
+</div>
+
+<hr>
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-6">
+
+<h4>Default type colors</h4>
+<p>The Android UI uses the following default color styles: <code>textColorPrimary</code> and
+<code>textColorSecondary</code>. For light themes use <code>textColorPrimaryInverse</code> and
+<code>textColorSecondaryInverse</code>. The framework text color styles also support variants for
+touch feedback states when used inside UI elements.</p>
+
+    <img src="{@docRoot}design/media/typography_defaults.png">
+
+  </div>
+  <div class="layout-content-col span-6">
+
+<h4>Typographic Scale</h4>
+<p>Contrast in type sizes can go a long way to create ordered, understandable layouts. However, too
+many different sizes in the same UI can be messy. The Android framework uses the following limited
+set of type sizes:</p>
+
+<img src="{@docRoot}design/media/typography_sizes.png">
+
+<p>Users can select a system-wide scaling factor for text in the Settings app. In order to support
+these accessibility features, type should be specified in scale-independent pixels
+(<acronym title="Scale-independent pixels. One sp is one pixel on a 160 dpi screen if the user's global text scale is set to 100%.">sp</acronym>)
+wherever possible. Layouts supporting scalable types should be tested against these settings.</p>
+
+  </div>
+</div>
diff --git a/docs/html/design/style/writing.html b/docs/html/design/style/writing.html
deleted file mode 100644
index 146ce88..0000000
--- a/docs/html/design/style/writing.html
+++ /dev/null
@@ -1,487 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-  <head>
-    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
-    <title>
-
-Android Design - Writing Style
-    </title>
-    <link rel="shortcut icon" type="image/x-icon" href="/favicon.ico">
-    <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Roboto:regular,medium,thin,italic,mediumitalic">
-    <link rel="stylesheet" href="../static/yui-3.3.0-reset-min.css">
-    <link rel="stylesheet" href="../static/default.css">
-
-<style>
-
-/* UI tables */
-
-.ui_table {
-  width: 100%;
-  background: #282828;
-  color: #fff;
-  border-radius: 2px;
-  box-shadow: 0 2px 4px rgba(0,0,0,0.25);
-  border-collapse: separate;
-}
-
-.ui_table th,
-.ui_table td {
-  padding: 5px 10px;
-}
-
-.ui_table thead th {
-  font-weight: 600;
-}
-
-.ui_table tfoot td {
-  border-top: 1px solid #494949;
-  border-right: 1px solid #494949;
-  text-align: center;
-}
-
-.ui_table tfoot td:last-child {
-  border-right: 0;
-}
-
-.list_item_margins {
-  margin-left: 30px !important;
-}
-
-.example_label {
-  margin-bottom: 10px;
-  padding-left: 20px;
-  background: transparent none no-repeat scroll 0px 3px;
-}
-
-.example_label.bad {
-  background-image: url(../static/ico_wrong.png);
-}
-
-.example_label.good {
-  background-image: url(../static/ico_good.png);
-}
-
-</style>
-
-  </head>
-  <body>
-
-    <div id="page-container">
-
-      <div id="page-header"><a href="../index.html">Android Design</a></div>
-
-      <div id="main-row">
-
-        <ul id="nav">
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../index.html">Get Started</a></div>
-            <ul>
-              <li><a href="../get-started/creative-vision.html">Creative Vision</a></li>
-              <li><a href="../get-started/principles.html">Design Principles</a></li>
-              <li><a href="../get-started/ui-overview.html">UI Overview</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../style/index.html">Style</a></div>
-            <ul>
-              <li><a href="../style/devices-displays.html">Devices and Displays</a></li>
-              <li><a href="../style/themes.html">Themes</a></li>
-              <li><a href="../style/touch-feedback.html">Touch Feedback</a></li>
-              <li><a href="../style/metrics-grids.html">Metrics and Grids</a></li>
-              <li><a href="../style/typography.html">Typography</a></li>
-              <li><a href="../style/color.html">Color</a></li>
-              <li><a href="../style/iconography.html">Iconography</a></li>
-              <li><a href="../style/writing.html">Writing Style</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../patterns/index.html">Patterns</a></div>
-            <ul>
-              <li><a href="../patterns/new-4-0.html">New in Android 4.0</a></li>
-              <li><a href="../patterns/gestures.html">Gestures</a></li>
-              <li><a href="../patterns/app-structure.html">App Structure</a></li>
-              <li><a href="../patterns/navigation.html">Navigation</a></li>
-              <li><a href="../patterns/actionbar.html">Action Bar</a></li>
-              <li><a href="../patterns/multi-pane-layouts.html">Multi-pane Layouts</a></li>
-              <li><a href="../patterns/swipe-views.html">Swipe Views</a></li>
-              <li><a href="../patterns/selection.html">Selection</a></li>
-              <li><a href="../patterns/notifications.html">Notifications</a></li>
-              <li><a href="../patterns/compatibility.html">Compatibility</a></li>
-              <li><a href="../patterns/pure-android.html">Pure Android</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header"><a href="../building-blocks/index.html">Building Blocks</a></div>
-            <ul>
-              <li><a href="../building-blocks/tabs.html">Tabs</a></li>
-              <li><a href="../building-blocks/lists.html">Lists</a></li>
-              <li><a href="../building-blocks/grid-lists.html">Grid Lists</a></li>
-              <li><a href="../building-blocks/scrolling.html">Scrolling</a></li>
-              <li><a href="../building-blocks/spinners.html">Spinners</a></li>
-              <li><a href="../building-blocks/buttons.html">Buttons</a></li>
-              <li><a href="../building-blocks/text-fields.html">Text Fields</a></li>
-              <li><a href="../building-blocks/seek-bars.html">Seek Bars</a></li>
-              <li><a href="../building-blocks/progress.html">Progress &amp; Activity</a></li>
-              <li><a href="../building-blocks/switches.html">Switches</a></li>
-              <li><a href="../building-blocks/dialogs.html">Dialogs</a></li>
-              <li><a href="../building-blocks/pickers.html">Pickers</a></li>
-            </ul>
-          </li>
-
-          <li class="nav-section">
-            <div class="nav-section-header empty"><a href="../downloads/index.html">Downloads</a></div>
-          </li>
-
-          <li>
-            <div id="back-dac-section"><a href="../../index.html">Developers</a></div>
-          </li>
-
-        </ul>
-
-        <div id="content">
-
-          
-          <div class="layout-content-row content-header">
-            <div class="layout-content-col span-9">
-              <h2>Writing Style</h2>
-            </div>
-            <div class="paging-links layout-content-col span-4">
-              <a href="#" class="prev-page-link">Previous</a>
-              <a href="#" class="next-page-link">Next</a>
-            </div>
-          </div>
-          
-
-          
-
-<p>When choosing words for your app:</p>
-<ol>
-<li>
-<p><strong>Keep it brief.</strong> Be concise, simple and precise. Start with a 30 character limit (including
-   spaces), and don't use more unless absolutely necessary.</p>
-</li>
-<li>
-<p><strong>Keep it simple.</strong> Pretend you're speaking to someone who's smart and competent, but doesn't
-   know technical jargon and may not speak English very well. Use short words, active verbs, and
-   common nouns.</p>
-</li>
-<li>
-<p><strong>Be friendly.</strong> Use contractions. Talk directly to the reader using second person ("you"). If
-   your text doesn't read the way you'd say it in casual conversation, it's probably not the way
-   you should write it. Don't be abrupt or annoying and make the user feel safe, happy and
-   energized.</p>
-</li>
-<li>
-<p><strong>Put the most important thing first.</strong> The first two words (around 11 characters, including
-   spaces) should include at least a taste of the most important information in the string. If they
-   don't, start over.</p>
-</li>
-<li>
-<p><strong>Describe only what's necessary, and no more.</strong> Don't try to explain subtle differences. They
-   will be lost on most users.</p>
-</li>
-<li>
-<p><strong>Avoid repetition.</strong> If a significant term gets repeated within a screen or block of text, find
-   a way to use it just once.</p>
-</li>
-</ol>
-
-<h2 id="examples">Examples</h2>
-
-<ol><li class="value-1"><strong>Keep it brief.</strong> From the setup wizard:</ol>
-
-<div class="layout-content-row">
-  <div class="layout-content-col span-6 list_item_margins">
-
-    <div class="example_label bad">Too formal</div>
-
-    <table class="ui_table good"><tbody><tr><td>
-    Consult the documentation that came with your phone for further instructions.
-    </td></tr></tbody></table>
-
-  </div>
-  <div class="layout-content-col span-6">
-
-    <div class="example_label good">Better</div>
-
-    <table class="ui_table good"><tbody><tr><td>
-    Read the instructions that came with your phone.
-    </td></tr></tbody></table>
-
-  </div>
-</div>
-
-<div class="vspace size-1">&nbsp;</div>
-
-<ol><li class="value-2"><strong>Keep it simple.</strong> From the Location settings screen:</ol>
-
-<div class="layout-content-row">
-  <div class="layout-content-col span-6 list_item_margins">
-
-    <div class="example_label bad">Confusing</div>
-
-    <table class="ui_table bad">
-    <thead>
-      <tr>
-        <th>
-        Use GPS satellites
-        </th>
-      </tr>
-    </thead>
-    <tbody>
-      <tr>
-        <td>
-        When locating, accurate to street level.
-        </td>
-      </tr>
-    </tbody>
-    </table>
-
-  </div>
-  <div class="layout-content-col span-6">
-
-    <div class="example_label good">Better</div>
-
-    <table class="ui_table good">
-    <thead>
-      <tr>
-        <th>
-        GPS
-        </th>
-      </tr>
-    </thead>
-    <tbody>
-      <tr>
-        <td>
-        Let apps use satellites to pinpoint your location.
-        </td>
-      </tr>
-    </tbody>
-    </table>
-
-  </div>
-</div>
-
-<div class="vspace size-1">&nbsp;</div>
-
-<ol><li class="value-3"><strong>Be friendly.</strong> Dialog that appears when an application
-crashes:</ol>
-
-<div class="layout-content-row">
-  <div class="layout-content-col span-6 list_item_margins">
-
-    <div class="example_label bad">Confusing and annoying&mdash;"Sorry" just rubs salt in the
-    wound.</div>
-
-    <table class="ui_table bad">
-    <thead>
-      <tr>
-        <th colspan="3">
-        Sorry!
-        </th>
-      </tr>
-    </thead>
-    <tbody>
-      <tr>
-        <td colspan="3">
-        Activity MyAppActivity (in application MyApp)
-        is not responding.
-        </td>
-      </tr>
-    </tbody>
-    <tfoot>
-      <tr>
-        <td width="33%">Force close</td>
-        <td width="33%">Wait</td>
-        <td width="33%">Report</td>
-      </tr>
-    </tbody>
-    </table>
-
-  </div>
-  <div class="layout-content-col span-6">
-
-    <div class="example_label good">Shorter, more direct, no faux-apologetic title:<br><br></div>
-
-    <table class="ui_table good">
-    <thead>
-      <tr>
-        <th colspan="3">
-        MyApp isn't responding.
-        </th>
-      </tr>
-    </thead>
-    <tbody>
-      <tr>
-        <td colspan="3">
-        Do you want to close it?
-        </td>
-      </tr>
-    </tbody>
-    <tfoot>
-      <tr>
-        <td width="33%">Wait</td>
-        <td width="33%">Report</td>
-        <td width="33%">Close</td>
-      </tr>
-    </tbody>
-    </table>
-
-  </div>
-</div>
-
-<div class="vspace size-1">&nbsp;</div>
-
-<ol><li class="value-4"><strong>Put the most important thing first.</strong></ol>
-
-<div class="layout-content-row">
-  <div class="layout-content-col span-6 list_item_margins">
-
-    <div class="example_label bad">Top news last</div>
-
-    <table class="ui_table bad"><tbody><tr><td>
-    77 other people +1'd this, including Larry Page.
-    </td></tr></tbody></table>
-
-  </div>
-  <div class="layout-content-col span-6">
-
-    <div class="example_label good">Top news first</div>
-
-    <table class="ui_table good"><tbody><tr><td>
-    Larry Page and 77 others +1'd this.
-    </td></tr></tbody></table>
-
-  </div>
-</div>
-
-<div class="layout-content-row">
-  <div class="layout-content-col span-6 list_item_margins">
-
-    <div class="example_label bad">Task last</div>
-
-    <table class="ui_table bad"><tbody><tr><td>
-    Touch Next to complete setup using a Wi-Fi connection.
-    </td></tr></tbody></table>
-
-  </div>
-  <div class="layout-content-col span-6">
-
-    <div class="example_label good">Task first</div>
-
-    <table class="ui_table good"><tbody><tr><td>
-    To finish setup using Wi-Fi, touch Next.
-    </td></tr></tbody></table>
-
-  </div>
-</div>
-
-<div class="vspace size-1">&nbsp;</div>
-
-<ol><li class="value-5"><strong>Describe only what's necessary, and no more.</strong></ol>
-
-<div class="layout-content-row">
-  <div class="layout-content-col span-6 list_item_margins">
-
-    <div class="example_label bad">From a Setup Wizard screen</div>
-
-    <table class="ui_table bad">
-    <thead>
-      <tr>
-        <th>
-        Signing in...
-        </th>
-      </tr>
-    </thead>
-    <tbody>
-      <tr>
-        <td>
-        Your phone needs to communicate with<br>
-        Google servers to sign in to your account.<br>
-        This may take up to five minutes.
-        </td>
-      </tr>
-    </tbody>
-    </table>
-
-  </div>
-  <div class="layout-content-col span-6">
-
-    <div class="example_label good">From a Setup Wizard screen</div>
-
-    <table class="ui_table good">
-    <thead>
-      <tr>
-        <th>
-        Signing in...
-        </th>
-      </tr>
-    </thead>
-    <tbody>
-      <tr>
-        <td>
-        Your phone is contacting Google.<br>
-        This can take up to 5 minutes.
-        </td>
-      </tr>
-    </tbody>
-    </table>
-
-  </div>
-</div>
-
-
-
-          
-          <div class="layout-content-row content-footer">
-            <div class="paging-links layout-content-col span-9">&nbsp;</div>
-            <div class="paging-links layout-content-col span-4">
-              <a href="#" class="prev-page-link">Previous</a>
-              <a href="#" class="next-page-link">Next</a>
-            </div>
-          </div>
-          
-        </div>
-
-      </div>
-
-      <div id="page-footer">
-
-        <p id="copyright">
-          Except as noted, this content is licensed under
-          <a href="http://creativecommons.org/licenses/by/2.5/">
-          Creative Commons Attribution 2.5</a>.<br>
-          For details and restrictions, see the
-          <a href="http://developer.android.com/license.html">Content License</a>.
-        </p>
-
-        <p>
-          <a href="http://www.android.com/terms.html">Site Terms of Service</a> &ndash;
-          <a href="http://www.android.com/privacy.html">Privacy Policy</a> &ndash;
-          <a href="http://www.android.com/branding.html">Brand Guidelines</a>
-        </p>
-
-      </div>
-    </div>
-
-    <script src="../static/jquery-1.6.2.min.js"></script>
-    <script>
-    var SITE_ROOT = '../';
-    </script>
-    <script src="../static/default.js"></script>
-
-
-    <script type="text/javascript">
-    var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
-    document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
-    </script>
-    <script type="text/javascript">
-    var pageTracker = _gat._getTracker("UA-5831155-1");
-    pageTracker._trackPageview();
-    </script>
-  </body>
-</html>
diff --git a/docs/html/design/style/writing.jd b/docs/html/design/style/writing.jd
new file mode 100644
index 0000000..80fd03e
--- /dev/null
+++ b/docs/html/design/style/writing.jd
@@ -0,0 +1,330 @@
+page.title=Writing Style
+@jd:body
+
+<style>
+
+/* UI tables */
+
+.ui_table {
+  width: 100%;
+  background: #282828;
+  color: #fff;
+  border-radius: 2px;
+  box-shadow: 0 2px 4px rgba(0,0,0,0.25);
+  border-collapse: separate;
+}
+
+.ui_table th,
+.ui_table td {
+  padding: 5px 10px;
+}
+
+.ui_table thead th {
+  font-weight: 600;
+}
+
+.ui_table tfoot td {
+  border-top: 1px solid #494949;
+  border-right: 1px solid #494949;
+  text-align: center;
+}
+
+.ui_table tfoot td:last-child {
+  border-right: 0;
+}
+
+.list_item_margins {
+  margin-left: 30px !important;
+}
+
+.example_label {
+  margin-bottom: 10px;
+  padding-left: 20px;
+  background: transparent none no-repeat scroll 0px 3px;
+}
+
+.example_label.bad {
+  background-image: url({@docRoot}assets/design/ico_wrong.png);
+}
+
+.example_label.good {
+  background-image: url({@docRoot}assets/design/ico_good.png);
+}
+
+</style>
+
+<p>When choosing words for your app:</p>
+<ol>
+<li>
+<p><strong>Keep it brief.</strong> Be concise, simple and precise. Start with a 30 character limit (including
+   spaces), and don't use more unless absolutely necessary.</p>
+</li>
+<li>
+<p><strong>Keep it simple.</strong> Pretend you're speaking to someone who's smart and competent, but doesn't
+   know technical jargon and may not speak English very well. Use short words, active verbs, and
+   common nouns.</p>
+</li>
+<li>
+<p><strong>Be friendly.</strong> Use contractions. Talk directly to the reader using second person ("you"). If
+   your text doesn't read the way you'd say it in casual conversation, it's probably not the way
+   you should write it. Don't be abrupt or annoying and make the user feel safe, happy and
+   energized.</p>
+</li>
+<li>
+<p><strong>Put the most important thing first.</strong> The first two words (around 11 characters, including
+   spaces) should include at least a taste of the most important information in the string. If they
+   don't, start over.</p>
+</li>
+<li>
+<p><strong>Describe only what's necessary, and no more.</strong> Don't try to explain subtle differences. They
+   will be lost on most users.</p>
+</li>
+<li>
+<p><strong>Avoid repetition.</strong> If a significant term gets repeated within a screen or block of text, find
+   a way to use it just once.</p>
+</li>
+</ol>
+
+<h2 id="examples">Examples</h2>
+
+<ol><li class="value-1"><strong>Keep it brief.</strong> From the setup wizard:</ol>
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-6 list_item_margins">
+
+    <div class="example_label bad">Too formal</div>
+
+    <table class="ui_table good"><tbody><tr><td>
+    Consult the documentation that came with your phone for further instructions.
+    </td></tr></tbody></table>
+
+  </div>
+  <div class="layout-content-col span-6">
+
+    <div class="example_label good">Better</div>
+
+    <table class="ui_table good"><tbody><tr><td>
+    Read the instructions that came with your phone.
+    </td></tr></tbody></table>
+
+  </div>
+</div>
+
+<div class="vspace size-1">&nbsp;</div>
+
+<ol><li class="value-2"><strong>Keep it simple.</strong> From the Location settings screen:</ol>
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-6 list_item_margins">
+
+    <div class="example_label bad">Confusing</div>
+
+    <table class="ui_table bad">
+    <thead>
+      <tr>
+        <th>
+        Use GPS satellites
+        </th>
+      </tr>
+    </thead>
+    <tbody>
+      <tr>
+        <td>
+        When locating, accurate to street level.
+        </td>
+      </tr>
+    </tbody>
+    </table>
+
+  </div>
+  <div class="layout-content-col span-6">
+
+    <div class="example_label good">Better</div>
+
+    <table class="ui_table good">
+    <thead>
+      <tr>
+        <th>
+        GPS
+        </th>
+      </tr>
+    </thead>
+    <tbody>
+      <tr>
+        <td>
+        Let apps use satellites to pinpoint your location.
+        </td>
+      </tr>
+    </tbody>
+    </table>
+
+  </div>
+</div>
+
+<div class="vspace size-1">&nbsp;</div>
+
+<ol><li class="value-3"><strong>Be friendly.</strong> Dialog that appears when an application
+crashes:</ol>
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-6 list_item_margins">
+
+    <div class="example_label bad">Confusing and annoying&mdash;"Sorry" just rubs salt in the
+    wound.</div>
+
+    <table class="ui_table bad">
+    <thead>
+      <tr>
+        <th colspan="3">
+        Sorry!
+        </th>
+      </tr>
+    </thead>
+    <tbody>
+      <tr>
+        <td colspan="3">
+        Activity MyAppActivity (in application MyApp)
+        is not responding.
+        </td>
+      </tr>
+    </tbody>
+    <tfoot>
+      <tr>
+        <td width="33%">Force close</td>
+        <td width="33%">Wait</td>
+        <td width="33%">Report</td>
+      </tr>
+    </tbody>
+    </table>
+
+  </div>
+  <div class="layout-content-col span-6">
+
+    <div class="example_label good">Shorter, more direct, no faux-apologetic title:<br><br></div>
+
+    <table class="ui_table good">
+    <thead>
+      <tr>
+        <th colspan="3">
+        MyApp isn't responding.
+        </th>
+      </tr>
+    </thead>
+    <tbody>
+      <tr>
+        <td colspan="3">
+        Do you want to close it?
+        </td>
+      </tr>
+    </tbody>
+    <tfoot>
+      <tr>
+        <td width="33%">Wait</td>
+        <td width="33%">Report</td>
+        <td width="33%">Close</td>
+      </tr>
+    </tbody>
+    </table>
+
+  </div>
+</div>
+
+<div class="vspace size-1">&nbsp;</div>
+
+<ol><li class="value-4"><strong>Put the most important thing first.</strong></ol>
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-6 list_item_margins">
+
+    <div class="example_label bad">Top news last</div>
+
+    <table class="ui_table bad"><tbody><tr><td>
+    77 other people +1'd this, including Larry Page.
+    </td></tr></tbody></table>
+
+  </div>
+  <div class="layout-content-col span-6">
+
+    <div class="example_label good">Top news first</div>
+
+    <table class="ui_table good"><tbody><tr><td>
+    Larry Page and 77 others +1'd this.
+    </td></tr></tbody></table>
+
+  </div>
+</div>
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-6 list_item_margins">
+
+    <div class="example_label bad">Task last</div>
+
+    <table class="ui_table bad"><tbody><tr><td>
+    Touch Next to complete setup using a Wi-Fi connection.
+    </td></tr></tbody></table>
+
+  </div>
+  <div class="layout-content-col span-6">
+
+    <div class="example_label good">Task first</div>
+
+    <table class="ui_table good"><tbody><tr><td>
+    To finish setup using Wi-Fi, touch Next.
+    </td></tr></tbody></table>
+
+  </div>
+</div>
+
+<div class="vspace size-1">&nbsp;</div>
+
+<ol><li class="value-5"><strong>Describe only what's necessary, and no more.</strong></ol>
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-6 list_item_margins">
+
+    <div class="example_label bad">From a Setup Wizard screen</div>
+
+    <table class="ui_table bad">
+    <thead>
+      <tr>
+        <th>
+        Signing in...
+        </th>
+      </tr>
+    </thead>
+    <tbody>
+      <tr>
+        <td>
+        Your phone needs to communicate with<br>
+        Google servers to sign in to your account.<br>
+        This may take up to five minutes.
+        </td>
+      </tr>
+    </tbody>
+    </table>
+
+  </div>
+  <div class="layout-content-col span-6">
+
+    <div class="example_label good">From a Setup Wizard screen</div>
+
+    <table class="ui_table good">
+    <thead>
+      <tr>
+        <th>
+        Signing in...
+        </th>
+      </tr>
+    </thead>
+    <tbody>
+      <tr>
+        <td>
+        Your phone is contacting Google.<br>
+        This can take up to 5 minutes.
+        </td>
+      </tr>
+    </tbody>
+    </table>
+
+  </div>
+</div>
diff --git a/docs/html/guide/appendix/install-location.jd b/docs/html/guide/appendix/install-location.jd
index 292d3e7..63a3817 100644
--- a/docs/html/guide/appendix/install-location.jd
+++ b/docs/html/guide/appendix/install-location.jd
@@ -172,9 +172,9 @@
 before the external storage is mounted to the device. If your application is installed on the
 external storage, it can never receive this broadcast.</dd>
   <dt>Copy Protection</dt>
-    <dd>Your application cannot be installed to a device's SD card if it uses Android Market's 
-      Copy Protection feature. However, if you use Android Market's 
-      <a href="{@docRoot}guide/publishing/licensing.html">Application Licensing</a> instead, your 
+    <dd>Your application cannot be installed to a device's SD card if it uses Google Play's 
+      Copy Protection feature. However, if you use Google Play's 
+      <a href="{@docRoot}guide/market/licensing.html">Application Licensing</a> instead, your 
       application <em>can</em> be installed to internal or external storage, including SD cards.</dd>
 </dl>
 
diff --git a/docs/html/guide/appendix/market-filters.jd b/docs/html/guide/appendix/market-filters.jd
index d9b2155..3e502d7 100644
--- a/docs/html/guide/appendix/market-filters.jd
+++ b/docs/html/guide/appendix/market-filters.jd
@@ -1,4 +1,4 @@
-page.title=Market Filters
+page.title=Filters on Google Play
 @jd:body
 
 <div id="qv-wrapper">
@@ -6,15 +6,15 @@
 
 <h2>Quickview</h2>
 <ul>
-<li>Android Market applies filters that control which Android-powered devices can access your
-application on Market.</li>
+<li>Google Play applies filters that control which Android-powered devices can access your
+application when the user is visiting the store.</li>
 <li>Filtering is determined by comparing device configurations that you declare in you app's
 manifest file to the configurations defined by the device, as well as other factors.</li> </ul>
 
 <h2>In this document</h2>
 
 <ol>
-  <li><a href="#how-filters-work">How Filters Work in Android Market</a></li>
+  <li><a href="#how-filters-work">How Filters Work on Google Play</a></li>
   <li><a href="#manifest-filters">Filtering based on Manifest Elements</a>
     <ol>
       <li><a href="#advanced-filters">Advanced manifest filters</a></li>
@@ -47,10 +47,10 @@
 <div id="qv-extra">
   <img id="rule" src="{@docRoot}assets/images/grad-rule-qv.png">
   <div id="qv-sub-rule">
-    <img src="{@docRoot}assets/images/icon_market.jpg" style="float:left;margin:0;padding:0 5px;">
-    <h2 style="color:#669999;">Interested in publishing your app on Android Market?</h2>
+    <img src="{@docRoot}assets/images/icon_play.png" style="float:left;margin:0;padding:0 5px;">
+    <h2 style="color:#669999;padding-top:1em;">Interested in publishing your app on Google Play?</h2>
     <p><a id="publish-link"
-href="http://market.android.com/publish">Go to Android Market</a> to create a publisher
+href="http://play.google.com/apps/publish">Go to Google Play</a> to create a publisher
 account and upload your app.</p></div>
 </div>
 
@@ -58,44 +58,44 @@
 </div>
 
 
-<p>When a user searches or browses in Android Market on an Android device, the results are filtered
+<p>When a user searches or browses on Google Play on an Android device, the results are filtered
 based on which applications are compatible with that device. For example, if an application
-requires a camera (as specified in the application manifest file), then Android Market will not show
+requires a camera (as specified in the application manifest file), then Google Play will not show
 the app on any device that does not have a camera.</p>
 
 <p>Declarations in the manifest file that are compared to the device's configuration is not the
 only part of how applications are filtered. Filtering might also occur due to the user's country and
 carrier, the presence or absence of a SIM card, and other factors. </p>
 
-<p>Changes to the Android Market filters are independent of changes to the Android platform itself.
-This document is updated periodically to reflect any changes that affect the way Android Market
+<p>Changes to the Google Play filters are independent of changes to the Android platform itself.
+This document is updated periodically to reflect any changes that affect the way Google Play
 filters applications.</p>
 
 
-<h2 id="how-filters-work">How Filters Work in Android Market</h2>
+<h2 id="how-filters-work">How Filters Work on Google Play</h2>
 
-<p>Android Market uses the filter restrictions described below to determine
+<p>Google Play uses the filter restrictions described below to determine
 whether to show your application to a user who is browsing or searching for
-applications from the Android Market app. When determining whether to display your app,
-Market checks the device's hardware and software configuration, as well as it's
+applications from the Google Play app. When determining whether to display your app,
+Google Play checks the device's hardware and software configuration, as well as it's
 carrier, location, and other characteristics. It then compares those against the
 restrictions and dependencies expressed by the application's
 manifest file and publishing details. If the application is
-compatible with the device according to the filter rules, Market displays the
-application to the user. Otherwise, Market hides your application from search
+compatible with the device according to the filter rules, Google Play displays the
+application to the user. Otherwise, Google Play hides your application from search
 results and category browsing, even if a user specifically requests
-the app by clicking a deep link that points directly to the app's ID within Market..</p>
+the app by clicking a deep link that points directly to the app's ID within Google Play..</p>
 
 <p class="note"><strong>Note:</strong> When users browse the <a
-href="http://market.android.com">Android Market web site</a>, they can see all published
-applications. The Android Market web site compares the application requirements to each of the
+href="http://play.google.com/apps">Google Play web site</a>, they can see all published
+applications. The Google Play web site compares the application requirements to each of the
 user's registered devices for compatibility, though, and only allows them to install the application
 if it's compatible with their device.</p>
 
 <p>You can use any combination of the available filters for your app. For example, you can set a
 <code>minSdkVersion</code> requirement of <code>"4"</code> and set <code>smallScreens="false"</code>
-in the app, then when uploading the app to Market you could target European countries (carriers)
-only. Android Market's filters will thus prevent the application from being available on any device
+in the app, then when uploading the app to Google Play you could target European countries (carriers)
+only. Google Play's filters will thus prevent the application from being available on any device
 that does not match all three of these requirements. </p>
 
 <p>All filtering restrictions are associated with an application's version and can
@@ -106,15 +106,15 @@
 
 <h2 id="manifest-filters">Filtering based on Manifest Elements</h2>
 
-<p>Most Market filters are triggered by elements within an application's
+<p>Most filters are triggered by elements within an application's
 manifest file, <a
 href="{@docRoot}guide/topics/manifest/manifest-intro.html">AndroidManifest.xml</a>
 (although not everything in the manifest file can trigger filtering).
-Table 1 lists the manifest elements that you should use to trigger Android
-Market filtering, and explains how the filtering for each element works.</p>
+Table 1 lists the manifest elements that you should use to trigger
+filtering, and explains how the filtering for each element works.</p>
 
 <p id="table1" class="table-caption"><strong>Table 1.</strong> Manifest elements that
-trigger filtering on Market.</p>
+trigger filtering on Google Play.</p>
 <table>
   <tr>
     <th>Manifest Element</th>
@@ -129,19 +129,19 @@
 
 <p>An application indicates the screen sizes that it is capable of supporting by
 setting attributes of the <code>&lt;supports-screens&gt;</code> element. When
-the application is published, Market uses those attributes to determine whether
+the application is published, Google Play uses those attributes to determine whether
 to show the application to users, based on the screen sizes of their
 devices. </p>
 
-<p>As a general rule, Market assumes that the platform on the device can adapt
+<p>As a general rule, Google Play assumes that the platform on the device can adapt
 smaller layouts to larger screens, but cannot adapt larger layouts to smaller
 screens. Thus, if an application declares support for "normal" screen size only,
-Market makes the application available to both normal- and large-screen devices,
+Google Play makes the application available to both normal- and large-screen devices,
 but filters the application so that it is not available to small-screen
 devices.</p>
 
 <p>If an application does not declare attributes for
-<code>&lt;supports-screens&gt;</code>, Market uses the default values for those
+<code>&lt;supports-screens&gt;</code>, Google Play uses the default values for those
 attributes, which vary by API Level. Specifically: </p>
 
 <ul>
@@ -150,7 +150,7 @@
 minSdkVersion</a></code> or <code><a
 href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">android:
 targetSdkVersion</a></code> to 3 or lower, the <code>&lt;supports-screens&gt;</code> element itself
-is undefined and no attributes are available. In this case, Market assumes that
+is undefined and no attributes are available. In this case, Google Play assumes that
 the application is designed for normal-size screens and shows the application to
 devices that have normal or larger screens. </p>
 
@@ -166,19 +166,19 @@
     <p><strong>Example 1</strong><br />
     The manifest declares <code>&lt;uses-sdk android:minSdkVersion="3"&gt;</code>
     and does not include a <code>&lt;supports-screens&gt;</code> element.
-    <strong>Result</strong>: Android Market does not show the app to a user of a
-    small-screen device, but does show it to users of normal and large-screen
-    devices, unless  other filters also exclude those devices. </p>
+    <strong>Result</strong>: Google Play will not show the app to a user of a
+    small-screen device, but will show it to users of normal and large-screen
+    devices, unless  other filters apply. </p>
     <p><strong>Example 2<br />
     </strong>The manifest declares <code>&lt;uses-sdk android:minSdkVersion="3"
     android:targetSdkVersion="4"&gt;</code> and does not include a
     <code>&lt;supports-screens&gt;</code> element.
-    <strong>Result</strong>: Android Market will show the app to users on all
+    <strong>Result</strong>: Google Play will show the app to users on all
     devices, unless other filters apply. </p>
     <p><strong>Example 3<br />
     </strong>The manifest declares <code>&lt;uses-sdk android:minSdkVersion="4"&gt;</code>
     and does not include a <code>&lt;supports-screens&gt;</code> element.
-    <strong>Result</strong>: Android Market will show the app to all users,
+    <strong>Result</strong>: Google Play will show the app to all users,
     unless  other filters apply. </p>
     <p>For more information on how to declare support for screen sizes in your
     application, see <code><a
@@ -195,11 +195,11 @@
     Configuration: <br />
     keyboard, navigation, touch screen</td>
     <td valign="top"><p>An application can
-    request certain hardware features, and Android Market will  show the app only on devices that have the required hardware.</p>
+    request certain hardware features, and Google Play will  show the app only on devices that have the required hardware.</p>
       <p><strong>Example 1<br />
-      </strong>The manifest includes <code>&lt;uses-configuration android:reqFiveWayNav=&quot;true&quot; /&gt;</code>, and a user is searching for apps on a device that does not have a five-way navigational control. <strong>Result</strong>: Android Market will not show the app to the user. </p>
+      </strong>The manifest includes <code>&lt;uses-configuration android:reqFiveWayNav=&quot;true&quot; /&gt;</code>, and a user is searching for apps on a device that does not have a five-way navigational control. <strong>Result</strong>: Google Play will not show the app to the user. </p>
       <p><strong>Example 2<br />
-      </strong>The manifest does not include a <code>&lt;uses-configuration&gt;</code> element. <strong>Result</strong>: Android Market will show the app to all users, unless other filters apply.</p>
+      </strong>The manifest does not include a <code>&lt;uses-configuration&gt;</code> element. <strong>Result</strong>: Google Play will show the app to all users, unless other filters apply.</p>
 <p>For more details, see  <a
 href="{@docRoot}guide/topics/manifest/uses-configuration-element.html"><code>&lt;uses-configuration&gt;</code></a>.</p></td>
   </tr>
@@ -218,16 +218,16 @@
       </strong>The manifest includes <code>&lt;uses-feature
 android:name=&quot;android.hardware.sensor.light&quot; /&gt;</code>, and a user
 is searching for apps on a device that does not have a light sensor.
-<strong>Result</strong>: Android Market will not show the app to the user. </p>
+<strong>Result</strong>: Google Play will not show the app to the user. </p>
       <p><strong>Example 2<br />
       </strong>The manifest does not include a <code>&lt;uses-feature&gt;</code>
-element. <strong>Result</strong>: Android Market will show the app to all users,
+element. <strong>Result</strong>: Google Play will show the app to all users,
 unless other filters apply.</p>
       <p>For complete information, see <code><a
 href="{@docRoot}guide/topics/manifest/uses-feature-element.html">&lt;uses-feature&gt;</a>
 </code>.</p>
-      <p><em>Filtering based on implied features:</em> In some cases, Android
-Market interprets permissions requested through
+      <p><em>Filtering based on implied features:</em> In some cases, Google
+Play interprets permissions requested through
 <code>&lt;uses-permission&gt;</code> elements as feature requirements equivalent
 to those declared in <code>&lt;uses-feature&gt;</code> elements. See <a
 href="#uses-permission-filtering"><code>&lt;uses-permission&gt;</code></a>,
@@ -245,19 +245,19 @@
       <p><strong>Example 1<br />
       </strong>An app
         requests multiple OpenGL-ES versions by specifying <code>openGlEsVersion</code> multiple times in the
-        manifest.  <strong>Result</strong>: Market assumes that the app requires the highest of the indicated versions.</p>
+        manifest.  <strong>Result</strong>: Google Play assumes that the app requires the highest of the indicated versions.</p>
 <p><strong>Example 2<br />
 </strong>An app
-        requests OpenGL-ES version 1.1, and a user is searching for apps on a device that supports OpenGL-ES version 2.0. <strong>Result</strong>: Android Market will show the app to the user, unless other filters apply. If a
-  device reports that it supports OpenGL-ES version <em>X</em>,  Market assumes that it
+        requests OpenGL-ES version 1.1, and a user is searching for apps on a device that supports OpenGL-ES version 2.0. <strong>Result</strong>: Google Play will show the app to the user, unless other filters apply. If a
+  device reports that it supports OpenGL-ES version <em>X</em>,  Google Play assumes that it
   also supports any version earlier than <em>X</em>.
 </p>
 <p><strong>Example 3<br />
 </strong>A user is searching for apps on a device that does not
-        report an OpenGL-ES version (for example, a device running Android 1.5 or earlier). <strong>Result</strong>: Android Market assumes that the device
-  supports only OpenGL-ES 1.0. Market will only show the user apps that do not specify <code>openGlEsVersion</code>, or apps that do not specify an OpenGL-ES version higher than 1.0. </p>
+        report an OpenGL-ES version (for example, a device running Android 1.5 or earlier). <strong>Result</strong>: Google Play assumes that the device
+  supports only OpenGL-ES 1.0. Google Play will only show the user apps that do not specify <code>openGlEsVersion</code>, or apps that do not specify an OpenGL-ES version higher than 1.0. </p>
       <p><strong>Example 4<br />
-      </strong>The manifest does not specify <code>openGlEsVersion</code>. <strong>Result</strong>: Android Market will show the app to all users, unless other filters apply. </p>
+      </strong>The manifest does not specify <code>openGlEsVersion</code>. <strong>Result</strong>: Google Play will show the app to all users, unless other filters apply. </p>
 <p>For more details, see <a
 href="{@docRoot}guide/topics/manifest/uses-feature-element.html"><code>&lt;uses-feature&gt;</code></a>.</p></td>
   </tr>
@@ -268,28 +268,28 @@
     <td valign="top"><p>An application can require specific
     shared libraries to be present on the device. </p>
       <p><strong>Example 1<br />
-      </strong>An app requires the <code>com.google.android.maps</code> library, and a user is searching for apps on a device that does not have the <code>com.google.android.maps</code> library. <strong>Result</strong>: Android Market will not show the app to the user. </p>
+      </strong>An app requires the <code>com.google.android.maps</code> library, and a user is searching for apps on a device that does not have the <code>com.google.android.maps</code> library. <strong>Result</strong>: Google Play will not show the app to the user. </p>
       <p><strong>Example 2</strong><br />
-        The manifest does not include a <code>&lt;uses-library&gt;</code> element. <strong>Result</strong>: Android Market will show the app to all users, unless other filters apply.</p>
+        The manifest does not include a <code>&lt;uses-library&gt;</code> element. <strong>Result</strong>: Google Play will show the app to all users, unless other filters apply.</p>
 <p>For more details, see <a
 href="{@docRoot}guide/topics/manifest/uses-library-element.html"><code>&lt;uses-library&gt;</code></a>.</p></td>
   </tr>
   <tr id="uses-permission-filtering">
     <td valign="top" style="white-space:nowrap;"><code><a href="{@docRoot}guide/topics/manifest/uses-permission-element.html">&lt;uses-permission&gt;</a></code></td>
     <td valign="top">&nbsp;</td>
-    <td valign="top">Strictly, Android Market does not filter based on
+    <td valign="top">Strictly, Google Play does not filter based on
 <code>&lt;uses-permission&gt;</code> elements. However, it does read the
 elements to determine whether the application has hardware feature requirements
 that may not have been properly declared in <code>&lt;uses-feature&gt;</code>
 elements. For example, if an application requests the <code>CAMERA</code>
 permission but does not declare a <code>&lt;uses-feature&gt;</code> element for
-<code>android.hardware.camera</code>, Android Market considers that the
+<code>android.hardware.camera</code>, Google Play considers that the
 application requires a camera and should not be shown to users whose devices do
 not offer a camera.</p>
     <p>In general, if an application requests hardware-related permissions,
-Android Market assumes that the application requires the underlying hardware
+Google Play assumes that the application requires the underlying hardware
 features, even though there might be no corresponding to
-<code>&lt;uses-feature&gt;</code> declarations. Android Market then sets up
+<code>&lt;uses-feature&gt;</code> declarations. Google Play then sets up
 filtering based on the features implied by the <code>&lt;uses-feature&gt;</code>
 declarations.</p>
     <p>For a list of permissions that imply hardware features, see
@@ -305,9 +305,9 @@
     <td valign="top"><p>An application can require a minimum API level.  </p>
       <p><strong>Example 1</strong><br />
         The manifest includes <code>&lt;uses-sdk
-      android:minSdkVersion=&quot;3&quot;&gt;</code>, and the app uses APIs that were introduced in API Level 3. A user is searching for apps on a device that has API Level 2. <strong>Result</strong>: Android Market will not show the app to the user. </p>
+      android:minSdkVersion=&quot;3&quot;&gt;</code>, and the app uses APIs that were introduced in API Level 3. A user is searching for apps on a device that has API Level 2. <strong>Result</strong>: Google Play will not show the app to the user. </p>
       <p><strong>Example 2</strong><br />
-      The manifest does not include <code>minSdkVersion</code>, and the app uses APIs that were introduced in API Level 3. A user is searching for apps on a device that has API Level 2. <strong>Result</strong>: Android Market assumes that <code>minSdkVersion</code> is &quot;1&quot; and that the app is compatible with all versions of Android. Market  shows the app to the user and allows the user to download the app. The app crashes at runtime. </p>
+      The manifest does not include <code>minSdkVersion</code>, and the app uses APIs that were introduced in API Level 3. A user is searching for apps on a device that has API Level 2. <strong>Result</strong>: Google Play assumes that <code>minSdkVersion</code> is &quot;1&quot; and that the app is compatible with all versions of Android. Google Play  shows the app to the user and allows the user to download the app. The app crashes at runtime. </p>
     <p>Because you want to avoid this second scenario, we recommend that you always declare a <code>minSdkVersion</code>. For details, see <a
 href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min"><code>android:minSdkVersion</code></a>.</p></td>
   </tr>
@@ -316,7 +316,7 @@
     <td valign="top"><p><em>Deprecated.</em> Android
     2.1 and later do not check or enforce the <code>maxSdkVersion</code> attribute, and
     the SDK will not compile if <code>maxSdkVersion</code> is set in an app's manifest. For devices already
-    compiled with <code>maxSdkVersion</code>, Market will respect it and use it for
+    compiled with <code>maxSdkVersion</code>, Google Play will respect it and use it for
     filtering.</p>
 <p> Declaring <code>maxSdkVersion</code> is <em>not</em> recommended. For details, see <a
 href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#max"><code>android:maxSdkVersion</code></a>.</p></td>
@@ -327,7 +327,7 @@
 
 <h3 id="advanced-filters">Advanced manifest filters</h3>
 
-<p>In addition to the manifest elements in <a href="#table1">table 1</a>, Android Market can also
+<p>In addition to the manifest elements in <a href="#table1">table 1</a>, Google Play can also
 filter applications based on the advanced manifest elements in table 2.</p>
 
 <p>These manifest elements and the filtering they trigger are for exceptional use-cases
@@ -336,14 +336,14 @@
 these filters</strong>.</p>
 
 <p id="table2" class="table-caption"><strong>Table 2.</strong> Advanced manifest elements for
-Android Market filtering.</p>
+Google Play filtering.</p>
 <table>
   <tr><th>Manifest Element</th><th>Summary</th></tr>
   <tr>
     <td><nobr><a href="{@docRoot}guide/topics/manifest/compatible-screens-element.html">{@code
 &lt;compatible-screens&gt;}</a></nobr></td>
     <td>
-      <p>Android Market filters the application if the device screen size and density does not match
+      <p>Google Play filters the application if the device screen size and density does not match
 any of the screen configurations (declared by a {@code &lt;screen&gt;} element) in the {@code
 &lt;compatible-screens&gt;} element.</p>
       <p class="caution"><strong>Caution:</strong> Normally, <strong>you should not use
@@ -360,7 +360,7 @@
     <td><nobr><a href="{@docRoot}guide/topics/manifest/supports-gl-texture-element.html">{@code
 &lt;supports-gl-texture&gt;}</a></nobr></td>
     <td>
-      <p>Android Market filters the application unless one or more of the GL texture compression
+      <p>Google Play filters the application unless one or more of the GL texture compression
 formats supported by the application are also supported by the device. </p>
     </td>
   </tr>
@@ -370,16 +370,16 @@
 
 <h2 id="other-filters">Other Filters</h2>
 
-<p>Android Market uses other application characteristics to determine whether to show or hide an application for a particular user on a given device, as described in the table below. </p>
+<p>Google Play uses other application characteristics to determine whether to show or hide an application for a particular user on a given device, as described in the table below. </p>
 
 <p id="table3" class="table-caption"><strong>Table 3.</strong> Application and publishing
-characteristics that affect filtering on Market.</p>
+characteristics that affect filtering on Google Play.</p>
 <table> <tr>
     <th>Filter Name</th> <th>How It Works</th> </tr>
 
   <tr>
     <td valign="top">Publishing Status</td> <td valign="top"><p>Only published applications will appear in
-      searches and browsing within Android Market.</p> <p>Even if an app is unpublished, it can
+      searches and browsing within Google Play.</p> <p>Even if an app is unpublished, it can
         be installed if users can see it in their Downloads area among their purchased,
         installed, or recently uninstalled apps.</p> <p>If an application has been
   suspended, users will not be able to reinstall or update it, even if it appears in their Downloads.</p> </td></tr>
@@ -390,10 +390,10 @@
 country (as determined by SIM carrier) in which paid apps are available.</p></td>
 </tr> <tr>
   <td valign="top">Country / Carrier Targeting</td> <td valign="top"> <p>When you upload your app to
-    the Android Market, you can select specific countries to target. The app will only
+    Google Play, you can select specific countries to target. The app will only
     be visible to the countries (carriers) that you select, as follows:</p>
     <ul><li><p>A device's country is determined based on the carrier, if a carrier is
-      available. If no carrier can be determined, the Market application tries to
+      available. If no carrier can be determined, Google Play tries to
       determine the country based on IP.</p></li> <li><p>Carrier is determined based on
       the device's SIM (for GSM devices), not the current roaming carrier.</p></li></ul>
 </td> </tr> <tr>
@@ -404,22 +404,22 @@
       Android NDK?</a></p> </tr> <tr>
         <td valign="top">Copy-Protected Applications</td> <td valign="top"><p>To
           copy protect an application, set copy protection to "On" when you configure publishing
-options for your application. Market will not show copy-protected applications on
+options for your application. Google Play will not show copy-protected applications on
 developer devices or unreleased devices.</p></td> </tr> </table>
 
 
 
 <h2 id="MultiApks">Publishing Multiple APKs with Different Filters</h2>
 
-<p>Some specific Android Market filters allow you to publish multiple APKs for the same
+<p>Some specific Google Play filters allow you to publish multiple APKs for the same
 application in order to provide a different APK to different device configurations. For example, if
 you're creating a video game that uses high-fidelity graphic assets, you might want to create
 two APKs that each support different texture compression formats. This way, you can reduce the
 size of the APK file by including only the textures that are required for each device
-configuration. Depending on each device's support for your texture compression formats, Android
-Market will deliver it the APK that you've declared to support that device.</p>
+configuration. Depending on each device's support for your texture compression formats, Google
+Play will deliver it the APK that you've declared to support that device.</p>
 
-<p>Currently, Android Market allows you to publish multiple APKs for the same application only
+<p>Currently, Google Play allows you to publish multiple APKs for the same application only
 when each APK provides different filters based on the following configurations:</p>
 <ul>
   <li>OpenGL texture compression formats
@@ -440,7 +440,7 @@
 </ul>
 
 <p>All other filters still work the same as usual, but these three are the only filters that can
-distinguish one APK from another within the same application listing on Android Market. For example,
+distinguish one APK from another within the same application listing on Google Play. For example,
 you <em>cannot</em> publish multiple APKs for the same application if the APKs differ only based on
 whether the device has a camera.</p>
 
@@ -450,5 +450,5 @@
 requires that you follow specific rules within your filters and that you pay extra attention to the
 version codes for each APK to ensure proper update paths for each configuration.</p>
 
-<p>If you need more information about how to publish multiple APKs on Android Market, read <a
+<p>If you need more information about how to publish multiple APKs on Google Play, read <a
 href="{@docRoot}guide/market/publishing/multiple-apks.html">Multiple APK Support</a>.</p>
diff --git a/docs/html/guide/developing/building/index.jd b/docs/html/guide/developing/building/index.jd
index 59c4645..569cd28 100644
--- a/docs/html/guide/developing/building/index.jd
+++ b/docs/html/guide/developing/building/index.jd
@@ -27,8 +27,8 @@
   <p>To run an application on an emulator or device, the application must be signed using debug or
   release mode. You typically want to sign your application in debug mode when you develop and test
   your application, because the build tools use a debug key with a known password so you do not have
-  to enter it every time you build. When you are ready to release the application to Android
-  Market, you must sign the application in release mode, using your own private key.</p>
+  to enter it every time you build. When you are ready to release the application to Google
+  Play, you must sign the application in release mode, using your own private key.</p>
 
   <p>Fortunately, Eclipse or your Ant build script signs the application for you in debug mode
   when you build your application. You can also easily setup Eclipse or your Ant build to sign your
diff --git a/docs/html/guide/developing/devices/emulator.jd b/docs/html/guide/developing/devices/emulator.jd
index 02dcb68..c217790 100644
--- a/docs/html/guide/developing/devices/emulator.jd
+++ b/docs/html/guide/developing/devices/emulator.jd
@@ -78,7 +78,7 @@
 applications. You can choose what version of the Android system you want to
 run in the emulator by configuring AVDs, and you can also customize the
 mobile device skin and key mappings. When launching the emulator and at runtime,
-you can use a variety of commands and options to control the its behaviors.
+you can use a variety of commands and options to control its behavior.
 </p>
 
 <p>The Android system image distributed in the SDK contains ARM machine code for
diff --git a/docs/html/guide/developing/tools/emulator.jd b/docs/html/guide/developing/tools/emulator.jd
index 5151ec1..09e41c3 100644
--- a/docs/html/guide/developing/tools/emulator.jd
+++ b/docs/html/guide/developing/tools/emulator.jd
@@ -516,7 +516,7 @@
   </tr>
   <tr>
     <td>Audio volume up button</td>
-    <td>KEYPAD_PLUS, Ctrl-5</td>
+    <td>KEYPAD_PLUS, Ctrl-F5</td>
   </tr>
 
   <tr>
diff --git a/docs/html/guide/developing/tools/proguard.jd b/docs/html/guide/developing/tools/proguard.jd
index eca262a..ea8a1ea 100644
--- a/docs/html/guide/developing/tools/proguard.jd
+++ b/docs/html/guide/developing/tools/proguard.jd
@@ -39,7 +39,7 @@
   sized <code>.apk</code> file that is more difficult to reverse engineer. Because ProGuard makes your
   application harder to reverse engineer, it is important that you use it
   when your application utilizes features that are sensitive to security like when you are
-  <a href="{@docRoot}guide/publishing/licensing.html">Licensing Your Applications</a>.</p>
+  <a href="{@docRoot}guide/market/licensing/index.html">Licensing Your Applications</a>.</p>
 
   <p>ProGuard is integrated into the Android build system, so you do not have to invoke it
   manually. ProGuard runs only when you build your application in release mode, so you do not 
diff --git a/docs/html/guide/guide_toc.cs b/docs/html/guide/guide_toc.cs
index 4a9a684..9d5064e 100644
--- a/docs/html/guide/guide_toc.cs
+++ b/docs/html/guide/guide_toc.cs
@@ -444,15 +444,31 @@
   </li>
 
   <li>
-    <span class="heading">
-      <span class="en">Android Market Topics</span>
-    </span>
+    <h2>
+      <span class="en">Google Play Topics</span>
+    </h2>
     <ul>
       <li><a href="<?cs var:toroot ?>guide/publishing/publishing.html">
-          <span class="en">Publishing on Android Market</span>
+          <span class="en">Publishing on Google Play</span>
           </a></li>
-      <li><a href="<?cs var:toroot ?>guide/publishing/licensing.html">
+      <li class="toggle-list">
+        <div><a href="<?cs var:toroot ?>guide/market/licensing/index.html">
           <span class="en">Application Licensing</span></a>
+        </div>
+        <ul>
+          <li><a href="<?cs var:toroot?>guide/market/licensing/overview.html">
+              <span class="en">Licensing Overview</span></a>
+          </li>
+          <li><a href="<?cs var:toroot?>guide/market/licensing/setting-up.html">
+              <span class="en">Setting Up for Licensing</span></a>
+          </li>
+          <li><a href="<?cs var:toroot?>guide/market/licensing/adding-licensing.html">
+              <span class="en">Adding Licensing to Your App</span></a>
+          </li>
+          <li><a href="<?cs var:toroot?>guide/market/licensing/licensing-reference.html">
+              <span class="en">Licensing Reference</span></a>
+          </li>
+        </ul>
       </li>
       <li class="toggle-list">
         <div><a href="<?cs var:toroot?>guide/market/billing/index.html">
@@ -480,11 +496,15 @@
         </ul>
       </li>
       <li><a href="<?cs var:toroot ?>guide/appendix/market-filters.html">
-          <span class="en">Market Filters</span></a>
+          <span class="en">Filters on Google Play</span></a>
       </li>
       <li><a href="<?cs var:toroot ?>guide/market/publishing/multiple-apks.html">
           <span class="en">Multiple APK Support</span></a>
       </li>
+      <li><a href="<?cs var:toroot ?>guide/market/expansion-files.html">
+          <span class="en">APK Expansion Files</span></a>
+          <span class="new">new!</span>
+      </li>
     </ul>
   </li>
 
diff --git a/docs/html/guide/index.jd b/docs/html/guide/index.jd
index 38f71c0..8378472 100644
--- a/docs/html/guide/index.jd
+++ b/docs/html/guide/index.jd
@@ -34,9 +34,9 @@
 designing a user interface and setting up resources to storing 
 data and using permissions &mdash; as needed.</dd>
 
-<dt><b>Android Market Topics</b></dt>
-<dd>Documentation for topics that concern publishing and monetizing applications on Android
-Market, such as how to enforce licensing policies and implement in-app billing.</dd>
+<dt><b>Google Play Topics</b></dt>
+<dd>Documentation for topics that concern publishing and monetizing applications on Google Play,
+such as how to enforce licensing policies and implement in-app billing.</dd>
 
 <dt><b>Developing</b></dt>
 <dd>Directions for using Android's development and debugging tools, 
diff --git a/docs/html/guide/market/billing/billing_admin.jd b/docs/html/guide/market/billing/billing_admin.jd
index a84eb4e..0f869ab 100755
--- a/docs/html/guide/market/billing/billing_admin.jd
+++ b/docs/html/guide/market/billing/billing_admin.jd
@@ -38,19 +38,19 @@
 few administrative tasks, including setting up and maintaining your product list on the publisher
 site, registering test accounts, and handling refunds when necessary.</p>
 
-<p>You must have an Android Market publisher account to register test accounts. And you must have a
+<p>You must have a Google Play publisher account to register test accounts. And you must have a
 Google Checkout merchant account to create a product list and issue refunds to your users. If you
-already have a publisher account on Android Market, you can use your existing account. You do not
+already have a publisher account on Google Play, you can use your existing account. You do not
 need to register for a new account to support in-app billing. If you do not have a publisher
-account, you can register as an Android Market developer and set up a publisher account at the
-Android Market <a href="http://market.android.com/publish">publisher site</a>. If you do not have a
+account, you can register as a Google Play developer and set up a publisher account at the
+Google Play <a href="http://play.google.com/apps/publish">publisher site</a>. If you do not have a
 Google Checkout merchant account, you can register for one at the <a
 href="http://checkout.google.com">Google Checkout site</a>.</p>
 
 <h2 id="billing-list-setup">Creating a Product List</h2>
 
-<p>The Android Market publisher site provides a product list for each of your published
-applications. You can sell an item using Android Market's in-app billing feature only if the item is
+<p>The Google Play publisher site provides a product list for each of your published
+applications. You can sell an item using Google Play's in-app billing feature only if the item is
 listed on an application's product list. Each application has its own product list; you cannot sell
 items that are listed in another application's product list.</p>
 
@@ -77,7 +77,7 @@
 </p>
 
 <p>You can create a product list for any published application or any draft application that's been
-uploaded and saved to the Android Market site. However, you must have a Google Checkout merchant
+uploaded and saved to the Google Play site. However, you must have a Google Checkout merchant
 account and the application's manifest must include the <code>com.android.vending.BILLING</code>
 permission. If an application's manifest does not include this permission, you will be able to edit
 existing items in the product list but you will not be able to add new items to the list. For more
@@ -104,8 +104,8 @@
 <p>To add an item to a product list using the In-app Products UI, follow these steps:</p>
 
 <ol>
-  <li><a href="http://market.android.com/publish">Log in</a> to your publisher account.</li>
-  <li>In the <strong>All Android Market listings</strong> panel, under the application name, click
+  <li><a href="http://play.google.com/apps/publish">Log in</a> to your publisher account.</li>
+  <li>In the <strong>All Google Play listings</strong> panel, under the application name, click
   <strong>In-app Products</strong>.</li>
   <li>On the In-app Products List page, click <strong>Add in-app product</strong>.</li>
   <li>On the Create New In-app Product page (see figure 3), provide details about the item you are
@@ -137,7 +137,7 @@
   <li><strong>Publishing State</strong>
     <p>An item's publishing state can be <strong>Published</strong> or <strong>Unpublished
     </strong>. To be visible to a user during checkout, an item's publishing state must be set to
-    <strong>Published</strong> and the item's application must be published on Android Market.</p>
+    <strong>Published</strong> and the item's application must be published on Google Play.</p>
     <p class="note"><strong>Note:</strong> This is not true for test accounts. An item is visible to
     a test account if the application is not published and the item is published. See <a
     href="{@docRoot}guide/market/billing/billing_testing.html#billing-testing-real">Testing In-app
@@ -167,9 +167,9 @@
     <p>You must provide a default price in your home currency. You can also provide prices in other
     currencies, but you can do this only if a currency's corresponding country is listed as a
     target country for your application. You can specify target countries on the Edit Application
-    page in the Android Market developer console.</p>
+    page in the Google Play developer console.</p>
     <p>To specify prices in other currencies, you can manually enter the price for each
-    currency or you can click <strong>Auto Fill</strong> and let Android Market do a one-time
+    currency or you can click <strong>Auto Fill</strong> and let Google Play do a one-time
     conversion from your home currency to the currencies you are targeting (see figure 4).</p>
   </li>
 </ul>
@@ -357,8 +357,8 @@
 <p>To import the items that are specified in your CSV file, do the following:</p>
 
 <ol>
-  <li><a href="http://market.android.com/publish">Log in</a> to your publisher account.</li>
-  <li>In the <strong>All Android Market listings</strong> panel, under the application name, click
+  <li><a href="http://play.google.com/apps/publish">Log in</a> to your publisher account.</li>
+  <li>In the <strong>All Google Play listings</strong> panel, under the application name, click
   <strong>In-app Products</strong>.</li>
   <li>On the In-app Products List page, click <strong>Choose File</strong> and select your CSV
 file.
@@ -381,17 +381,17 @@
 
 <h3 id="billing-purchase-type">Choosing a Purchase Type</h3>
 
-<p>An item's purchase type controls how Android Market manages the purchase of the item. There are
+<p>An item's purchase type controls how Google Play manages the purchase of the item. There are
 two purchase types: "managed per user account" and "unmanaged."</p>
 
 <p>Items that are managed per user account can be purchased only once per user account. When an item
-is managed per user account, Android Market permanently stores the transaction information for each
-item on a per-user basis. This enables you to query Android Market with the
+is managed per user account, Google Play permanently stores the transaction information for each
+item on a per-user basis. This enables you to query Google Play with the
 <code>RESTORE_TRANSACTIONS</code> request and restore the state of the items a specific user has
 purchased.</p>
 
-<p>If a user attempts to purchase a managed item that has already been purchased, Android Market
-displays an "Item already purchased" error. This occurs during checkout, when Android Market
+<p>If a user attempts to purchase a managed item that has already been purchased, Google Play
+displays an "Item already purchased" error. This occurs during checkout, when Google Play
 displays the price and description information on the checkout page. When the user dismisses the
 error message, the checkout page disappears and the user returns to your user interface. As a best
 practice, your application should prevent the user from seeing this error. The sample application
@@ -404,10 +404,10 @@
 user reinstalls your application, wipes the data on their device, or installs your application on a
 new device.</p>
 
-<p>Items that are unmanaged do not have their transaction information stored on Android Market,
-which means you cannot query Android Market to retrieve transaction information for items whose
+<p>Items that are unmanaged do not have their transaction information stored on Google Play,
+which means you cannot query Google Play to retrieve transaction information for items whose
 purchase type is listed as unmanaged. You are responsible for managing the transaction information
-of unmanaged items. Also, unmanaged items can be purchased multiple times as far as Android Market
+of unmanaged items. Also, unmanaged items can be purchased multiple times as far as Google Play
 is concerned, so it's also up to you to control how many times an unmanaged item can be
 purchased.</p>
 
@@ -417,10 +417,10 @@
 
 <h2 id="billing-refunds">Handling Refunds</h2>
 
-<p>In-app billing does not allow users to send a refund request to Android Market. Refunds for
+<p>In-app billing does not allow users to send a refund request to Google Play. Refunds for
 in-app purchases must be directed to you (the application developer). You can then process the
-refund through your Google Checkout merchant account. When you do this, Android Market receives a
-refund notification from Google Checkout, and Android Market sends a refund message to your
+refund through your Google Checkout merchant account. When you do this, Google Play receives a
+refund notification from Google Checkout, and Google Play sends a refund message to your
 application. For more information, see <a
 href="{@docRoot}guide/market/billing/billing_overview.html#billing-action-notify">Handling
 IN_APP_NOTIFY messages</a> and <a
@@ -434,9 +434,9 @@
 
 <h2 id="billing-testing-setup">Setting Up Test Accounts</h2>
 
-<p>The Android Market publisher site lets you set up one or more test accounts. A test account is a
+<p>The Google Play publisher site lets you set up one or more test accounts. A test account is a
 regular Google account that you register on the publisher site as a test account. Test accounts are
-authorized to make in-app purchases from applications that you have uploaded to the Android Market
+authorized to make in-app purchases from applications that you have uploaded to the Google Play
 site but have not yet published.</p>
 
 <p>You can use any Google account as a test account. Test accounts are useful if you want to let
@@ -458,7 +458,7 @@
 <p>To add test accounts to your publisher account, follow these steps:</p>
 
 <ol>
-  <li><a href="http://market.android.com/publish">Log in</a> to your publisher account.</li>
+  <li><a href="http://play.google.com/apps/publish">Log in</a> to your publisher account.</li>
   <li>On the upper left part of the page, under your name, click <strong>Edit profile</strong>.</li>
   <li>On the Edit Profile page, scroll down to the Licensing &amp; In-app Billing panel (see figure
   5).</li>
@@ -480,7 +480,7 @@
 correct forum, you can get the support you need more quickly.</p>
 
 <p class="table-caption" id="support-table"><strong>Table 2.</strong> Developer support resources
-for Android Market in-app billing.</p>
+for Google Play in-app billing.</p>
 
 <table>
 
@@ -502,8 +502,8 @@
 android</a></td>
 </tr>
 <tr>
-<td>Market billing issue tracker</td>
-<td><a href="http://code.google.com/p/marketbilling/issues/">Market billing
+<td>Billing issue tracker</td>
+<td><a href="http://code.google.com/p/marketbilling/issues/">Billing
 project issue tracker</a></td>
 <td>Bug and issue reports related specifically to in-app billing sample code.</td>
 </tr>
diff --git a/docs/html/guide/market/billing/billing_best_practices.jd b/docs/html/guide/market/billing/billing_best_practices.jd
index d9776af..e100ce5 100755
--- a/docs/html/guide/market/billing/billing_best_practices.jd
+++ b/docs/html/guide/market/billing/billing_best_practices.jd
@@ -32,7 +32,7 @@
 
 <p>As you design your in-app billing implementation, be sure to follow the security and design
 guidelines that are discussed in this document. These guidelines are recommended best practices for
-anyone who is using Android Market's in-app billing service.</p>
+anyone who is using Google Play's in-app billing service.</p>
 
 <h2>Security Best Practices</h2>
 
@@ -92,7 +92,7 @@
 nonces on the server.</p>
 
 <h4>Take action against trademark and copyright infringement</h4>
-<p>If you see your content being redistributed on Android Market, act quickly and decisively. File a
+<p>If you see your content being redistributed on Google Play, act quickly and decisively. File a
 <a href="http://market.android.com/support/bin/answer.py?hl=en&amp;answer=141511">trademark notice
 of infringement</a> or a <a href="http://www.google.com/android_dmca.html">copyright notice of
 infringement</a>.</p>
@@ -102,7 +102,7 @@
 purchase state of the unlocked content whenever a user accesses the content. This allows you to
 revoke use when necessary and minimize piracy.</p>
 
-<h4>Protect your Android Market public key</h4>
+<h4>Protect your Google Play public key</h4>
 <p>To keep your public key safe from malicious users and hackers, do not embed it in any code as a
 literal string. Instead, construct the string at runtime from pieces or use bit manipulation (for
 example, XOR with some other string) to hide the actual key. The key itself is not secret
diff --git a/docs/html/guide/market/billing/billing_integrate.jd b/docs/html/guide/market/billing/billing_integrate.jd
index 6017583..b49dc25 100755
--- a/docs/html/guide/market/billing/billing_integrate.jd
+++ b/docs/html/guide/market/billing/billing_integrate.jd
@@ -35,8 +35,8 @@
 </div>
 </div>
 
-<p>Android Market In-app Billing provides a straightforward, simple interface for sending in-app
-billing requests and managing in-app billing transactions using Android Market. This document helps
+<p>In-app Billing on Google Play provides a straightforward, simple interface for sending in-app
+billing requests and managing in-app billing transactions using Google Play. This document helps
 you implement in-app billing by stepping through the primary implementation tasks, using the in-app
 billing sample application as an example.</p>
 
@@ -53,23 +53,23 @@
   <li><a href="#billing-permission">Update your AndroidManifest.xml file</a>.</li>
   <li><a href="#billing-service">Create a Service</a> and bind it to the
   <code>MarketBillingService</code> so your application can send billing requests and receive
-  billing responses from the Android Market application.</li>
+  billing responses from Google Play.</li>
   <li><a href="#billing-broadcast-receiver">Create a BroadcastReceiver</a> to handle broadcast
-  intents from the Android Market application.</li>
+  intents from Google Play.</li>
   <li><a href="#billing-signatures">Create a security processing component</a> to verify the
-  integrity of the transaction messages that are sent by Android Market .</li>
+  integrity of the transaction messages that are sent by Google Play.</li>
   <li><a href="#billing-implement">Modify your application code</a> to support in-app billing.</li>
 </ol>
 
 <h2 id="billing-download">Downloading the Sample Application</h2>
 
 <p>The in-app billing sample application shows you how to perform several tasks that are common to
-all Android Market in-app billing implementations, including:</p>
+all in-app billing implementations, including:</p>
 
 <ul>
-  <li>Sending in-app billing requests to the Android Market application.</li>
-  <li>Handling synchronous responses from the Android Market application.</li>
-  <li>Handling broadcast intents (asynchronous responses) from the Android Market application.</li>
+  <li>Sending in-app billing requests to Google Play.</li>
+  <li>Handling synchronous responses from Google Play.</li>
+  <li>Handling broadcast intents (asynchronous responses) from Google Play.</li>
   <li>Using in-app billing security mechanisms to verify the integrity of billing responses.</li>
   <li>Creating a user interface that lets users select items for purchase.</li>
 </ul>
@@ -91,8 +91,8 @@
 
 <tr>
 <td>IMarketBillingService.aidl</td>
-<td>Android Interface Definition Library (AIDL) file that defines the IPC interface to Android
-Market's in-app billing service (<code>MarketBillingService</code>).</td>
+<td>Android Interface Definition Library (AIDL) file that defines the IPC interface to Google
+Play's in-app billing service (<code>MarketBillingService</code>).</td>
 </tr>
 
 <tr>
@@ -109,12 +109,12 @@
 <tr>
   <td>BillingReceiver.java</td>
   <td>A {@link android.content.BroadcastReceiver} that receives asynchronous response messages
-  (broadcast intents) from Android Market. Forwards all messages to the
+  (broadcast intents) from Google Play. Forwards all messages to the
   <code>BillingService</code>.</td>
 </tr>
 <tr>
   <td>BillingService.java</td>
-  <td>A {@link android.app.Service} that sends messages to Android Market on behalf of the
+  <td>A {@link android.app.Service} that sends messages to Google Play on behalf of the
   application by connecting (binding) to the <code>MarketBillingService</code>.</td>
 </tr>
 
@@ -136,8 +136,8 @@
 
 <tr>
 <td>Consts.java</td>
-<td>Defines various Android Market constants and sample application constants. All constants that
-are defined by Android Market must be defined the same way in your application.</td>
+<td>Defines various Google Play constants and sample application constants. All constants that
+are defined by Google Play must be defined the same way in your application.</td>
 </tr>
 
 <tr>
@@ -171,7 +171,7 @@
 
 <ul>
   <li>Configuring and building the sample application.</li>
-  <li>Uploading the sample application to Android Market.</li>
+  <li>Uploading the sample application to Google Play.</li>
   <li>Setting up test accounts and running the sample application.</li>
 </ul>
 
@@ -186,12 +186,12 @@
 following:</p>
 
 <ol>
-  <li><strong>Add your Android Market public key to the sample application code.</strong>
+  <li><strong>Add your Google Play public key to the sample application code.</strong>
     <p>This enables the application to verify the signature of the transaction information that is
-    returned from Android Market. To add your public key to the sample application code, do the
+    returned from Google Play. To add your public key to the sample application code, do the
     following:</p>
     <ol>
-      <li>Log in to your Android Market <a href="http://market.android.com/publish">publisher
+      <li>Log in to your Google Play <a href="http://play.google.com/apps/publish">publisher
       account</a>.</li>
       <li>On the upper left part of the page, under your name, click <strong>Edit
       Profile</strong>.</li>
@@ -208,7 +208,7 @@
     </ol>
   </li>
   <li><strong>Change the package name of the sample application.</strong>
-    <p>The current package name is <code>com.example.dungeons</code>. Android Market does not let
+    <p>The current package name is <code>com.example.dungeons</code>. Google Play does not let
     you upload applications with package names that contain <code>com.example</code>, so you must
     change the package name to something else.</p>
   </li>
@@ -221,14 +221,14 @@
 <h3>Uploading the sample application</h3>
 
 <p>After you build a release version of the sample application and sign it, you need to upload it as
-a draft to the Android Market publisher site. You also need to create a product list for the in-app
+a draft to the Google Play publisher site. You also need to create a product list for the in-app
 items that are available for purchase in the sample application. The following instructions show you
 how to do this.</p>
 <ol>
-  <li><strong>Upload the release version of the sample application to Android Market.</strong>
+  <li><strong>Upload the release version of the sample application to Google Play.</strong>
     <p>Do not publish the sample application; leave it as an unpublished draft application. The
     sample application is for demonstration purposes only and should not be made publicly available
-    on Android Market. To learn how to upload an application to Android Market, see <a
+    on Google Play. To learn how to upload an application to Google Play, see <a
     href="http://market.android.com/support/bin/answer.py?answer=113469">Uploading
     applications</a>.</p>
   </li>
@@ -253,7 +253,7 @@
 onto a device to run it. To run the sample application, do the following:</p>
 
 <ol>
-  <li><strong>Make sure you have at least one test account registered under your Android Market
+  <li><strong>Make sure you have at least one test account registered under your Google Play
   publisher account.</strong>
     <p>You cannot purchase items from yourself (Google Checkout prohibits this), so you need to
     create at least one test account that you can use to purchase items in the sample application.
@@ -261,18 +261,18 @@
     href="{@docRoot}guide/market/billing/billing_testing.html#billing-testing-setup">Setting up Test
     Accounts</a>.</p>
   </li>
-  <li><strong>Verify that your device is running a supported version of the Android Market
+  <li><strong>Verify that your device is running a supported version of the Google Play
   application or the MyApps application.</strong>
     <p>If your device is running Android 3.0, in-app billing requires version 5.0.12 (or higher) of
     the MyApps application. If your device is running any other version of Android, in-app billing
-    requires version 2.3.4 (or higher) of the Android Market application. To learn how to check the
-    version of the Android Market application, see <a
-    href="http://market.android.com/support/bin/answer.py?answer=190860">Updating Android
-    Market</a>.</p>
+    requires version 2.3.4 (or higher) of the Google Play application. To learn how to check the
+    version of the Google Play application, see <a
+    href="http://market.android.com/support/bin/answer.py?answer=190860">Updating Google
+    Play</a>.</p>
   </li>
   <li><strong>Install the application onto your device.</strong>
-    <p>Even though you uploaded the application to Android Market, the application is not published,
-    so you cannot download it from Android Market to a device. Instead, you must install the
+    <p>Even though you uploaded the application to Google Play, the application is not published,
+    so you cannot download it from Google Play to a device. Instead, you must install the
     application onto your device. To learn how to install an application onto a device, see <a
     href="{@docRoot}guide/developing/building/building-cmdline.html#RunningOnDevice">Running on a
     device</a>.</p>
@@ -280,7 +280,7 @@
  <li><strong>Make one of your test accounts the primary account on your device.</strong>
     <p>The primary account on your device must be one of the <a
     href="{@docRoot}guide/market/billing/billing_admin.html#billing-testing-setup">test accounts</a>
-    that you registered on the Android Market site. If the primary account on your device is not a
+    that you registered on the Google Play publisher site. If the primary account on your device is not a
     test account, you must do a factory reset of the device and then sign in with one of your test
     accounts. To perform a factory reset, do the following:</p>
     <ol>
@@ -306,7 +306,7 @@
 <h2 id="billing-add-aidl">Adding the AIDL file to your project</h2>
 
 <p>The sample application contains an Android Interface Definition Language (AIDL) file,  which
-defines the interface to Android Market's in-app billing service
+defines the interface to Google Play's in-app billing service
 (<code>MarketBillingService</code>). When you add this file to your project, the Android build
 environment creates an interface file (<code>IMarketBillingService.java</code>). You can then use
 this interface to make billing requests by invoking IPC method calls.</p>
@@ -333,29 +333,29 @@
 
 <h2 id="billing-permission">Updating Your Application's Manifest</h2>
 
-<p>In-app billing relies on the Android Market application, which handles all communication between
-your application and the Android Market server. To use the Android Market application, your
+<p>In-app billing relies on the Google Play application, which handles all communication between
+your application and the Google Play server. To use the Google Play application, your
 application must request the proper permission. You can do this by adding the
 <code>com.android.vending.BILLING</code> permission to your AndroidManifest.xml file. If your
 application does not declare the in-app billing permission, but attempts to send billing requests,
-Android Market will refuse the requests and respond with a <code>RESULT_DEVELOPER_ERROR</code>
+Google Play will refuse the requests and respond with a <code>RESULT_DEVELOPER_ERROR</code>
 response code.</p>
 
 <p>In addition to the billing permission, you need to declare the {@link
 android.content.BroadcastReceiver} that you will use to receive asynchronous response messages
-(broadcast intents) from Android Market, and you need to declare the {@link android.app.Service}
-that you will use to bind with the <code>IMarketBillingService</code> and send messages to Android
-Market. You must also declare <a
+(broadcast intents) from Google Play, and you need to declare the {@link android.app.Service}
+that you will use to bind with the <code>IMarketBillingService</code> and send messages to Google
+Play. You must also declare <a
 href="{@docRoot}guide/topics/manifest/intent-filter-element.html">intent filters</a> for the {@link
 android.content.BroadcastReceiver} so that the Android system knows how to handle the broadcast
-intents that are sent from the Android Market application.</p>
+intents that are sent from the Google Play application.</p>
 
 <p>For example, here is how the in-app billing sample application declares the billing permission,
 the {@link android.content.BroadcastReceiver}, the {@link android.app.Service}, and the intent
 filters. In the sample application, <code>BillingReceiver</code> is the {@link
-android.content.BroadcastReceiver} that handles broadcast intents from the Android Market
+android.content.BroadcastReceiver} that handles broadcast intents from the Google Play
 application and <code>BillingService</code> is the {@link android.app.Service} that sends requests
-to the Android Market application.</p>
+to the Google Play application.</p>
 
 <pre>
 &lt;?xml version="1.0" encoding="utf-8"?&gt;
@@ -391,11 +391,11 @@
 <h2 id="billing-service">Creating a Local Service</h2>
 
 <p>Your application must have a local {@link android.app.Service} to facilitate messaging between
-your application and Android Market. At a minimum, this service must do the following:</p>
+your application and Google Play. At a minimum, this service must do the following:</p>
 
 <ul>
   <li>Bind to the <code>MarketBillingService</code>.
-  <li>Send billing requests (as IPC method calls) to the Android Market application. The five types
+  <li>Send billing requests (as IPC method calls) to the Google Play application. The five types
   of billing requests include:
     <ul>
       <li><code>CHECK_BILLING_SUPPORTED</code> requests</li>
@@ -474,7 +474,7 @@
 key can have the following five values:</p>
 
 <ul>
-  <li><code>CHECK_BILLING_SUPPORTED</code>&mdash;verifies that the Android Market application
+  <li><code>CHECK_BILLING_SUPPORTED</code>&mdash;verifies that the Google Play application
   supports in-app billing.</li>
   <li><code>REQUEST_PURCHASE</code>&mdash;sends a purchase request for an in-app item.</li>
   <li><code>GET_PURCHASE_INFORMATION</code>&mdash;retrieves transaction information for a purchase
@@ -510,7 +510,7 @@
 
 <h4>Verifying that in-app billing is supported (CHECK_BILLING_SUPPPORTED)</h4>
 
-<p>The following code sample shows how to verify whether the Android Market application supports
+<p>The following code sample shows how to verify whether the Google Play application supports
 in-app billing. In the sample, <code>mService</code> is an instance of the
 <code>MarketBillingService</code> interface.</p>
 
@@ -533,7 +533,7 @@
   <li><code>RESULT_BILLING_UNAVAILABLE</code>&mdash;in-app billing is not available because the API
   version you specified is not recognized or the user is not eligible to make in-app purchases (for
   example, the user resides in a country that prohibits in-app purchases).</li>
-  <li><code>RESULT_ERROR</code>&mdash;there was an error connecting with the Android Market
+  <li><code>RESULT_ERROR</code>&mdash;there was an error connecting with the Google Play
   application.</li>
   <li><code>RESULT_DEVELOPER_ERROR</code>&mdash;the application is trying to make an in-app billing
   request but the application has not declared the <code>com.android.vending.BILLING</code>
@@ -546,10 +546,10 @@
 
 <p>We recommend that you invoke the <code>CHECK_BILLING_SUPPORTED</code> request within a
 <code>RemoteException</code> block. When your code throws a <code>RemoteException</code> it
-indicates that the remote method call failed, which means that the Android Market application is out
+indicates that the remote method call failed, which means that the Google Play application is out
 of date and needs to be updated. In this case, you can provide users with an error message that
 contains a link to the <a
-href="http://market.android.com/support/bin/answer.py?answer=190860">Updating Android Market</a>
+href="http://market.android.com/support/bin/answer.py?answer=190860">Updating Google Play</a>
 Help topic.</p>
 
 <p>The sample application demonstrates how you can handle this error condition (see
@@ -561,16 +561,16 @@
 
 <ul>
   <li>Send the <code>REQUEST_PURCHASE</code> request.</li>
-  <li>Launch the {@link android.app.PendingIntent} that is returned from the Android Market
+  <li>Launch the {@link android.app.PendingIntent} that is returned from the Google Play
   application.</li>
-  <li>Handle the broadcast intents that are sent by the Android Market application.</li>
+  <li>Handle the broadcast intents that are sent by the Google Play application.</li>
 </ul>
 
 <h5>Making the request</h5>
 
 <p>You must specify four keys in the request {@link android.os.Bundle}. The following code sample
 shows how to set these keys and make a purchase request for a single in-app item. In the sample,
-<code>mProductId</code> is the Android Market product ID of an in-app item (which is listed in the
+<code>mProductId</code> is the Google Play product ID of an in-app item (which is listed in the
 application's <a href="{@docRoot}guide/market/billing/billing_admin.html#billing-list-setup">product
 list</a>), and <code>mService</code> is an instance of the <code>MarketBillingService</code>
 interface.</p>
@@ -644,25 +644,25 @@
 context and not an application context. Also, you cannot use the <code>singleTop</code> <a
 href="{@docRoot}guide/topics/manifest/activity-element.html#lmode">launch mode</a> to launch the
 pending intent. If you do either of these, the Android system will not attach the pending intent to
-your application process. Instead, it will bring Android Market to the foreground, disrupting your
+your application process. Instead, it will bring Google Play to the foreground, disrupting your
 application.</p>
 
 <h5>Handling broadcast intents</h5>
 
 <p>A <code>REQUEST_PURCHASE</code> request also triggers two asynchronous responses (broadcast
-intents). First, the Android Market application sends a <code>RESPONSE_CODE</code> broadcast intent,
+intents). First, the Google Play application sends a <code>RESPONSE_CODE</code> broadcast intent,
 which provides error information about the request. If the request does not generate an
 error, the <code>RESPONSE_CODE</code> broadcast intent returns <code>RESULT_OK</code>, which
 indicates that the request was successfully sent. (To be clear, a <code>RESULT_OK</code> response
 does not indicate that the requested purchase was successful; it indicates that the request was sent
-successfully to Android Market.)</p>
+successfully to Google Play.)</p>
 
 <p>Next, when the requested transaction changes state (for example, the purchase is successfully
-charged to a credit card or the user cancels the purchase), the Android Market application sends an
+charged to a credit card or the user cancels the purchase), the Google Play application sends an
 <code>IN_APP_NOTIFY</code> broadcast intent. This message contains a notification ID, which you can
 use to retrieve the transaction details for the <code>REQUEST_PURCHASE</code> request.</p>
 
-<p class="note"><strong>Note:</strong> The Android Market application also sends
+<p class="note"><strong>Note:</strong> The Google Play application also sends
 an <code>IN_APP_NOTIFY</code> for refunds. For more information, see <a
 href="{@docRoot}guide/market/billing/billing_overview.html#billing-action-notify">Handling
 IN_APP_NOTIFY messages</a>.</p>
@@ -670,7 +670,7 @@
 <p>Because the purchase process is not instantaneous and can take several seconds (or more), you
 must assume that a purchase request is pending from the time you receive a <code>RESULT_OK</code>
 message until you receive an <code>IN_APP_NOTIFY</code> message for the transaction. While the
-transaction is pending, the Android Market checkout UI displays an "Authorizing purchase..."
+transaction is pending, the Google Play checkout UI displays an "Authorizing purchase..."
 notification; however, this notification is dismissed after 60 seconds and you should not rely on
 this notification as your primary means of conveying transaction status to users. Instead, we
 recommend that you do the following:</p>
@@ -693,12 +693,12 @@
 be sure that your pending status UI does not block your application. For example, you should avoid
 using a hovering progress wheel to convey the status of a pending transaction because a pending
 transaction could last a long time, particularly if a device loses network connectivity and cannot
-receive transaction updates from Android Market.</p>
+receive transaction updates from Google Play.</p>
 
 <p class="caution"><strong>Important:</strong> If a user purchases a managed item, you must prevent
 the user from purchasing the item again while the original transaction is pending. If a user
-attempts to purchase a managed item twice, and the first transaction is still pending, Android
-Market will display an error to the user; however, Android Market will not send an error to your
+attempts to purchase a managed item twice, and the first transaction is still pending, Google
+Play will display an error to the user; however, Google Play will not send an error to your
 application notifying you that the second purchase request was canceled. This might cause your
 application to get stuck in a pending state while it waits for an <code>IN_APP_NOTIFY</code> message
 for the second purchase request.</p>
@@ -730,7 +730,7 @@
 <code>API_VERSION</code>, and <code>PACKAGE_NAME</code>. The additional keys are then added to the
 bundle prior to invoking the <code>sendBillingRequest()</code> method. The
 <code>REQUEST_NONCE</code> key contains a cryptographically secure nonce (number used once) that you
-must generate. The Android Market application returns this nonce with the
+must generate. The Google Play application returns this nonce with the
 <code>PURCHASE_STATE_CHANGED</code> broadcast intent so you can verify the integrity of the
 transaction information. The <code>NOTIFY_IDS</code> key contains an array of notification IDs,
 which you received in the <code>IN_APP_NOTIFY</code> broadcast intent.</p>
@@ -741,9 +741,9 @@
 request identifier for the request.</p>
 
 <p>A <code>GET_PURCHASE_INFORMATION</code> request also triggers two asynchronous responses
-(broadcast intents). First, the Android Market application sends a <code>RESPONSE_CODE</code>
+(broadcast intents). First, the Google Play application sends a <code>RESPONSE_CODE</code>
 broadcast intent, which provides status and error information about the request. Next, if the
-request was successful, the Android Market application sends a <code>PURCHASE_STATE_CHANGED</code>
+request was successful, the Google Play application sends a <code>PURCHASE_STATE_CHANGED</code>
 broadcast intent. This message contains detailed transaction information. The transaction
 information is contained in a signed JSON string (unencrypted). The message includes the signature
 so you can verify the integrity of the signed string.</p>
@@ -783,8 +783,8 @@
 <code>RESPONSE_CODE</code> broadcast intent. This broadcast intent provides status and error
 information about the request.</p>
 
-<p>You must send a confirmation when you receive transaction information from Android Market. If you
-don't send a confirmation message, Android Market will continue sending
+<p>You must send a confirmation when you receive transaction information from Google Play. If you
+don't send a confirmation message, Google Play will continue sending
 <code>IN_APP_NOTIFY</code> messages for the transactions you have not confirmed. Also,
 your application must be able to handle <code>IN_APP_NOTIFY</code> messages that contain multiple
 orders.</p>
@@ -792,7 +792,7 @@
 <p>In addition, as a best practice, you should not send a <code>CONFIRM_NOTIFICATIONS</code> request
 for a purchased item until you have delivered the item to the user. This way, if your application
 crashes or something else prevents your application from delivering the product, your application
-will still receive an <code>IN_APP_NOTIFY</code> broadcast intent from Android Market indicating
+will still receive an <code>IN_APP_NOTIFY</code> broadcast intent from Google Play indicating
 that you need to deliver the product.</p>
 
 <h4>Restoring transaction information (RESTORE_TRANSACTIONS)</h4>
@@ -817,7 +817,7 @@
 <code>API_VERSION</code>, and <code>PACKAGE_NAME</code>. The additional <code>REQUEST_NONCE</code>
 key is then added to the bundle prior to invoking the <code>sendBillingRequest()</code> method. The
 <code>REQUEST_NONCE</code> key contains a cryptographically secure nonce (number used once) that you
-must generate. The Android Market application returns this nonce with the transactions information
+must generate. The Google Play application returns this nonce with the transactions information
 contained in the <code>PURCHASE_STATE_CHANGED</code> broadcast intent so you can verify the
 integrity of the transaction information.</p>
 
@@ -827,9 +827,9 @@
 request identifier for the request.</p>
 
 <p>A <code>RESTORE_TRANSACTIONS</code> request also triggers two asynchronous responses (broadcast
-intents). First, the Android Market application sends a <code>RESPONSE_CODE</code> broadcast intent,
+intents). First, the Google Play application sends a <code>RESPONSE_CODE</code> broadcast intent,
 which provides status and error information about the request. Next, if the request was successful,
-the Android Market application sends a <code>PURCHASE_STATE_CHANGED</code> broadcast intent. This
+the Google Play application sends a <code>PURCHASE_STATE_CHANGED</code> broadcast intent. This
 message contains the detailed transaction information. The transaction information is contained in a
 signed JSON string (unencrypted). The message includes the signature so you can verify the integrity
 of the signed string.</p>
@@ -842,7 +842,7 @@
 
 <p>You may also want your {@link android.app.Service} to receive intent messages from your {@link
 android.content.BroadcastReceiver}. You can use these intent messages to convey the information that
-was sent asynchronously from the Android Market application to your {@link
+was sent asynchronously from the Google Play application to your {@link
 android.content.BroadcastReceiver}. To see an example of how you can send and receive these intent
 messages, see the <code>BillingReceiver.java</code> and <code>BillingService.java</code> files in
 the sample application. You can use these samples as a basis for your own implementation. However,
@@ -851,16 +851,16 @@
 
 <h2 id="billing-broadcast-receiver">Creating a BroadcastReceiver</h2>
 
-<p>The Android Market application uses broadcast intents to send asynchronous billing responses to
+<p>The Google Play application uses broadcast intents to send asynchronous billing responses to
 your application. To receive these intent messages, you need to create a {@link
 android.content.BroadcastReceiver} that can handle the following intents:</p>
 
 <ul>
   <li>com.android.vending.billing.RESPONSE_CODE
-  <p>This broadcast intent contains an Android Market response code, and is sent after you make an
+  <p>This broadcast intent contains a Google Play response code, and is sent after you make an
   in-app billing request. For more information about the response codes that are sent with this
   response, see <a
-  href="{@docRoot}guide/market/billing/billing_reference.html#billing-codes">Android Market Response
+  href="{@docRoot}guide/market/billing/billing_reference.html#billing-codes">Google Play Response
   Codes for In-app Billing</a>.</p>
   </li>
   <li>com.android.vending.billing.IN_APP_NOTIFY
@@ -895,18 +895,18 @@
   <td><code>com.android.vending.billing.RESPONSE_CODE</code></td>
   <td><code>request_id</code></td>
   <td>A <code>long</code> representing a request ID. A request ID identifies a specific billing
-  request and is returned by Android Market at the time a request is made.</td>
+  request and is returned by Google Play at the time a request is made.</td>
 </tr>
 <tr>
   <td><code>com.android.vending.billing.RESPONSE_CODE</code></td>
   <td><code>response_code</code></td>
-  <td>An <code>int</code> representing the actual Android Market server response code.</td>
+  <td>An <code>int</code> representing the actual Google Play server response code.</td>
 </tr>
 <tr>
   <td><code>com.android.vending.billing.IN_APP_NOTIFY</code></td>
   <td><code>notification_id</code></td>
   <td>A <code>String</code> representing the notification ID for a given purchase state change.
-  Android Market notifies you when there is a purchase state change and the notification includes a
+  Google Play notifies you when there is a purchase state change and the notification includes a
   unique notification ID. To get the details of the purchase state change, you send the notification
   ID with the <code>GET_PURCHASE_INFORMATION</code> request.</td>
 </tr>
@@ -933,16 +933,16 @@
 
   private static final String TAG = "BillingReceiver";
 
-  // Intent actions that we receive in the BillingReceiver from Android Market.
-  // These are defined by Android Market and cannot be changed.
+  // Intent actions that we receive in the BillingReceiver from Google Play.
+  // These are defined by Google Play and cannot be changed.
   // The sample application defines these in the Consts.java file.
   public static final String ACTION_NOTIFY = "com.android.vending.billing.IN_APP_NOTIFY";
   public static final String ACTION_RESPONSE_CODE = "com.android.vending.billing.RESPONSE_CODE";
   public static final String ACTION_PURCHASE_STATE_CHANGED =
     "com.android.vending.billing.PURCHASE_STATE_CHANGED";
 
-  // The intent extras that are passed in an intent from Android Market.
-  // These are defined by Android Market and cannot be changed.
+  // The intent extras that are passed in an intent from Google Play.
+  // These are defined by Google Play and cannot be changed.
   // The sample application defines these in the Consts.java file.
   public static final String NOTIFICATION_ID = "notification_id";
   public static final String INAPP_SIGNED_DATA = "inapp_signed_data";
@@ -974,7 +974,7 @@
 }
 </pre>
 
-<p>In addition to receiving broadcast intents from the Android Market application, your {@link
+<p>In addition to receiving broadcast intents from the Google Play application, your {@link
 android.content.BroadcastReceiver} must handle the information it received in the broadcast intents.
 Usually, your {@link android.content.BroadcastReceiver} does this by sending the information to a
 local service (discussed in the next section). The <code>BillingReceiver.java</code> file in the
@@ -985,8 +985,8 @@
 
 <h2 id="billing-signatures">Verifying Signatures and Nonces</h2>
 
-<p>Android Market's in-app billing service uses two mechanisms to help verify the integrity of the
-transaction information you receive from Android Market: nonces and signatures. A nonce (number used
+<p>Google Play's in-app billing service uses two mechanisms to help verify the integrity of the
+transaction information you receive from Google Play: nonces and signatures. A nonce (number used
 once) is a cryptographically secure number that your application generates and sends with every
 <code>GET_PURCHASE_INFORMATION</code> and <code>RESTORE_TRANSACTIONS</code> request. The nonce is
 returned with the <code>PURCHASE_STATE_CHANGED</code> broadcast intent, enabling you to verify that
@@ -1023,12 +1023,12 @@
 href="{@docRoot}guide/market/billing/billing_best_practices.html">Security and Design</a> and
 obfuscate your code.</p>
 
-<p>You will need to use your Android Market public key to perform the signature verification. The
-following procedure shows you how to retrieve Base64-encoded public key from the Android Market
+<p>You will need to use your Google Play public key to perform the signature verification. The
+following procedure shows you how to retrieve Base64-encoded public key from the Google Play
 publisher site.</p>
 
 <ol>
-  <li>Log in to your <a href="http://market.android.com/publish">publisher account</a>.</li>
+  <li>Log in to your <a href="http://play.google.com/apps/publish">publisher account</a>.</li>
   <li>On the upper left part of the page, under your name, click <strong>Edit profile</strong>.</li>
   <li>On the Edit Profile page, scroll down to the Licensing &amp; In-app Billing panel (see figure
   2).</li>
@@ -1080,8 +1080,8 @@
 
 <h3>Creating a user interface for selecting items</h3>
 
-<p>You must provide users with a means for selecting items that they want to purchase. Android
-Market provides the checkout user interface (which is where the user provides a form of payment and
+<p>You must provide users with a means for selecting items that they want to purchase. Google
+Play provides the checkout user interface (which is where the user provides a form of payment and
 approves the purchase), but your application must provide a control (widget) that invokes the
 <code>sendBillingRequest()</code> method when a user selects an item for purchase.</p>
 
diff --git a/docs/html/guide/market/billing/billing_overview.jd b/docs/html/guide/market/billing/billing_overview.jd
index 8f9fd4c..b593811 100755
--- a/docs/html/guide/market/billing/billing_overview.jd
+++ b/docs/html/guide/market/billing/billing_overview.jd
@@ -38,24 +38,24 @@
 </div>
 </div>
 
-<p>Android Market In-app Billing is an Android Market service that provides checkout processing for
+<p>In-app Billing is a Google Play service that provides checkout processing for
 in-app purchases. To use the service, your application sends a billing request for a specific in-app
 product. The service then handles all of the checkout details for the transaction, including
 requesting and validating the form of payment and processing the financial transaction. When the
 checkout process is complete, the service sends your application the purchase details, such as the
 order number, the order date and time, and the price paid. At no point does your application have to
-handle any financial transactions; that role is provided by Android Market's in-app billing
+handle any financial transactions; that role is provided by Google Play's in-app billing
 service.</p>
 
 <h2 id="billing-arch">In-app Billing Architecture</h2>
 
 <p>In-app billing uses an asynchronous message loop to convey billing requests and billing responses
-between your application and the Android Market server. In practice, your application never directly
-communicates with the Android Market server (see figure 1). Instead, your application sends billing
-requests to the Android Market application over interprocess communication (IPC) and receives
-purchase responses from the Android Market application in the form of asynchronous broadcast
-intents. Your application does not manage any network connections between itself and the Android
-Market server or use any special APIs from the Android platform.</p>
+between your application and the Google Play server. In practice, your application never directly
+communicates with the Google Play server (see figure 1). Instead, your application sends billing
+requests to the Google Play application over interprocess communication (IPC) and receives
+purchase responses from the Google Play application in the form of asynchronous broadcast
+intents. Your application does not manage any network connections between itself and the Google
+Play server or use any special APIs from the Android platform.</p>
 
 <p>Some in-app billing implementations may also use a private remote server to deliver content or
 validate transactions, but a remote server is not required to implement in-app billing. A remote
@@ -70,16 +70,16 @@
 <img src="{@docRoot}images/billing_arch.png" alt="" height="582" />
 <p class="img-caption">
   <strong>Figure 1.</strong> Your application sends and receives billing messages through the
-  Android Market application, which handles all communication with the Android Market server.</p>
+  Google Play application, which handles all communication with the Google Play server.</p>
 </div>
 
 <p>A typical in-app billing implementation relies on three components:</p>
 <ul>
   <li>A {@link android.app.Service} (named <code>BillingService</code> in the sample application),
-  which processes purchase messages from the application and sends billing requests to Android
-  Market's in-app billing service.</li>
+  which processes purchase messages from the application and sends billing requests to the Google
+  Play in-app billing service.</li>
   <li>A {@link android.content.BroadcastReceiver} (named <code>BillingReceiver</code> in the sample
-  application), which receives all asynchronous billing responses from the Android Market
+  application), which receives all asynchronous billing responses from the Google Play
   application.</li>
   <li>A security component (named <code>Security</code> in the sample application), which performs
   security-related tasks, such as signature verification and nonce generation. For more information
@@ -99,19 +99,19 @@
 
 <p>In addition to these components, your application must provide a way to store information about
 users' purchases and some sort of user interface that lets users select items to purchase. You do
-not need to provide a checkout user interface. When a user initiates an in-app purchase, the Android
-Market application presents the checkout user interface to your user. When the user completes the
+not need to provide a checkout user interface. When a user initiates an in-app purchase, the Google
+Play application presents the checkout user interface to your user. When the user completes the
 checkout process, your application resumes.</p>
 
 <h2 id="billing-msgs">In-app Billing Messages</h2>
 
-<p>When the user initiates a purchase, your application sends billing messages to Android Market's
+<p>When the user initiates a purchase, your application sends billing messages to Google Play's
 in-app billing service (named <code>MarketBillingService</code>) using simple IPC method calls. The
-Android Market application responds to all billing requests synchronously, providing your
-application with status notifications and other information. The Android Market application also
+Google Play application responds to all billing requests synchronously, providing your
+application with status notifications and other information. The Google Play application also
 responds to some billing requests asynchronously, providing your application with error messages and
 detailed transaction information. The following section describes the basic request-response
-messaging that takes place between your application and the Android Market application.</p>
+messaging that takes place between your application and the Google Play application.</p>
 
 <h3 id="billing-request">In-app billing requests</h3>
 
@@ -133,31 +133,31 @@
 
 <p>One of the most important keys that every request Bundle must have is the
 <code>BILLING_REQUEST</code> key. This key lets you specify the type of billing request you are
-making. Android Market's in-app billing service supports the following five types of billing
+making. Google Play's in-app billing service supports the following five types of billing
 requests:</p>
 
 <ul>
   <li><code>CHECK_BILLING_SUPPORTED</code>
-    <p>This request verifies that the Android Market application supports in-app billing. You
+    <p>This request verifies that the Google Play application supports in-app billing. You
     usually send this request when your application first starts up. This request is useful if you
     want to enable or disable certain UI features that are relevant only to in-app billing.</p>
   </li>
   <li><code>REQUEST_PURCHASE</code>
-    <p>This request sends a purchase message to the Android Market application and is the foundation
+    <p>This request sends a purchase message to the Google Play application and is the foundation
     of in-app billing. You send this request when a user indicates that he or she wants to purchase
-    an item in your application. Android Market then handles the financial transaction by displaying
+    an item in your application. Google Play then handles the financial transaction by displaying
     the checkout user interface.</p>
   </li>
   <li><code>GET_PURCHASE_INFORMATION</code>
     <p>This request retrieves the details of a purchase state change. A purchase changes state when
     a requested purchase is billed successfully or when a user cancels a transaction during
-    checkout. It can also occur when a previous purchase is refunded. Android Market notifies your
+    checkout. It can also occur when a previous purchase is refunded. Google Play notifies your
     application when a purchase changes state, so you only need to send this request when there is
     transaction information to retrieve.</p>
   </li>
   <li><code>CONFIRM_NOTIFICATIONS</code>
     <p>This request acknowledges that your application received the details of a purchase state
-    change. Android Market sends purchase state change notifications to your application until you
+    change. Google Play sends purchase state change notifications to your application until you
     confirm that you received them.</p>
   </li>
   <li><code>RESTORE_TRANSACTIONS</code>
@@ -171,7 +171,7 @@
 
 <h3 id="billing-response">In-app Billing Responses</h3>
 
-<p>The Android Market application responds to in-app billing requests with both synchronous and
+<p>The Google Play application responds to in-app billing requests with both synchronous and
 asynchronous responses. The synchronous response is a {@link android.os.Bundle} with the following
 three keys:</p>
 
@@ -196,9 +196,9 @@
 
 <ul>
     <li><code>com.android.vending.billing.RESPONSE_CODE</code>
-    <p>This response contains an Android Market server response code, and is sent after you make an
+    <p>This response contains a Google Play server response code, and is sent after you make an
     in-app billing request. A server response code can indicate that a billing request was
-    successfully sent to Android Market or it can indicate that some error occurred during a billing
+    successfully sent to Google Play or it can indicate that some error occurred during a billing
     request. This response is <em>not</em> used to report any purchase state changes (such as refund
     or purchase information). For more information about the response codes that are sent with this
     response, see <a
@@ -253,7 +253,7 @@
 <ol>
   <li>Your application sends a purchase request (<code>REQUEST_PURCHASE</code> type), specifying a
   product ID and other parameters.</li>
-  <li>The Android Market application sends your application a Bundle with the following keys:
+  <li>The Google Play application sends your application a Bundle with the following keys:
   <code>RESPONSE_CODE</code>, <code>PURCHASE_INTENT</code>, and <code>REQUEST_ID</code>. The
   <code>PURCHASE_INTENT</code> key provides a {@link android.app.PendingIntent}, which your
   application uses to start the checkout UI for the given product ID.</li>
@@ -262,20 +262,20 @@
     context and not an application context.</p>
   </li>
   <li>When the checkout flow finishes (that is, the user successfully purchases the item or cancels
-  the purchase), Android Market sends your application a notification message (an
+  the purchase), Google Play sends your application a notification message (an
   <code>IN_APP_NOTIFY</code> broadcast intent). The notification message includes a notification ID,
   which references the transaction.</li>
   <li>Your application requests the transaction information by sending a
   <code>GET_PURCHASE_STATE_CHANGED</code> request, specifying the notification ID for the
   transaction.</li>
-  <li>The Android Market application sends a Bundle with a <code>RESPONSE_CODE</code> key and a 
+  <li>The Google Play application sends a Bundle with a <code>RESPONSE_CODE</code> key and a 
   <code>REQUEST_ID</code> key.
-  <li>Android Market sends the transaction information to your application in a
+  <li>Google Play sends the transaction information to your application in a
   <code>PURCHASE_STATE_CHANGED</code> broadcast intent.</li>
   <li>Your application confirms that you received the transaction information for the given
   notification ID by sending a confirmation message (<code>CONFIRM_NOTIFICATIONS</code> type),
   specifying the notification ID for which you received transaction information.</li>
-  <li>The Android Market application sends your application a Bundle with a
+  <li>The Google Play application sends your application a Bundle with a
   <code>RESPONSE_CODE</code> key and a <code>REQUEST_ID</code> key.</li>
 </ol>
 
@@ -284,13 +284,13 @@
   <strong>Figure 2.</strong> Message sequence for a purchase request.
 </p>
 
-<p>Keep in mind, you must send a confirmation when you receive transaction information from Android
-Market (step 8 in figure 2). If you don't send a confirmation message, Android Market will
+<p>Keep in mind, you must send a confirmation when you receive transaction information from Google
+Play (step 8 in figure 2). If you don't send a confirmation message, Google Play will
 continue sending <code>IN_APP_NOTIFY</code> messages for the transactions you have not
 confirmed. As a best practice, you should not send a <code>CONFIRM_NOTIFICATIONS</code> request for
 a purchased item until you have delivered the item to the user. This way, if your application
 crashes or something else prevents your application from delivering the product, your application
-will still receive an <code>IN_APP_NOTIFY</code> broadcast intent from Android Market indicating
+will still receive an <code>IN_APP_NOTIFY</code> broadcast intent from Google Play indicating
 that you need to deliver the product. Also, as a best practice, your application must be able to
 handle <code>IN_APP_NOTIFY</code> messages that contain multiple orders.</p>
 
@@ -307,7 +307,7 @@
 </div>
 
 <p>The request triggers three responses. The first is a {@link android.os.Bundle} with a
-<code>RESPONSE_CODE</code> key and a <code>REQUEST_ID</code> key. Next, the Android Market
+<code>RESPONSE_CODE</code> key and a <code>REQUEST_ID</code> key. Next, the Google Play
 application sends a <code>RESPONSE_CODE</code> broadcast intent, which provides status information
 or error information about the request. As always, the <code>RESPONSE_CODE</code> message references
 a specific request ID, so you can determine which request a <code>RESPONSE_CODE</code> message
@@ -338,18 +338,18 @@
 is unavailable because the API version you specified is unrecognized or the user is not eligible to
 make in-app purchases (for example, the user resides in a country that does not allow in-app
 billing). A <code>SERVER_ERROR</code> can also be returned, indicating that there was a problem with
-the Android Market server.</p>
+the Google Play server.</p>
 
 <h3 id="billing-action-notify">Handling IN_APP_NOTIFY messages</h3>
 
-<p>Usually, your application receives an <code>IN_APP_NOTIFY</code> broadcast intent from Android
-Market in response to a <code>REQUEST_PURCHASE</code> message (see figure 2). The
+<p>Usually, your application receives an <code>IN_APP_NOTIFY</code> broadcast intent from Google
+Play in response to a <code>REQUEST_PURCHASE</code> message (see figure 2). The
 <code>IN_APP_NOTIFY</code> broadcast intent informs your application that the state of a requested
 purchase has changed. To retrieve the details of that purchase, your application sends a
-<code>GET_PURCHASE_INFORMATION</code> request. Android Market responds with a
+<code>GET_PURCHASE_INFORMATION</code> request. Google Play responds with a
 <code>PURCHASE_STATE_CHANGED</code> broadcast intent, which contains the details of the purchase
 state change. Your application then sends a <code>CONFIRM_NOTIFICATIONS</code> message, informing
-Android Market that you have received the purchase state change information.</p>
+Google Play that you have received the purchase state change information.</p>
 
 <p>In some special cases, you may receive multiple <code>IN_APP_NOTIFY</code> messages even though
 you have confirmed receipt of the purchase information, or you may receive
@@ -358,13 +358,13 @@
 
 <h4>Handling multiple IN_APP_NOTIFY messages</h4>
 
-<p>When Android Market receives a <code>CONFIRM_NOTIFICATIONS</code> message for a given
+<p>When Google Play receives a <code>CONFIRM_NOTIFICATIONS</code> message for a given
 <code>PURCHASE_STATE_CHANGED</code> message, it usually stops sending <code>IN_APP_NOTIFY</code>
-intents for that <code>PURCHASE_STATE_CHANGED</code> message. Sometimes, however, Android
-Market may send repeated <code>IN_APP_NOTIFY</code> intents for a
+intents for that <code>PURCHASE_STATE_CHANGED</code> message. Sometimes, however, Google
+Play may send repeated <code>IN_APP_NOTIFY</code> intents for a
 <code>PURCHASE_STATE_CHANGED</code> message even though your application has sent a
 <code>CONFIRM_NOTIFICATIONS</code> message. This can occur if a device loses network connectivity
-while you are sending the <code>CONFIRM_NOTIFICATIONS</code> message. In this case, Android Market
+while you are sending the <code>CONFIRM_NOTIFICATIONS</code> message. In this case, Google Play
 might not receive your <code>CONFIRM_NOTIFICATIONS</code> message and it could send multiple
 <code>IN_APP_NOTIFY</code> messages until it receives acknowledgement that you received the
 transaction message. Therefore, your application must be able to recognize that the subsequent
@@ -390,7 +390,7 @@
 
 <p>In the first case, your application may receive an <code>IN_APP_NOTIFY</code> broadcast intent
 when a user has your application installed on two (or more) devices and the user makes an in-app
-purchase from one of the devices. In this case, Android Market sends an <code>IN_APP_NOTIFY</code>
+purchase from one of the devices. In this case, Google Play sends an <code>IN_APP_NOTIFY</code>
 message to the second device, informing the application that there is a purchase state change. Your
 application can handle this message the same way it handles the response from an
 application-initiated <code>REQUEST_PURCHASE</code> message, so that ultimately your application
@@ -400,8 +400,8 @@
 to "managed per user account."</p>
 
 <p>In the second case, your application can receive an <code>IN_APP_NOTIFY</code> broadcast intent
-when Android Market receives a refund notification from Google Checkout. In this case, Android
-Market sends an <code>IN_APP_NOTIFY</code> message to your application. Your application can handle
+when Google Play receives a refund notification from Google Checkout. In this case, Google
+Play sends an <code>IN_APP_NOTIFY</code> message to your application. Your application can handle
 this message the same way it handles responses from an application-initiated
 <code>REQUEST_PURCHASE</code> message so that ultimately your application receives a
 <code>PURCHASE_STATE_CHANGED</code> message that includes information about the item that has been
@@ -417,13 +417,13 @@
 <h2 id="billing-security">Security Controls</h2>
 
 <p>To help ensure the integrity of the transaction information that is sent to your application,
-Android Market signs the JSON string that is contained in the <code>PURCHASE_STATE_CHANGED</code>
-broadcast intent. Android Market uses the private key that is associated with your publisher account
+Google Play signs the JSON string that is contained in the <code>PURCHASE_STATE_CHANGED</code>
+broadcast intent. Google Play uses the private key that is associated with your publisher account
 to create this signature. The publisher site generates an RSA key pair for each publisher account.
 You can find the public key portion of this key pair on your account's profile page. It is the same
-public key that is used with Android Market licensing.</p>
+public key that is used with Google Play licensing.</p>
 
-<p>When Android Market signs a billing response, it includes the signed JSON string (unencrypted)
+<p>When Google Play signs a billing response, it includes the signed JSON string (unencrypted)
 and the signature. When your application receives this signed response you can use the public key
 portion of your RSA key pair to verify the signature. By performing signature verification you can
 help detect responses that have been tampered with or that have been spoofed. You can perform this
@@ -431,9 +431,9 @@
 remote server then we recommend that you perform the signature verification on that server.</p>
 
 <p>In-app billing also uses nonces (a random number used once) to help verify the integrity of the
-purchase information that's returned from Android Market. Your application must generate a nonce and
+purchase information that's returned from Google Play. Your application must generate a nonce and
 send it with a <code>GET_PURCHASE_INFORMATION</code> request and a <code>RESTORE_TRANSACTIONS</code>
-request. When Android Market receives the request, it adds the nonce to the JSON string that
+request. When Google Play receives the request, it adds the nonce to the JSON string that
 contains the transaction information. The JSON string is then signed and returned to your
 application. When your application receives the JSON string, you need to verify the nonce as well as
 the signature of the JSON string.</p>
@@ -447,20 +447,20 @@
 limitations.</p>
 
 <ul>
-  <li>In-app billing can be implemented only in applications that you publish through Android
-  Market.</li>
-  <li>You must have a Google Checkout Merchant account to use Android Market In-app Billing.</li>
+  <li>In-app billing can be implemented only in applications that you publish through Google
+  Play.</li>
+  <li>You must have a Google Checkout Merchant account to use Google Play In-app Billing.</li>
   <li>If your device is running Android 3.0, in-app billing requires version 5.0.12 (or higher) of
   the MyApps application. If your device is running any other version of Android, in-app billing
-  requires version 2.3.4 (or higher) of the Android Market application.</li>
+  requires version 2.3.4 (or higher) of the Google Play application.</li>
   <li>An application can use in-app billing only if the device is running Android 1.6 (API level 4)
   or higher.</li>
   <li>You can use in-app billing to sell only digital content. You cannot use in-app billing to sell
   physical goods, personal services, or anything that requires physical delivery.</li>
-  <li>Android Market does not provide any form of content delivery. You are responsible for
+  <li>Google Play does not provide any form of content delivery. You are responsible for
   delivering the digital content that you sell in your applications.</li>
   <li>You cannot implement in-app billing on a device that never connects to the network. To
-  complete in-app purchase requests, a device must be able to access the Android Market server over
+  complete in-app purchase requests, a device must be able to access the Google Play server over
   the network. </li>
 </ul>
 
diff --git a/docs/html/guide/market/billing/billing_reference.jd b/docs/html/guide/market/billing/billing_reference.jd
index 5a7ba56..e8cf2ee8 100755
--- a/docs/html/guide/market/billing/billing_reference.jd
+++ b/docs/html/guide/market/billing/billing_reference.jd
@@ -36,20 +36,20 @@
 <p>The following document provides technical reference information for the following:</p>
 
 <ul>
-  <li><a href="#billing-codes">Android Market Server Response Codes for In-app Billing</a></li>
+  <li><a href="#billing-codes">Google Play Server Response Codes for In-app Billing</a></li>
   <li><a href="#billing-interface">In-app Billing Interface Parameters</a></li>
   <li><a href="#billing-intents">In-app Billing Broadcast Intents</a></li>
 </ul>
 
-<h2 id="billing-codes">Android Market Server Response Codes for In-app Billing</h2>
+<h2 id="billing-codes">Google Play Server Response Codes for In-app Billing</h2>
 
-<p>The following table lists all of the server response codes that are sent from Android Market to
-your application. Android Market sends these response codes asynchronously as
+<p>The following table lists all of the server response codes that are sent from Google Play to
+your application. Google Play sends these response codes asynchronously as
 <code>response_code</code> extras in the <code>com.android.vending.billing.RESPONSE_CODE</code>
 broadcast intent. Your application must handle all of these response codes.</p>
 
 <p class="table-caption" id="response-codes-table"><strong>Table 1.</strong> Summary of response
-codes returned by Android Market.</p>
+codes returned by Google Play.</p>
 
 <table>
 
@@ -80,13 +80,13 @@
   <td><code>RESULT_BILLING_UNAVAILABLE</code></td>
   <td>3</td>
   <td>Indicates that in-app billing is not available because the <code>API_VERSION</code> that you
-  specified is not recognized by the Android Market application or the user is ineligible for in-app
+  specified is not recognized by the Google Play application or the user is ineligible for in-app
   billing (for example, the user resides in a country that prohibits in-app purchases).</td>
 </tr>
 <tr>
   <td><code>RESULT_ITEM_UNAVAILABLE</code></td>
   <td>4</td>
-  <td>Indicates that Android Market cannot find the requested item in the application's product
+  <td>Indicates that Google Play cannot find the requested item in the application's product
   list. This can happen if the product ID is misspelled in your <code>REQUEST_PURCHASE</code>
   request or if an item is unpublished in the application's product list.</td>
 </tr>
@@ -108,7 +108,7 @@
 
 <h2 id="billing-interface">In-app Billing Service Interface</h2>
 
-<p>The following section describes the interface for Android Market's in-app billing service. The
+<p>The following section describes the interface for Google Play's in-app billing service. The
 interface is defined in the <code>IMarketBillingService.aidl</code> file, which is included with the
 in-app billing <a
 href="{@docRoot}guide/market/billing/billing_integrate.html#billing-download">sample
@@ -144,7 +144,7 @@
   <td><code>int</code></td>
   <td>1</td>
   <td>Yes</td>
-  <td>The version of Android Market's in-app billing service you are using. The current version is
+  <td>The version of Google Play's in-app billing service you are using. The current version is
   1.</td>
 </tr>
 <tr>
@@ -160,8 +160,8 @@
   <td>Any valid product identifier.</td>
   <td>Required for <code>REQUEST_PURCHASE</code> requests.</td>
   <td>The product ID of the item you are making a billing request for. Every in-app item that you
-  sell using Android Market's in-app billing service must have a unique product ID, which you
-  specify on the Android Market publisher site.</td>
+  sell using Google Play's in-app billing service must have a unique product ID, which you
+  specify on the Google Play publisher site.</td>
 </tr>
 <tr>
   <td><code>NONCE</code></td>
@@ -172,7 +172,7 @@
   <td>A number used once. Your application must generate and send a nonce with each
   <code>GET_PURCHASE_INFORMATION</code> and <code>RESTORE_TRANSACTIONS</code> request. The nonce is
   returned with the <code>PURCHASE_STATE_CHANGED</code> broadcast intent, so you can use this value
-  to verify the integrity of transaction responses form Android Market.</td>
+  to verify the integrity of transaction responses form Google Play.</td>
 </tr>
 <tr>
   <td><code>NOTIFY_IDS</code></td>
@@ -202,20 +202,20 @@
 
 <ul>
   <li><code>CHECK_BILLING_SUPPORTED</code>
-    <p>This request verifies that the Android Market application supports in-app billing. You
+    <p>This request verifies that the Google Play application supports in-app billing. You
     usually send this request when your application first starts up. This request is useful if you
     want to enable or disable certain UI features that are relevant only to in-app billing.</p>
   </li>
   <li><code>REQUEST_PURCHASE</code>
-    <p>This request sends a purchase message to the Android Market application and is the foundation
+    <p>This request sends a purchase message to the Google Play application and is the foundation
     of in-app billing. You send this request when a user indicates that he or she wants to purchase
-    an item in your application. Android Market then handles the financial transaction by displaying
+    an item in your application. Google Play then handles the financial transaction by displaying
     the checkout user interface.</p>
   </li>
   <li><code>GET_PURCHASE_INFORMATION</code>
     <p>This request retrieves the details of a purchase state change. A purchase state change can
     occur when a purchase request is billed successfully or when a user cancels a transaction during
-    checkout. It can also occur when a previous purchase is refunded. Android Market notifies your
+    checkout. It can also occur when a previous purchase is refunded. Google Play notifies your
     application when a purchase changes state, so you only need to send this request when there is
     transaction information to retrieve.</p>
   </li>
@@ -294,8 +294,8 @@
 
 <h2 id="billing-intents">In-app Billing Broadcast Intents</h2>
 
-<p>The following section describes the in-app billing broadcast intents that are sent by the Android
-Market application. These broadcast intents inform your application about in-app billing actions
+<p>The following section describes the in-app billing broadcast intents that are sent by the Google
+Play application. These broadcast intents inform your application about in-app billing actions
 that have occurred. Your application must implement a {@link android.content.BroadcastReceiver} to
 receive these broadcast intents, such as the <code>BillingReceiver</code> that's shown in the in-app
 billing <a href="{@docRoot}guide/market/billing/billing_integrate.html#billing-download">sample
@@ -303,21 +303,21 @@
 
 <h4>com.android.vending.billing.RESPONSE_CODE</h4>
 
-<p>This broadcast intent contains an Android Market response code, and is sent after you make an
+<p>This broadcast intent contains a Google Play response code, and is sent after you make an
 in-app billing request. A server response code can indicate that a billing request was successfully
-sent to Android Market or it can indicate that some error occurred during a billing request. This
+sent to Google Play or it can indicate that some error occurred during a billing request. This
 intent is not used to report any purchase state changes (such as refund or purchase information).
 For more information about the response codes that are sent with this response, see <a
-href="#billing-codes">Android Market Response Codes for In-app Billing</a>. The sample application
+href="#billing-codes">Google Play Response Codes for In-app Billing</a>. The sample application
 assigns this broadcast intent to a constant named <code>ACTION_RESPONSE_CODE</code>.</p>
 
 <h5>Extras</h5>
 
 <ul type="none">
   <li><code>request_id</code>&mdash;a <code>long</code> representing a request ID. A request ID
-  identifies a specific billing request and is returned by Android Market at the time a request is
+  identifies a specific billing request and is returned by Google Play at the time a request is
   made.</li>
-  <li><code>response_code</code>&mdash;an <code>int</code> representing the Android Market server
+  <li><code>response_code</code>&mdash;an <code>int</code> representing the Google Play server
   response code.</li>
 </ul>
 
@@ -335,7 +335,7 @@
 
 <ul type="none">
   <li><code>notification_id</code>&mdash;a <code>String</code> representing the notification ID for
-  a given purchase state change. Android Market notifies you when there is a purchase state change
+  a given purchase state change. Google Play notifies you when there is a purchase state change
   and the notification includes a unique notification ID. To get the details of the purchase state
   change, you send the notification ID with the <code>GET_PURCHASE_INFORMATION</code> request.</li>
 </ul>
@@ -375,15 +375,15 @@
 <tr>
   <td>nonce</td>
   <td>A number used once. Your application generates the nonce and sends it with the
-  <code>GET_PURCHASE_INFORMATION</code> request. Android Market sends the nonce back as part of the
+  <code>GET_PURCHASE_INFORMATION</code> request. Google Play sends the nonce back as part of the
   JSON string so you can verify the integrity of the message.</td>
 </tr>
 <tr>
   <td>notificationId</td>
   <td>A unique identifier that is sent with an <code>IN_APP_NOTIFY</code> broadcast intent. Each
   <code>notificationId</code> corresponds to a specify message that is waiting to be retrieved on
-  the Android Market server. Your application sends back the <code>notificationId</code> with the
-  <code>GET_PURCHASE_INFORMATION</code> message so Android Market can determine which messages you
+  the Google Play server. Your application sends back the <code>notificationId</code> with the
+  <code>GET_PURCHASE_INFORMATION</code> message so Google Play can determine which messages you
   are retrieving.</td>
 </tr>
 <tr>
@@ -398,7 +398,7 @@
 <tr>
   <td>productId</td>
   <td>The item's product identifier. Every item has a product ID, which you must specify in the
-  application's product list on the Android Market publisher site.</td>
+  application's product list on the Google Play publisher site.</td>
 </tr>
 <tr>
   <td>purchaseTime</td>
diff --git a/docs/html/guide/market/billing/billing_testing.jd b/docs/html/guide/market/billing/billing_testing.jd
index 5453047..77aa3ed 100755
--- a/docs/html/guide/market/billing/billing_testing.jd
+++ b/docs/html/guide/market/billing/billing_testing.jd
@@ -32,16 +32,16 @@
 </div>
 </div>
 
-<p>The Android Market publisher site provides several tools that help you test your in-app billing
+<p>The Google Play publisher site provides several tools that help you test your in-app billing
 implementation before it is published. You can use these tools to create test accounts and purchase
 special reserved items that send static billing responses to your application.</p>
 
 <p>To test in-app billing in an application you must install the application on an Android-powered
 device. You cannot use the Android emulator to test in-app billing.  The device you use for testing
 must run a standard version of the Android 1.6 or later platform (API level 4 or higher), and have
-the most current version of the Android Market application installed. If a device is not running the
-most current Android Market application, your application won't be able to send in-app billing
-requests to Android Market. For general information about how to set up a device for use in
+the most current version of the Google Play application installed. If a device is not running the
+most current Google Play application, your application won't be able to send in-app billing
+requests to Google Play. For general information about how to set up a device for use in
 developing Android applications, see <a href="{@docRoot}guide/developing/device.html">Using Hardware
 Devices</a>.</p>
 
@@ -50,12 +50,12 @@
 <h2 id="billing-testing-static">Testing in-app purchases with static responses</h2>
 
 <p>We recommend that you first test your in-app billing implementation using static responses from
-Android Market. This enables you to verify that your application is handling the primary Android
-Market responses correctly and that your application is able to verify signatures correctly.</p>
+Google Play. This enables you to verify that your application is handling the primary Google
+Play responses correctly and that your application is able to verify signatures correctly.</p>
 
 <p>To test your implementation with static responses, you make an in-app billing request using a
 special item that has a reserved product ID. Each reserved product ID returns a specific static
-response from Android Market. No money is transferred when you make in-app billing requests with the
+response from Google Play. No money is transferred when you make in-app billing requests with the
 reserved product IDs. Also, you cannot specify the form of payment when you make a billing request
 with a reserved product ID. Figure 1 shows the checkout flow for the reserved item that has the
 product ID android.test.purchased.</p>
@@ -65,7 +65,7 @@
   <strong>Figure 1.</strong> Checkout flow for the special reserved item android.test.purchased.
 </p>
 
-<p>You do not need to list the reserved products in your application's product list. Android Market
+<p>You do not need to list the reserved products in your application's product list. Google Play
 already knows about the reserved product IDs. Also, you do not need to upload your application to
 the publisher site to perform static response tests with the reserved product IDs. You can simply
 install your application on a device, log into the device, and make billing requests using the
@@ -75,24 +75,24 @@
 
 <ul>
   <li><strong>android.test.purchased</strong>
-    <p>When you make an in-app billing request with this product ID, Android Market responds as
+    <p>When you make an in-app billing request with this product ID, Google Play responds as
     though you successfully purchased an item. The response includes a JSON string, which contains
     fake purchase information (for example, a fake order ID). In some cases, the JSON string is
     signed and the response includes the signature so you can test your signature verification
     implementation using these responses.</p>
   </li>
   <li><strong>android.test.canceled</strong>
-    <p>When you make an in-app billing request with this product ID Android Market responds as
+    <p>When you make an in-app billing request with this product ID Google Play responds as
     though the purchase was canceled. This can occur when an error is encountered in the order
     process, such as an invalid credit card, or when you cancel a user's order before it is
     charged.</p>
   </li>
   <li><strong>android.test.refunded</strong>
-    <p>When you make an in-app billing request with this product ID, Android Market responds as
-    though the purchase was refunded. Refunds cannot be initiated through Android Market's in-app
+    <p>When you make an in-app billing request with this product ID, Google Play responds as
+    though the purchase was refunded. Refunds cannot be initiated through Google Play's in-app
     billing service. Refunds must be initiated by you (the merchant). After you process a refund
     request through your Google Checkout account, a refund message is sent to your application by
-    Android Market. This occurs only when Android Market gets notification from Google Checkout that
+    Google Play. This occurs only when Google Play gets notification from Google Checkout that
     a refund has been made. For more information about refunds, see <a
     href="{@docRoot}guide/market/billing/billing_overview.html#billing-action-notify">Handling
     IN_APP_NOTIFY messages</a> and <a
@@ -100,7 +100,7 @@
     Pricing</a>.</p>
   </li>
   <li><strong>android.test.item_unavailable</strong>
-    <p>When you make an in-app billing request with this product ID, Android Market responds as
+    <p>When you make an in-app billing request with this product ID, Google Play responds as
     though the item being purchased was not listed in your application's product list.</p>
   </li>
 </ul>
@@ -185,20 +185,20 @@
     <p>You do not need to use a test account if you are testing only with the reserved product
     IDs.</p>
   </li>
-  <li><strong>Verify that your device is running a supported version of the Android Market
+  <li><strong>Verify that your device is running a supported version of the Google Play
   application or the MyApps application.</strong>
     <p>If your device is running Android 3.0, in-app billing requires version 5.0.12 (or higher) of
     the MyApps application. If your device is running any other version of Android, in-app billing
-    requires version 2.3.4 (or higher) of the Android Market application. To learn how to check the
-    version of the Android Market application, see <a
-    href="http://market.android.com/support/bin/answer.py?answer=190860">Updating Android
-    Market</a>.</p>
+    requires version 2.3.4 (or higher) of the Google Play application. To learn how to check the
+    version of the Google Play application, see <a
+    href="http://market.android.com/support/bin/answer.py?answer=190860">Updating Google
+    Play</a>.</p>
   </li>
   <li><strong>Run your application and purchase the reserved product IDs.</strong></li>
 </ol>
 
 <p class="note"><strong>Note</strong>: Making in-app billing requests with the reserved product IDs
-overrides the usual Android Market production system. When you send an in-app billing request for a
+overrides the usual Google Play production system. When you send an in-app billing request for a
 reserved product ID, the quality of service will not be comparable to the production
 environment.</p>
 
@@ -207,7 +207,7 @@
 <p>After you finish your static response testing, and you verify that signature verification is
 working in your application, you can test your in-app billing implementation by making actual in-app
 purchases. Testing real in-app purchases enables you to test the end-to-end in-app billing
-experience, including the actual responses from Android Market and the actual checkout flow that
+experience, including the actual responses from Google Play and the actual checkout flow that
 users will experience in your application.</p>
 
 <p class="note"><strong>Note</strong>: You do not need to publish your application to do end-to-end
@@ -215,7 +215,7 @@
 testing.</p>
 
 <p>To test your in-app billing implementation with actual in-app purchases, you will need to
-register at least one test account on the Android Market publisher site. You cannot use your
+register at least one test account on the Google Play publisher site. You cannot use your
 developer account to test the complete in-app purchase process because Google Checkout does not let
 you buy items from yourself. If you have not set up test accounts before, see <a
 href="{@docRoot}guide/market/billing/billing_admin.html#billing-testing-setup">Setting up test
@@ -237,7 +237,7 @@
     IDs; you only need to upload your application as a draft application. However, you must sign
     your application with your release key before you upload it as a draft application. Also, the
     version number of the uploaded application must match the version number of the application you
-    load to your device for testing. To learn how to upload an application to Android Market, see
+    load to your device for testing. To learn how to upload an application to Google Play, see
     <a href="http://market.android.com/support/bin/answer.py?answer=113469">Uploading
     applications</a>.</p>
   </li>
@@ -257,7 +257,7 @@
     <p>To perform end-to-end testing of in-app billing, the primary account on your device must be
     one of the <a
     href="{@docRoot}guide/market/billing/billing_admin.html#billing-testing-setup">test accounts</a>
-    that you registered on the Android Market site. If the primary account on your device is not a
+    that you registered on the Google Play site. If the primary account on your device is not a
     test account, you must do a factory reset of the device and then sign in with one of your test
     accounts. To perform a factory reset, do the following:</p>
     <ol>
@@ -269,14 +269,14 @@
       device setup process.</li>
     </ol>
   </li>
-  <li><strong>Verify that your device is running a supported version of the Android Market
+  <li><strong>Verify that your device is running a supported version of the Google Play
   application or the MyApps application.</strong>
     <p>If your device is running Android 3.0, in-app billing requires version 5.0.12 (or higher) of
     the MyApps application. If your device is running any other version of Android, in-app billing
-    requires version 2.3.4 (or higher) of the Android Market application. To learn how to check the
-    version of the Android Market application, see <a
-    href="http://market.android.com/support/bin/answer.py?answer=190860">Updating Android
-    Market</a>.</p>
+    requires version 2.3.4 (or higher) of the Google Play application. To learn how to check the
+    version of the Google Play application, see <a
+    href="http://market.android.com/support/bin/answer.py?answer=190860">Updating Google
+    Play</a>.</p>
   </li>
   <li><strong>Make in-app purchases in your application.</strong></li>
 </ol>
@@ -285,7 +285,7 @@
 do a factory reset, making sure you log on with your primary account first.</p>
 
 <p>When you are finished testing your in-app billing implementation, you are ready to
-publish your application on Android Market. You can follow the normal steps for <a
+publish your application on Google Play. You can follow the normal steps for <a
 href="{@docRoot}guide/publishing/preparing.html">preparing</a>, <a
 href="{@docRoot}guide/publishing/app-signing.html">signing</a>, and <a
 href="{@docRoot}guide/publishing/publishing.html">publishing your application</a>.
diff --git a/docs/html/guide/market/billing/index.jd b/docs/html/guide/market/billing/index.jd
index fdfa6fa..036761f 100755
--- a/docs/html/guide/market/billing/index.jd
+++ b/docs/html/guide/market/billing/index.jd
@@ -30,18 +30,18 @@
 </div>
 </div>
 
-<p>Android Market In-app Billing is an Android Market service that lets you sell digital content in
+<p>Google Play In-app Billing is a Google Play service that lets you sell digital content in
 your applications. You can use the service to sell a wide range of content, including downloadable
 content such as media files or photos, and virtual content such as game levels or potions.</p>
 
-<p>When you use Android Market's in-app billing service to sell an item, Android Market handles all
+<p>When you use Google Play's in-app billing service to sell an item, Google Play handles all
 checkout details so your application never has to directly process any financial transactions.
-Android Market uses the same checkout service that is used for application purchases, so your users
+Google Play uses the same checkout service that is used for application purchases, so your users
 experience a consistent and familiar purchase flow (see figure 1). Also, the transaction fee for
 in-app purchases is the same as the transaction fee for application purchases (30%).</p>
 
-<p>Any application that you publish through Android Market can implement in-app billing. No special
-account or registration is required other than an Android Market publisher account and a Google
+<p>Any application that you publish through Google Play can implement in-app billing. No special
+account or registration is required other than a Google Play app publisher account and a Google
 Checkout Merchant account. Also, because the service uses no dedicated framework APIs, you can add
 in-app billing to any application that uses a minimum API level of 4 or higher.</p>
 
@@ -59,11 +59,11 @@
 <img src="{@docRoot}images/billing_checkout_flow.png" height="382" id="figure1" />
 <p class="img-caption">
   <strong>Figure 1.</strong> Applications initiate in-app billing requests through their own UI
-  (first screen). Android Market responds to the request by providing the checkout user interface
+  (first screen). Google Play responds to the request by providing the checkout user interface
   (middle screen). When checkout is complete, the application resumes.
 </p>
 
-<p>To learn more about Android Market's in-app billing service and start integrating it into your
+<p>To learn more about Google Play's in-app billing service and start integrating it into your
 applications, read the following documents:</p>
 
 <dl>
@@ -88,7 +88,7 @@
     <dd>Learn how to set up your product list, register test accounts, and handle refunds.</dd>
   <dt><strong><a href="{@docRoot}guide/market/billing/billing_reference.html">In-app Billing
   Reference</a></strong></dt>
-    <dd>Get detailed information about Android Market response codes and the in-app billing
+    <dd>Get detailed information about Google Play response codes and the in-app billing
     interface.</dd>
 </dl>
 
diff --git a/docs/html/guide/market/expansion-files.jd b/docs/html/guide/market/expansion-files.jd
new file mode 100644
index 0000000..01acb33
--- /dev/null
+++ b/docs/html/guide/market/expansion-files.jd
@@ -0,0 +1,1274 @@
+page.title=APK Expansion Files
+@jd:body
+
+
+<div id="qv-wrapper">
+<div id="qv">
+<h2>Quickview</h2>
+<ul>
+  <li>Recommended for most apps that exceed the 50MB APK limit</li>
+  <li>You can provide up to 4GB of additional data for each APK</li>
+  <li>Google Play hosts and serves the expansion files at no charge</li>
+  <li>The files can be any file type you want and are saved to the device's shared storage</li>
+</ul>
+
+<h2>In this document</h2>
+<ol>
+  <li><a href="#Overview">Overview</a>
+    <ol>
+      <li><a href="#Filename">File name format</a></li>
+      <li><a href="#StorageLocation">Storage location</a></li>
+      <li><a href="#DownloadProcess">Download process</a></li>
+      <li><a href="#Checklist">Development checklist</a></li>
+    </ol>
+  </li>
+  <li><a href="#Rules">Rules and Limitations</a></li>
+  <li><a href="#Downloading">Downloading the Expansion Files</a>
+    <ol>
+      <li><a href="#AboutLibraries">About the Downloader Library</a></li>
+      <li><a href="#Preparing">Preparing to use the Downloader Library</a></li>
+      <li><a href="#Permissions">Declaring user permissions</a></li>
+      <li><a href="#DownloaderService">Implementing the downloader service</a></li>
+      <li><a href="#AlarmReceiver">Implementing the alarm receiver</a></li>
+      <li><a href="#Download">Starting the download</a></li>
+      <li><a href="#Progress">Receiving download progress</a></li>
+    </ol>
+  </li>
+  <li><a href="#ExpansionPolicy">Using APKExpansionPolicy</a></li>
+  <li><a href="#ReadingTheFile">Reading the Expansion File</a>
+    <ol>
+      <li><a href="#GettingFilenames">Getting the file names</a></li>
+      <li><a href="#ZipLib">Using the APK Expansion Zip Library</a></li>
+    </ol>
+  </li>
+  <li><a href="#Testing">Testing Your Expansion Files</a>
+    <ol>
+      <li><a href="#TestingReading">Testing file reads</a></li>
+      <li><a href="#TestingReading">Testing file downloads</a></li>
+    </ol>
+  </li>
+  <li><a href="#Updating">Updating Your Application</a></li>
+</ol>
+
+<h2>See also</h2>
+<ol>
+  <li><a href="{@docRoot}guide/market/licensing/index.html">Application Licensing</a></li>
+  <li><a href="{@docRoot}guide/market/publishing/multiple-apks.html">Multiple
+APK Support</a></li>
+</ol>
+</div>
+</div>
+
+
+
+<p>Google Play currently requires that your APK file be no more than 50MB. For most
+applications, this is plenty of space for all the application's code and assets.
+However, some apps need more space for high-fidelity graphics, media files, or other large assets.
+Previously, if your app exceeded 50MB, you had to host and download the additional resources
+yourself when the user opens the app. Hosting and serving the extra files can be costly, and the
+user experience is often less than ideal. To make this process easier for you and more pleasant
+for users, Google Play allows you to attach two large expansion files that supplement your
+APK.</p>
+
+<p>Google Play hosts the expansion files for your application and serves them to the device at
+no cost to you. The expansion files are saved to the device's shared storage location (the
+SD card or USB-mountable partition; also known as the "external" storage) where your app can access
+them. On most devices, Google Play downloads the expansion file(s) at the same time it
+downloads the APK, so your application has everything it needs when the user opens it for the
+first time. In some cases, however, your application must download the files from Google Play
+when your application starts.</p>
+
+
+
+<h2 id="Overview">Overview</h2>
+
+<p>Each time you upload an APK using the Google Play Android Developer Console, you have the option to
+add one or two expansion files to the APK. Each file can be up to 2GB and it can be any format you
+choose, but we recommend you use a compressed file to conserve bandwidth during the download.
+Conceptually, each expansion file plays a different role:</p>
+
+<ul>
+  <li>The <strong>main</strong> expansion file is the
+primary expansion file for additional resources required by your application.</li>
+  <li>The <strong>patch</strong> expansion file is optional and intended for small updates to the
+main expansion file.</li>
+</ul>
+
+<p>While you can use the two expansion files any way you wish, we recommend that the main
+expansion file deliver the primary assets and should rarely if ever updated; the patch expansion
+file should be smaller and serve as a “patch carrier,” getting updated with each major
+release or as necessary.</p>
+
+<p>However, even if your application update requires only a new patch expansion file, you still must
+upload a new APK with an updated <a
+href="{@docRoot}guide/topics/manifest/manifest-element.html#vcode">{@code
+versionCode}</a> in the manifest. (The
+Developer Console does not allow you to upload an expansion file to an existing APK.)</p>
+
+<p class="note"><strong>Note:</strong> The patch expansion file is semantically the same as the
+main expansion file&mdash;you can use each file any way you want. The system does
+not use the patch expansion file to perform patching for your app. You must perform patching
+yourself or be able to distinguish between the two files.</p>
+
+
+
+<h3 id="Filename">File name format</h3>
+
+<p>Each expansion file you upload can be any format you choose (ZIP, PDF, MP4, etc.). Regardless of
+the file type, Google Play considers them opaque binary blobs and renames the files
+using the following scheme:</p>
+
+<pre class="classic no-pretty-print">
+[main|patch].&lt;expansion-version&gt;.&lt;package-name&gt;.obb
+</pre>
+
+<p>There are three components to this scheme:</p>
+
+<dl>
+  <dt>{@code main} or {@code patch}</dt>
+    <dd>Specifies whether the file is the main or patch expansion file. There can be
+only one main file and one patch file for each APK.</dd>
+  <dt>{@code &lt;expansion-version&gt;}</dt>
+    <dd>This is an integer that matches the version code of the APK with which the expansion is
+<em>first</em> associated (it matches the application's <a
+href="{@docRoot}guide/topics/manifest/manifest-element.html#vcode">{@code android:versionCode}</a>
+value).
+    <p>"First" is emphasized because although the Developer Console allows you to
+re-use an uploaded expansion file with a new APK, the expansion file's name does not change&mdash;it
+retains the version applied to it when you first uploaded the file.</p></dd>
+  <dt>{@code &lt;package-name&gt;}</dt> 
+    <dd>Your application's Java-style package name.</dd>
+</dl>
+
+<p>For example, suppose your APK version is 314159 and your package name is com.example.app. If you
+upload a main expansion file, the file is renamed to:</p>
+<pre class="classic no-pretty-print">main.314159.com.example.app.obb</pre>
+
+
+<h3 id="StorageLocation">Storage location</h3>
+
+<p>When Google Play downloads your expansion files to a device, it saves them to the system's
+shared storage location. To ensure proper behavior, you must not delete, move, or rename the
+expansion files. In the event that your application must perform the download from Google Play
+itself, you must save the files to the exact same location.</p>
+
+<p>The specific location for your expansion files is:</p>
+
+<pre class="classic no-pretty-print">
+&lt;shared-storage&gt;/Android/obb/&lt;package-name&gt;/
+</pre>
+
+<ul>
+  <li>{@code &lt;shared-storage&gt;} is the path to the shared storage space, available from
+{@link android.os.Environment#getExternalStorageDirectory()}.</li>
+  <li>{@code &lt;package-name&gt;} is your application's Java-style package name, available
+from {@link android.content.Context#getPackageName()}.</li>
+</ul>
+
+<p>For each application, there are never more than two expansion files in this directory.
+One is the main expansion file and the other is the patch expansion file (if necessary). Previous
+versions are overwritten when you update your application with new expansion files.</p>
+
+<p>If you must unpack the contents of your expansion files, <strong>do not</strong> delete the
+{@code .obb} expansion files afterwards and <strong>do not</strong> save the unpacked data
+in the same directory. You should save your unpacked files in the directory
+specified by {@link android.content.Context#getExternalFilesDir getExternalFilesDir()}. However,
+if possible, it's best if you use an expansion file format that allows you to read directly from
+the file instead of requiring you to unpack the data. For example, we've provided a library
+project called the <a href="#ZipLib">APK Expansion Zip Library</a> that reads your data directly
+from the ZIP file.</p>
+
+<p class="note"><strong>Note:</strong> Unlike APK files, any files saved on the shared storage can
+be read by the user and other applications.</p>
+
+<p class="note"><strong>Tip:</strong> If you're packaging media files into a ZIP, you can use media
+playback calls on the files with offset and length controls (such as {@link
+android.media.MediaPlayer#setDataSource(FileDescriptor,long,long) MediaPlayer.setDataSource()} and
+{@link android.media.SoundPool#load(FileDescriptor,long,long,int) SoundPool.load()}) without the
+need to unpack your ZIP. In order for this to work, you must not perform additional compression on
+the media files when creating the ZIP packages. For example, when using the <code>zip</code> tool,
+you should use the <code>-n</code> option to specify the file suffixes that should not be
+compressed: <br/>
+<code>zip -n .mp4;.ogg main_expansion media_files</code></p>
+
+
+<h3 id="DownloadProcess">Download process</h3>
+
+<p>Most of the time, Google Play downloads and saves your expansion files at the same time it
+downloads the APK to the device. However, in some cases Google Play
+cannot download the expansion files or the user might have deleted previously downloaded expansion
+files. To handle these situations, your app must be able to download the files
+itself when the main activity starts, using a URL provided by Google Play.</p>
+
+<p>The download process from a high level looks like this:</p>
+
+<ol>
+  <li>User selects to install your app from Google Play.</li>
+  <li>If Google Play is able to download the expansion files (which is the case for most
+devices), it downloads them along with the APK.
+     <p>If Google Play is unable to download the expansion files, it downloads the
+APK only.</p>
+  </li>
+  <li>When the user launches your application, your app must check whether the expansion files are
+already saved on the device.
+    <ol>
+      <li>If yes, your app is ready to go.</li>
+      <li>If no, your app must download the expansion files over HTTP from Google Play. Your app
+must send a request to the Google Play client using the Google Play's <a
+href="{@docRoot}guide/market/licensing/index.html">Application Licensing</a> service, which
+responds with the name, file size, and URL for each expansion file. With this information, you then
+download the files and save them to the proper <a href="#StorageLocation">storage location</a>.</li>
+    </ol>
+  </li>
+</ol>
+
+<p class="caution"><strong>Caution:</strong> It is critical that you include the necessary code to
+download the expansion files from Google Play in the event that the files are not already on the
+device when your application starts. As discussed in the following section about <a
+href="#Downloading">Downloading the Expansion Files</a>, we've made a library available to you that
+greatly simplifies this process and performs the download from a service with a minimal amount of
+code from you.</p>
+
+
+
+
+<h3 id="Checklist">Development checklist</h3>
+
+<p>Here's a summary of the tasks you should perform to use expansion files with your
+application:</p>
+
+<ol>
+  <li>First determine whether your application absolutely requires more than 50MB per installation.
+Space is precious and you should keep your total application size as small as possible. If your app
+uses more than 50MB in order to provide multiple versions of your graphic assets for multiple screen
+densities, consider instead publishing <a
+href="{@docRoot}guide/market/publishing/multiple-apks.html">multiple APKs</a> in which each APK
+contains only the assets required for the screens that it targets.</li>
+  <li>Determine which application resources to separate from your APK and package them in a
+file to use as the main expansion file.
+    <p>Normally, you should only use the second patch expansion file when performing updates to
+the main expansion file. However, if your resources exceed the 2GB limit for the main
+expansion file, you can use the patch file for the rest of your assets.</p>
+  </li>
+  <li>Develop your application such that it uses the resources from your expansion files in the
+device's <a href="#StorageLocation">shared storage location</a>.
+    <p>Remember that you must not delete, move, or rename the expansion files.</p>
+    <p>If your application doesn't demand a specific format, we suggest you create ZIP files for 
+your expansion files, then read them using the <a href="#ZipLib">APK Expansion Zip
+Library</a>.</p>
+  </li>
+  <li>Add logic to your application's main activity that checks whether the expansion files
+are on the device upon start-up. If the files are not on the device, use Google Play's <a
+href="{@docRoot}guide/market/licensing/index.html">Application Licensing</a> service to request URLs
+for the expansion files, then download and save them.
+    <p>To greatly reduce the amount of code you must write and ensure a good user experience
+during the download, we recommend you use the <a href="AboutLibraries">Downloader
+Library</a> to implement your download behavior.</p>
+    <p>If you build your own download service instead of using the library, be aware that you
+must not change the name of the expansion files and must save them to the proper
+<a href="#StorageLocation">storage location</a>.</p></li>
+</ol>
+
+<p>Once you've finished your application development, follow the guide to <a href="#Testing">Testing
+Your Expansion Files</a>.</p>
+
+
+
+
+
+
+<h2 id="Rules">Rules and Limitations</h2>
+
+<p>Adding APK expansion files is a feature available when you upload your application using the
+Developer Console. When uploading your application for the first time or updating an
+application that uses expansion files, you must be aware of the following rules and limitations:</p>
+
+<ol type="I">
+  <li>Each expansion file can be no more than 2GB.</li>
+  <li>In order to download your expansion files from Google Play, <strong>the user must have
+acquired your application from Google Play</strong>. Google Play will not
+provide the URLs for your expansion files if the application was installed by other means.</li>
+  <li>When performing the download from within your application, the URL that Google Play
+provides for each file is unique for every download and each one expires shortly after it is given
+to your application.</li>
+  <li>If you update your application with a new APK or upload <a
+href="{@docRoot}guide/market/publishing/multiple-apks.html">multiple APKs</a> for the same
+application, you can select expansion files that you've uploaded for a previous APK. <strong>The
+expansion file's name does not change</strong>&mdash;it retains the version received by the APK to
+which the file was originally associated.</li>
+  <li>If you use expansion files in combination with <a
+href="{@docRoot}guide/market/publishing/multiple-apks.html">multiple APKs</a> in order to
+provide different expansion files for different devices, you still must upload separate APKs
+for each device in order to provide a unique  <a
+href="{@docRoot}guide/topics/manifest/manifest-element.html#vcode">{@code versionCode}</a>
+value and declare different <a href="{@docRoot}guide/appendix/market-filters.html">filters</a> for
+each APK.</li>
+  <li>You cannot issue an update to your application by changing the expansion files
+alone&mdash;<strong>you must upload a new APK</strong> to update your app. If your changes only
+concern the assets in your expansion files, you can update your APK simply by changing the <a
+href="{@docRoot}guide/topics/manifest/manifest-element.html#vcode">{@code versionCode}</a> (and
+perhaps also the <a href="{@docRoot}guide/topics/manifest/manifest-element.html#vname">{@code
+versionName}</a>).</p></li>
+  <li><strong>Do not save other data into your <code>obb/</code>
+directory</strong>. If you must unpack some data, save it into the location specified by {@link
+android.content.Context#getExternalFilesDir getExternalFilesDir()}.</li>
+  <li><strong>Do not delete or rename the {@code .obb} expansion file</strong> (unless you're
+performing an update). Doing so will cause Google Play (or your app itself) to repeatedly
+download the expansion file.</li>
+  <li>When updating an expansion file manually, you must delete the previous expansion file.</li>
+</ol>
+
+
+
+
+
+
+
+
+
+<h2 id="Downloading">Downloading the Expansion Files</h2>
+
+<p>In most cases, Google Play downloads and saves your expansion files to the device at the same
+time it installs or updates the APK. This way, the expansion files are available when your
+application launches for the first time. However, in some cases your app must download the
+expansion files itself by requesting them from a URL provided to you in a response
+from Google Play's <a
+href="{@docRoot}guide/market/licensing/index.html">Application Licensing</a> service.</p>
+
+<p>The basic logic you need to download your expansion files is the following:</p>
+
+<ol>
+  <li>When your application starts, look for the expansion files on the <a
+href="#StorageLocation">shared storage location</a> (in the
+<code>Android/obb/&lt;package-name&gt;/</code> directory).
+    <ol type="a">
+      <li>If the expansion files are there, you're all set and your application can continue.</li>
+      <li>If the expansion files are <em>not</em> there:
+        <ol>
+          <li>Perform a request using Google Play's <a
+href="{@docRoot}guide/market/licensing/index.html">Application Licensing</a> to get your
+app's expansion file names, sizes, and URLs.</li> 
+          <li>Use the URLs provided by Google Play to download the expansion files and save
+the expansion files. You <strong>must</strong> save the files to the <a
+href="#StorageLocation">shared storage location</a>
+(<code>Android/obb/&lt;package-name&gt;/</code>) and use the exact file name provided
+by Google Play's response.
+            <p class="note"><strong>Note:</strong> The URL that Google Play provides for your
+expansion files is unique for every download and each one expires shortly after it is given to
+your application.</p>
+          </li>
+        </ol>
+      </li>
+    </ol>
+  </li>
+</ol>
+
+
+<p>If your application is free (not a paid app), then you probably haven't used the <a
+href="{@docRoot}guide/market/licensing/index.html">Application Licensing</a> service. It's primarily
+designed for you to enforce
+licensing policies for your application and ensure that the user has the right to
+use your app (he or she rightfully paid for it on Google Play). In order to facilitate the
+expansion file functionality, the licensing service has been enhanced to provide a response
+to your application that includes the URL of your application's expansion files that are hosted
+on Google Play. So, even if your application is free for users, you need to include the
+License Verification Library (LVL) to use APK expansion files. Of course, if your application
+is free, you don't need to enforce license verification&mdash;you simply need the
+library to perform the request that returns the URL of your expansion files.</p>
+
+<p class="note"><strong>Note:</strong> Whether your application is free or not, Google Play
+returns the expansion file URLs only if the user acquired your application from Google Play.</p>
+
+<p>In addition to the LVL, you need a set of code that downloads the expansion files
+over an HTTP connection and saves them to the proper location on the device's shared storage.
+As you build this procedure into your application, there are several issues you should take into
+consideration:</p>
+
+<ul>
+  <li>The device might not have enough space for the expansion files, so you should check
+before beginning the download and warn the user if there's not enough space.</li>
+  <li>File downloads should occur in a background service in order to avoid blocking the user
+interaction and allow the user to leave your app while the download completes.</li>
+  <li>A variety of errors might occur during the request and download that you must
+gracefully handle.</li>
+  <li>Network connectivity can change during the download, so you should handle such changes and
+if interrupted, resume the download when possible.</li>
+  <li>While the download occurs in the background, you should provide a notification that
+indicates the download progress, notifies the user when it's done, and takes the user back to
+your application when selected.</li>
+</ul>
+
+
+<p>To simplify this work for you, we've built the <a href="#AboutLibraries">Downloader Library</a>,
+which requests the expansion file URLs through the licensing service, downloads the expansion files,
+performs all of the tasks listed above, and even allows your activity to pause and resume the
+download. By adding the Downloader Library and a few code hooks to your application, almost all the
+work to download the expansion files is already coded for you. As such, in order to provide the best
+user experience with minimal effort on your behalf, we recommend you use the Downloader Library to
+download your expansion files. The information in the following sections explain how to integrate
+the library into your application.</p>
+
+<p>If you'd rather develop your own solution to download the expansion files using the Google
+Play URLs, you must follow the <a href="{@docRoot}guide/market/licensing/index.html">Application
+Licensing</a> documentation to perform a license request, then retrieve the expansion file names,
+sizes, and URLs from the response extras. You should use the <a href="#ExpansionPolicy">{@code
+APKExpansionPolicy}</a> class (included in the License Verification Library) as your licensing
+policy, which captures the expansion file names, sizes, and URLs from the licensing service..</p>
+
+
+
+<h3 id="AboutLibraries">About the Downloader Library</h3>
+
+<p>To use APK expansion files with your application and provide the best user experience with
+minimal effort on your behalf, we recommend you use the Downloader Library that's included in the
+Google Market Apk Expansion package. This library downloads your expansion files in a
+background service, shows a user notification with the download status, handles network
+connectivity loss, resumes the download when possible, and more.</p>
+
+<p>To implement expansion file downloads using the Downloader Library, all you need to do is:</p>
+
+<ul>
+  <li>Extend a special {@link android.app.Service} subclass and {@link
+android.content.BroadcastReceiver} subclass that each require just a few
+lines of code from you.</li>
+  <li>Add some logic to your main activity that checks whether the expansion files have
+already been downloaded and, if not, invokes the download process and displays a
+progress UI.</li>
+  <li>Implement a callback interface with a few methods in your main activity that
+receives updates about the download progress.</li>
+</ul>
+
+<p>The following sections explain how to set up your app using the Downloader Library.</p>
+
+
+<h3 id="Preparing">Preparing to use the Downloader Library</h3>
+
+<p>To use the Downloader Library, you need to
+download two packages from the SDK Manager and add the appropriate libraries to your
+application.</p>
+
+<p>First, open the <a href="{@docRoot}sdk/adding-components.html">Android SDK Manager</a>, expand
+<em>Extras</em> and download:</p>
+<ul>
+  <li><em>Google Market Licensing package</em></li>
+  <li><em>Google Market Apk Expansion package</em></li>
+</ul>
+
+<p>If you're using Eclipse, create a project for each library and add it to your app:</p>
+<ol>
+  <li>Create a new Library Project for the License Verification Library and Downloader
+Library. For each library:
+    <ol>
+      <li>Begin a new Android project.</li>
+      <li>Select <strong>Create project from existing
+source</strong> and choose the library from the {@code &lt;sdk&gt;/extras/google/} directory
+({@code market_licensing/} for the License Verification Library or {@code
+market_apk_expansion/downloader_library/} for the Downloader Library).</li>
+      <li>Specify a <em>Project Name</em> such as "Google Play License Library" and "Google Play
+Downloader
+Library"</li>
+      <li>Click <strong>Finish</strong>.</li>
+    </ol>
+<p class="note"><strong>Note:</strong> The Downloader Library depends on the License
+Verification Library. Be sure to add the License
+Verification Library to the Downloader Library's project properties (same process as
+steps 2 and 3 below).</p>
+  </li>
+  <li>Right-click the Android project in which you want to use APK expansion files and
+select <strong>Properties</strong>.</li>
+  <li>In the <em>Library</em> panel, click <strong>Add</strong> to select and add each of the
+libraries to your application.</li>
+</ol>
+
+<p>Or, from a command line, update your project to include the libraries:</p>
+<ol>
+  <li>Change directories to the <code>&lt;sdk&gt;/tools/</code> directory.</li>
+  <li>Execute <code>android update project</code> with the {@code --library} option to add both the
+LVL and the Downloader Library to your project. For example:
+<pre class="no-pretty-print">
+android update project --path ~/Android/MyApp \
+--library ~/android_sdk/extras/google/market_licensing \
+--library ~/android_sdk/extras/google/market_apk_expansion/downloader_library
+</pre>
+  </li>
+</ol>
+
+<p>With both the License Verification Library and Downloader Library added to your
+application, you'll be able to quickly integrate the ability to download expansion files from
+Google Play. The format that you choose for the expansion files and how you read them
+from the shared storage is a separate implementation that you should consider based on your
+application needs.</p>
+
+<p class="note"><strong>Tip:</strong> The Apk Expansion package includes a sample
+application
+that shows how to use the Downloader Library in an app. The sample uses a third library
+available in the Apk Expansion package called the APK Expansion Zip Library. If
+you plan on
+using ZIP files for your expansion files, we suggest you also add the APK Expansion Zip Library to
+your application. For more information, see the section below
+about <a href="#ZipLib">Using the APK Expansion Zip Library</a>.</p>
+
+
+
+<h3 id="Permissions">Declaring user permissions</h3>
+
+<p>In order to download the expansion files, the Downloader Library
+requires several permissions that you must declare in your application's manifest file. They
+are:</p>
+
+<pre>
+&lt;manifest ...>
+    &lt;!-- Required to access Google Play Licensing -->
+    &lt;uses-permission android:name="com.android.vending.CHECK_LICENSE" />
+
+    &lt;!-- Required to download files from Google Play -->
+    &lt;uses-permission android:name="android.permission.INTERNET" />
+
+    &lt;!-- Required to keep CPU alive while downloading files (NOT to keep screen awake) -->
+    &lt;uses-permission android:name="android.permission.WAKE_LOCK" />
+
+    &lt;!-- Required to poll the state of the network connection and respond to changes -->
+    &lt;uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
+
+    &lt;!-- Required to check whether Wi-Fi is enabled -->
+    &lt;uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
+
+    &lt;!-- Required to read and write the expansion files on shared storage -->
+    &lt;uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+    ...
+&lt;/manifest>
+</pre>
+
+<p class="note"><strong>Note:</strong> By default, the Downloader Library requires API
+level 4, but the APK Expansion Zip Library requires API level 5.</p>
+
+
+<h3 id="DownloaderService">Implementing the downloader service</h3>
+
+<p>In order to perform downloads in the background, the Downloader Library provides its
+own {@link android.app.Service} subclass called {@code DownloaderService} that you should extend. In
+addition to downloading the expansion files for you, the {@code DownloaderService} also:</p>
+
+<ul>
+  <li>Registers a {@link android.content.BroadcastReceiver} that listens for changes to the
+device's network connectivity (the {@link android.net.ConnectivityManager#CONNECTIVITY_ACTION}
+broadcast) in order to pause the download when necessary (such as due to connectivity loss) and
+resume the download when possible (connectivity is acquired).</li>
+  <li>Schedules an {@link android.app.AlarmManager#RTC_WAKEUP} alarm to retry the download for
+cases in which the service gets killed.</li>
+  <li>Builds a custom {@link android.app.Notification} that displays the download progress and
+any errors or state changes.</li>
+  <li>Allows your application to manually pause and resume the download.</li>
+  <li>Verifies that the shared storage is mounted and available, that the files don't already exist,
+and that there is enough space, all before downloading the expansion files. Then notifies the user
+if any of these are not true.</li>
+</ul>
+
+<p>All you need to do is create a class in your application that extends the {@code
+DownloaderService} class and override three methods to provide specific application details:</p>
+
+<dl>
+  <dt>{@code getPublicKey()}</dt>
+    <dd>This must return a string that is the Base64-encoded RSA public key for your publisher
+account, available from the profile page on the Developer Console (see <a
+href="{@docRoot}guide/market/licensing/setting-up.html">Setting Up for Licensing</a>).</dd>
+  <dt>{@code getSALT()}</dt>
+    <dd>This must return an array of random bytes that the licensing {@code Policy} uses to
+create an <a
+href="{@docRoot}guide/market/licensing/adding-licensing.html#impl-Obfuscator">{@code
+Obfuscator}</a>. The salt ensures that your obfuscated {@link android.content.SharedPreferences}
+file in which your licensing data is saved will be unique and non-discoverable.</dd>
+  <dt>{@code getAlarmReceiverClassName()}</dt>
+    <dd>This must return the class name of the {@link android.content.BroadcastReceiver} in
+your application that should receive the alarm indicating that the download should be
+restarted (which might happen if the downloader service unexpectedly stops).</dd>
+</dl>
+
+<p>For example, here's a complete implementation of {@code DownloaderService}:</p>
+
+<pre>
+public class SampleDownloaderService extends DownloaderService {
+    // You must use the public key belonging to your publisher account
+    public static final String BASE64_PUBLIC_KEY = "YourLVLKey";
+    // You should also modify this salt
+    public static final byte[] SALT = new byte[] { 1, 42, -12, -1, 54, 98,
+            -100, -12, 43, 2, -8, -4, 9, 5, -106, -107, -33, 45, -1, 84
+    };
+
+    &#64;Override
+    public String getPublicKey() {
+        return BASE64_PUBLIC_KEY;
+    }
+
+    &#64;Override
+    public byte[] getSALT() {
+        return SALT;
+    }
+
+    &#64;Override
+    public String getAlarmReceiverClassName() {
+        return SampleAlarmReceiver.class.getName();
+    }
+}
+</pre>
+
+<p class="caution"><strong>Notice:</strong> You must update the {@code BASE64_PUBLIC_KEY} value
+to be the public key belonging to your publisher account. You can find the key in the Developer
+Console under your profile information. This is necessary even when testing
+your downloads.</p>
+
+<p>Remember to declare the service in your manifest file:</p>
+<pre>
+&lt;application ...>
+    &lt;service android:name=".SampleDownloaderService" />
+    ...
+&lt;/application>
+</pre>
+
+
+
+<h3 id="AlarmReceiver">Implementing the alarm receiver</h3>
+
+<p>In order to monitor the progress of the file downloads and restart the download if necessary, the
+{@code DownloaderService} schedules an {@link android.app.AlarmManager#RTC_WAKEUP} alarm that
+delivers an {@link android.content.Intent} to a {@link android.content.BroadcastReceiver} in your
+application. You must define the {@link android.content.BroadcastReceiver} to call an API
+from the Downloader Library that checks the status of the download and restarts
+it if necessary.</p>
+
+<p>You simply need to override the {@link android.content.BroadcastReceiver#onReceive
+onReceive()} method to call {@code
+DownloaderClientMarshaller.startDownloadServiceIfRequired()}.</p>
+
+<p>For example:</p>
+
+<pre>
+public class SampleAlarmReceiver extends BroadcastReceiver {
+    &#64;Override
+    public void onReceive(Context context, Intent intent) {
+        try {
+            DownloaderClientMarshaller.startDownloadServiceIfRequired(context, intent,
+                    SampleDownloaderService.class);
+        } catch (NameNotFoundException e) {
+            e.printStackTrace();
+        }      
+    }
+}
+</pre>
+
+<p>Notice that this is the class for which you must return the name
+in your service's {@code getAlarmReceiverClassName()} method (see the previous section).</p>
+
+<p>Remember to declare the receiver in your manifest file:</p>
+<pre>
+&lt;application ...>
+    &lt;receiver android:name=".SampleAlarmReceiver" />
+    ...
+&lt;/application>
+</pre>
+
+
+
+<h3 id="Download">Starting the download</h3>
+
+<p>The main activity in your application (the one started by your launcher icon) is
+responsible for verifying whether the expansion files are already on the device and initiating
+the download if they are not.</p>
+
+<p>Starting the download using the Downloader Library requires the following
+procedures:</p>
+
+<ol>
+  <li>Check whether the files have been downloaded.
+    <p>The Downloader Library includes some APIs in the {@code Helper} class to
+help with this process:</p>
+  <ul>
+    <li>{@code getExtendedAPKFileName(Context, c, boolean mainFile, int
+versionCode)}</li>
+    <li>{@code doesFileExist(Context c, String fileName, long fileSize)}</li>
+  </ul>
+    <p>For example, the sample app provided in the Apk Expansion package calls the
+following method in the activity's {@link android.app.Activity#onCreate onCreate()} method to check
+whether the expansion files already exist on the device:</p>
+<pre>
+boolean expansionFilesDelivered() {
+    for (XAPKFile xf : xAPKS) {
+        String fileName = Helpers.getExpansionAPKFileName(this, xf.mIsBase, xf.mFileVersion);
+        if (!Helpers.doesFileExist(this, fileName, xf.mFileSize, false))
+            return false;
+    }
+    return true;
+}        
+</pre>
+    <p>In this case, each {@code XAPKFile} object holds the version number and file size of a known
+expansion file and a boolean as to whether it's the main expansion file. (See the sample
+application's {@code SampleDownloaderActivity} class for details.)</p>
+    <p>If this method returns false, then the application must begin the download.</p>
+  </li>
+  <li>Start the download by calling the static method {@code
+DownloaderClientMarshaller.startDownloadServiceIfRequired(Context c, PendingIntent
+notificationClient, Class&lt;?> serviceClass)}.
+    <p>The method takes the following parameters:</p>
+    <ul>
+      <li><code>context</code>: Your application's {@link android.content.Context}.</li>
+      <li><code>notificationClient</code>: A {@link android.app.PendingIntent} to start your main
+activity. This is used in the {@link android.app.Notification} that the {@code DownloaderService}
+creates to show the download progress. When the user selects the notification, the system
+invokes the {@link android.app.PendingIntent} you supply here and should open the activity
+that shows the download progress (usually the same activity that started the download).</li>
+      <li><code>serviceClass</code>: The {@link java.lang.Class} object for your implementation of
+{@code DownloaderService}, required to start the service and begin the download if necessary.</li>
+    </ul>
+    <p>The method returns an integer that indicates
+whether or not the download is required. Possible values are:</p>
+    <ul>
+      <li>{@code NO_DOWNLOAD_REQUIRED}: Returned if the files already
+exist or a download is already in progress.</li>
+      <li>{@code LVL_CHECK_REQUIRED}: Returned if a license verification is
+required in order to acquire the expansion file URLs.</li>
+      <li>{@code DOWNLOAD_REQUIRED}: Returned if the expansion file URLs are already known,
+but have not been downloaded.</li>
+    </ul>
+    <p>The behavior for {@code LVL_CHECK_REQUIRED} and {@code DOWNLOAD_REQUIRED} are essentially the
+same and you normally don't need to be concerned about them. In your main activity that calls {@code
+startDownloadServiceIfRequired()}, you can simply check whether or not the response is {@code
+NO_DOWNLOAD_REQUIRED}. If the response is anything <em>other than</em> {@code NO_DOWNLOAD_REQUIRED},
+the Downloader Library begins the download and you should update your activity UI to
+display the download progress (see the next step). If the response <em>is</em> {@code
+NO_DOWNLOAD_REQUIRED}, then the files are available and your application can start.</p>
+    <p>For example:</p>
+<pre>
+&#64;Override
+public void onCreate(Bundle savedInstanceState) {
+    // Check if expansion files are available before going any further
+    if (!expansionFilesDelivered()) {
+        // Build an Intent to start this activity from the Notification
+        Intent notifierIntent = new Intent(this, MainActivity.getClass());
+        notifierIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
+                                Intent.FLAG_ACTIVITY_CLEAR_TOP);
+        ...
+        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,
+                notifierIntent, PendingIntent.FLAG_UPDATE_CURRENT);
+        
+        // Start the download service (if required)
+        int startResult = DownloaderClientMarshaller.startDownloadServiceIfRequired(this,
+                        pendingIntent, SampleDownloaderService.class);
+        // If download has started, initialize this activity to show download progress
+        if (startResult != DownloaderClientMarshaller.NO_DOWNLOAD_REQUIRED) {
+            // This is where you do set up to display the download progress (next step)
+            ...
+            return;
+        } // If the download wasn't necessary, fall through to start the app
+    }
+    startApp(); // Expansion files are available, start the app
+}
+</pre>
+  </li>
+  <li>When the {@code startDownloadServiceIfRequired()} method returns anything <em>other
+than</em> {@code NO_DOWNLOAD_REQUIRED}, create an instance of {@code IStub} by
+calling {@code DownloaderClientMarshaller.CreateStub(IDownloaderClient client, Class&lt;?>
+downloaderService)}. The {@code IStub} provides a binding between your activity to the downloader
+service such that your activity receives callbacks about the download progress.
+    <p>In order to instantiate your {@code IStub} by calling {@code CreateStub()}, you must pass it
+an implementation of the {@code IDownloaderClient} interface and your {@code DownloaderService}
+implementation. The next section about <a href="#Progress">Receiving download progress</a> discusses
+the {@code IDownloaderClient} interface, which you should usually implement in your {@link
+android.app.Activity} class so you can update the activity UI when the download state changes.</p>
+    <p>We recommend that you call {@code
+CreateStub()} to instantiate your {@code IStub} during your activity's {@link
+android.app.Activity#onCreate onCreate()} method, after {@code startDownloadServiceIfRequired()}
+starts the download. </p>
+    <p>For example, in the previous code sample for {@link android.app.Activity#onCreate
+onCreate()}, you can respond to the {@code startDownloadServiceIfRequired()} result like this:</p>
+<pre>
+        // Start the download service (if required)
+        int startResult = DownloaderClientMarshaller.startDownloadServiceIfRequired(this,
+                        pendingIntent, SampleDownloaderService.class);
+        // If download has started, initialize activity to show progress
+        if (startResult != DownloaderClientMarshaller.NO_DOWNLOAD_REQUIRED) {
+            // Instantiate a member instance of IStub
+            mDownloaderClientStub = DownloaderClientMarshaller.CreateStub(this,
+                    SampleDownloaderService.class);
+            // Inflate layout that shows download progress
+            setContentView(R.layout.downloader_ui);
+            return;
+        }
+</pre>
+
+    <p>After the {@link android.app.Activity#onCreate onCreate()} method returns, your activity
+receives a call to {@link android.app.Activity#onResume onResume()}, which is where you should then
+call {@code connect()} on the {@code IStub}, passing it your application's {@link
+android.content.Context}. Conversely, you should call
+{@code disconnect()} in your activity's {@link android.app.Activity#onStop onStop()} callback.</p>
+<pre>
+&#64;Override
+protected void onResume() {
+    if (null != mDownloaderClientStub) {
+        mDownloaderClientStub.connect(this);
+    }
+    super.onResume();
+}
+
+&#64;Override
+protected void onStop() {
+    if (null != mDownloaderClientStub) {
+        mDownloaderClientStub.disconnect(this);
+    }
+    super.onStop();
+}
+</pre>
+    <p>Calling {@code connect()} on the {@code IStub} binds your activity to the {@code
+DownloaderService} such that your activity receives callbacks regarding changes to the download
+state through the {@code IDownloaderClient} interface.</p>
+  </li>
+</ol>
+
+
+
+<h3 id="Progress">Receiving download progress</h3>
+
+<p>To receive updates regarding the download progress and to interact with the {@code
+DownloaderService}, you must implement the Downloader Library's {@code IDownloaderClient} interface.
+Usually, the activity you use to start the download should implement this interface in order to
+display the download progress and send requests to the service.</p>
+
+<p>The required interface methods for {@code IDownloaderClient} are:</p>
+
+<dl>
+  <dt>{@code onServiceConnected(Messenger m)}</dt>
+    <dd>After you instantiate the {@code IStub} in your activity, you'll receive a call to this
+method, which passes a {@link android.os.Messenger} object that's connected with your instance
+of {@code DownloaderService}. To send requests to the service, such as to pause and resume
+downloads, you must call {@code DownloaderServiceMarshaller.CreateProxy()} to receive the {@code
+IDownloaderService} interface connected to the service.
+    <p>A recommended implementation looks like this:</p>
+<pre>
+private IDownloaderService mRemoteService;
+...
+
+&#64;Override
+public void onServiceConnected(Messenger m) {
+    mRemoteService = DownloaderServiceMarshaller.CreateProxy(m);
+    mRemoteService.onClientUpdated(mDownloaderClientStub.getMessenger());
+}
+</pre>
+    <p>With the {@code IDownloaderService} object initialized, you can send commands to the
+downloader service, such as to pause and resume the download ({@code requestPauseDownload()}
+and {@code requestContinueDownload()}).</p>
+</dd>
+  <dt>{@code onDownloadStateChanged(int newState)}</dt>
+    <dd>The download service calls this when a change in download state occurs, such as the
+download begins or completes.
+      <p>The <code>newState</code> value will be one of several possible values specified in
+by one of the {@code IDownloaderClient} class's {@code STATE_*} constants.</p>
+      <p>To provide a useful message to your users, you can request a corresponding string
+for each state by calling {@code Helpers.getDownloaderStringResourceIDFromState()}. This
+returns the resource ID for one of the strings bundled with the Downloader
+Library. For example, the string "Download paused because you are roaming" corresponds to {@code
+STATE_PAUSED_ROAMING}.</p></dd>
+  <dt>{@code onDownloadProgress(DownloadProgressInfo progress)}</dt>
+    <dd>The download service calls this to deliver a {@code DownloadProgressInfo} object,
+which describes various information about the download progress, including estimated time remaining,
+current speed, overall progress, and total so you can update the download progress UI.</dd>
+</dl>
+<p class="note"><strong>Tip:</strong> For examples of these callbacks that update the download
+progress UI, see the {@code SampleDownloaderActivity} in the sample app provided with the
+Apk Expansion package.</p>
+
+<p>Some public methods for the {@code IDownloaderService} interface you might find useful are:</p>
+
+<dl>
+  <dt>{@code requestPauseDownload()}</dt>
+    <dd>Pauses the download.</dd>
+  <dt>{@code requestContinueDownload()}</dt>
+    <dd>Resumes a paused download.</dd>
+  <dt>{@code setDownloadFlags(int flags)}</dt>
+    <dd>Sets user preferences for network types on which its OK to download the files. The
+current implementation supports one flag, {@code FLAGS_DOWNLOAD_OVER_CELLULAR}, but you can add
+others. By default, this flag is <em>not</em> enabled, so the user must be on Wi-Fi to download
+expansion files. You might want to provide a user preference to enable downloads over
+the cellular network. In which case, you can call:
+<pre>
+mRemoteService.setDownloadFlags(IDownloaderService.FLAGS_DOWNLOAD_OVER_CELLULAR);
+</pre>
+</dd>
+</dl>
+
+
+
+
+<h2 id="ExpansionPolicy">Using APKExpansionPolicy</h2>
+
+<p>If you decide to build your own downloader service instead of using the Google Play
+<a href="#AboutLibraries">Downloader Library</a>, you should still use the {@code
+APKExpansionPolicy} that's provided in the License Verification Library. The {@code
+APKExpansionPolicy} class is nearly identical to {@code ServerManagedPolicy} (available in the
+Google Play License Verification Library) but includes additional handling for the APK expansion
+file response extras.</p>
+
+<p class="note"><strong>Note:</strong> If you <em>do use</em> the <a
+href="#AboutLibraries">Downloader Library</a> as discussed in the previous section, the
+library performs all interaction with the {@code APKExpansionPolicy} so you don't have to use
+this class directly.</p>
+
+<p>The class includes methods to help you get the necessary information about the available
+expansion files:</p>
+
+<ul>
+  <li>{@code getExpansionURLCount()}</li>
+  <li>{@code getExpansionURL(int index)}</li>
+  <li>{@code getExpansionFileName(int index)}</li>
+  <li>{@code getExpansionFileSize(int index)}</li>
+</ul>
+
+<p>For more information about how to use the {@code APKExpansionPolicy} when you're <em>not</em>
+using the <a
+href="#AboutLibraries">Downloader Library</a>, see the documentation for <a
+href="{@docRoot}guide/market/licensing/adding-licensing.html">Adding Licensing to Your App</a>,
+which explains how to implement a license policy such as this one.</p>
+
+
+
+
+
+
+
+<h2 id="ReadingTheFile">Reading the Expansion File</h2>
+
+<p>Once your APK expansion files are saved on the device, how you read your files
+depends on the type of file you've used. As discussed in the <a href="#Overview">overview</a>, your
+expansion files can be any kind of file you
+want, but are renamed using a particular <a href="#Filename">file name format</a> and are saved to
+{@code &lt;shared-storage&gt;/Android/obb/&lt;package-name&gt;/}.</p>
+
+<p>Regardless of how you read your files, you should always first check that the external
+storage is available for reading. There's a chance that the user has the storage mounted to a
+computer over USB or has actually removed the SD card.</p>
+
+<p class="note"><strong>Note:</strong> When your application starts, you should always check whether
+the external storage space is available and readable by calling {@link
+android.os.Environment#getExternalStorageState()}. This returns one of several possible strings
+that represent the state of the external storage. In order for it to be readable by your
+application, the return value must be {@link android.os.Environment#MEDIA_MOUNTED}.</p>
+
+
+<h3 id="GettingFilenames">Getting the file names</h3>
+
+<p>As described in the <a href="#Overview">overview</a>, your APK expansion files are saved
+using a specific file name format:</p>
+
+<pre class="classic no-pretty-print">
+[main|patch].&lt;expansion-version&gt;.&lt;package-name&gt;.obb
+</pre>
+
+<p>To get the location and names of your expansion files, you should use the
+{@link android.os.Environment#getExternalStorageDirectory()} and {@link
+android.content.Context#getPackageName()} methods to construct the path to your files.</p>
+
+<p>Here's a method you can use in your application to get an array containing the complete path
+to both your expansion files:</p>
+
+<pre>
+// The shared path to all app expansion files
+private final static String EXP_PATH = "/Android/obb/";
+
+static String[] getAPKExpansionFiles(Context ctx, int mainVersion, int patchVersion) {
+    String packageName = ctx.getPackageName();
+    Vector&lt;String> ret = new Vector&lt;String>();
+    if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
+        // Build the full path to the app's expansion files
+        File root = Environment.getExternalStorageDirectory();
+        File expPath = new File(root.toString() + EXP_PATH + packageName);
+
+        // Check that expansion file path exists
+        if (expPath.exists()) {
+            if ( mainVersion > 0 ) {
+                String strMainPath = expPath + File.separator + "main." +
+                        mainVersion + "." + packageName + ".obb";
+                File main = new File(strMainPath);
+                if ( main.isFile() ) {
+                        ret.add(strMainPath);
+                }
+            }
+            if ( patchVersion > 0 ) {
+                String strPatchPath = expPath + File.separator + "patch." +
+                        mainVersion + "." + packageName + ".obb";
+                File main = new File(strPatchPath);
+                if ( main.isFile() ) {
+                        ret.add(strPatchPath);
+                }
+            }
+        }
+    }
+    String[] retArray = new String[ret.size()];
+    ret.toArray(retArray);
+    return retArray;
+}
+</pre>
+
+<p>You can call this method by passing it your application {@link android.content.Context}
+and the desired expansion file's version.</p>
+
+<p>There are many ways you could determine the expansion file version number. One simple way is to
+save the version in a {@link android.content.SharedPreferences} file when the download begins, by
+querying the expansion file name with the {@code APKExpansionPolicy} class's {@code
+getExpansionFileName(int index)} method. You can then get the version code by reading the {@link
+android.content.SharedPreferences} file when you want to access the expansion
+file.</p>
+
+<p>For more information about reading from the shared storage, see the <a
+href="{@docRoot}guide/topics/data/data-storage.html#filesExternal">Data Storage</a>
+documentation.</p>
+
+
+
+<h3 id="ZipLib">Using the APK Expansion Zip Library</h3>
+
+<div class="sidebox-wrapper">
+<div class="sidebox">
+  <h3>Reading media files from a ZIP</h3>
+  <p>If you're using your expansion files to store media files, a ZIP file still allows you to
+use Android media playback calls that provide offset and length controls (such as {@link
+android.media.MediaPlayer#setDataSource(FileDescriptor,long,long) MediaPlayer.setDataSource()} and
+{@link android.media.SoundPool#load(FileDescriptor,long,long,int) SoundPool.load()}). In order for
+this to work, you must not perform additional compression on the media files when creating the ZIP
+packages. For example, when using the <code>zip</code> tool, you should use the <code>-n</code>
+option to specify the file suffixes that should not be compressed:</p>
+<p><code>zip -n .mp4;.ogg main_expansion media_files</code></p>
+</div>
+</div>
+
+<p>The Google Market Apk Expansion package includes a library called the APK
+Expansion Zip Library (located in {@code
+&lt;sdk>/extras/google/google_market_apk_expansion/zip_file/}). This is an optional library that
+helps you read your expansion
+files when they're saved as ZIP files. Using this library allows you to easily read resources from
+your ZIP expansion files as a virtual file system.</p>
+
+<p>The APK Expansion Zip Library includes the following classes and APIs:</p>
+
+<dl>
+  <dt>{@code APKExpansionSupport}</dt>
+    <dd>Provides some methods to access expansion file names and ZIP files:
+      
+      <dl style="margin-top:1em">
+        <dt>{@code getAPKExpansionFiles()}</dt> 
+          <dd>The same method shown above that returns the complete file path to both expansion
+files.</dd>
+        <dt>{@code getAPKExpansionZipFile(Context ctx, int mainVersion, int
+patchVersion)}</dt>
+          <dd>Returns a {@code ZipResourceFile} representing the sum of both the main file and
+patch file. That is, if you specify both the <code>mainVersion</code> and the
+<code>patchVersion</code>, this returns a {@code ZipResourceFile} that provides read access to
+all the data, with the patch file's data merged on top of the main file.</dd>
+      </dl>
+    </dd>
+    
+  <dt>{@code ZipResourceFile}</dt>
+    <dd>Represents a ZIP file on the shared storage and performs all the work to provide a virtual
+file system based on your ZIP files. You can get an instance using {@code
+APKExpansionSupport.getAPKExpansionZipFile()} or with the {@code ZipResourceFile} by passing it the
+path to your expansion file. This class includes a variety of useful methods, but you generally
+don't need to access most of them. A couple of important methods are:
+
+      <dl style="margin-top:1em">
+        <dt>{@code getInputStream(String assetPath)}</dt>
+          <dd>Provides an {@link java.io.InputStream} to read a file within the ZIP file. The
+<code>assetPath</code> must be the path to the desired file, relative to
+the root of the ZIP file contents.</dd>
+        <dt>{@code getAssetFileDescriptor(String assetPath)}</dt>
+          <dd>Provides an {@link android.content.res.AssetFileDescriptor} for a file within the
+ZIP file. The <code>assetPath</code> must be the path to the desired file, relative to
+the root of the ZIP file contents. This is useful for certain Android APIs that require  an {@link
+android.content.res.AssetFileDescriptor}, such as some {@link android.media.MediaPlayer} APIs.</dd>
+      </dl>
+    </dd>
+    
+  <dt>{@code APEZProvider}</dt>
+    <dd>Most applications don't need to use this class. This class defines a {@link
+android.content.ContentProvider} that marshals the data from the ZIP files through a content
+provider {@link android.net.Uri} in order to provide file access for certain Android APIs that
+expect {@link android.net.Uri} access to media files.
+      <p>The sample application available in the
+Apk Expansion package demonstrates a scenario in which this class is useful
+to specify a video with {@link android.widget.VideoView#setVideoURI
+VideoView.setVideoURI()}. See the sample app's class {@code SampleZipfileProvider} for an
+example of how to extend this class to use in your application.</p></dd>
+</dl>
+
+<h4>Reading from a ZIP file</h4>
+
+<p>When using the APK Expansion Zip Library, reading a file from your ZIP usually requires the
+following:</p>
+
+<pre>
+// Get a ZipResourceFile representing a merger of both the main and patch files
+ZipResourceFile expansionFile = APKExpansionSupport.getAPKExpansionZipFile(appContext,
+        mainVersion, patchVersion);
+        
+// Get an input stream for a known file inside the expansion file ZIPs
+InputStream fileStream = expansionFile.getInputStream(pathToFileInsideZip);
+</pre>
+
+<p>The above code provides access to any file that exists in either your main expansion file or
+patch expansion file, by reading from a merged map of all the files from both files. All you
+need to provide the {@code getAPKExpansionFile()} method is your application {@code
+android.content.Context} and the version number for both the main expansion file and patch
+expansion file.</p>
+
+<p>If you'd rather read from a specific expansion file, you can use the {@code
+ZipResourceFile} constructor with the path to the desired expansion file:</p>
+
+<pre>
+// Get a ZipResourceFile representing a specific expansion file
+ZipResourceFile expansionFile = new ZipResourceFile(filePathToMyZip);
+
+// Get an input stream for a known file inside the expansion file ZIPs
+InputStream fileStream = expansionFile.getInputStream(pathToFileInsideZip);
+</pre>
+
+<p>For more information about using this library for your expansion files, look at
+the sample application's {@code SampleDownloaderActivity} class, which includes additional code to
+verify the downloaded files using CRC. Beware that if you use this sample as the basis for
+your own implementation, it requires that you <strong>declare the byte size of your expansion
+files</strong> in the {@code xAPKS} array.</p>
+
+
+
+
+<h2 id="Testing">Testing Your Expansion Files</h2>
+
+<p>Before publishing your application, there are two things you should test: Reading the
+expansion files and downloading the files.</p>
+
+
+<h3 id="TestingReading">Testing file reads</h3>
+
+<p>Before you upload your application to Google Play, you
+should test your application's ability to read the files from the shared storage. All you need to do
+is add the files to the appropriate location on the device shared storage and launch your
+application:</p>
+
+<ol>
+  <li>On your device, create the appropriate directory on the shared storage where Google
+Play will save your files.
+  <p>For example, if your package name is {@code com.example.android}, you need to create
+the directory {@code Android/obb/com.example.android/} on the shared storage space. (Plug in
+your test device to your computer to mount the shared storage and manually create this
+directory.)</p>
+  </li>
+  <li>Manually add the expansion files to that directory. Be sure that you rename your files to
+match the <a href="#Filename">file name format</a> that Google Play will use.
+  <p>For example, regardless of the file type, the main expansion file for the {@code
+com.example.android} application should be {@code main.0300110.com.example.android.obb}.
+The version code can be whatever value you want. Just remember:</p>
+  <ul>
+    <li>The main expansion file always starts with {@code main} and the patch file starts with
+{@code patch}.</li>
+    <li>The package name always matches that of the APK to which the file is attached on
+Google Play.
+  </ul>
+  </li>
+  <li>Now that the expansion file(s) are on the device, you can install and run your application to
+test your expansion file(s).</li>
+</ol>
+
+<p>Here are some reminders about handling the expansion files:</p>
+<ul>
+  <li><strong>Do not delete or rename</strong> the {@code .obb} expansion files (even if you unpack
+the data to a different location). Doing so will cause Google Play (or your app itself) to
+repeatedly download the expansion file.</li>
+  <li><strong>Do not save other data into your <code>obb/</code>
+directory</strong>. If you must unpack some data, save it into the location specified by {@link
+android.content.Context#getExternalFilesDir getExternalFilesDir()}.</li>
+</ul>
+
+
+
+<h3 id="TestingReading">Testing file downloads</h3>
+
+<p>Because your application must sometimes manually download the expansion files when it first
+opens, it's important that you test this process to be sure your application can successfully query
+for the URLs, download the files, and save them to the device.</p>
+
+<p>To test your application's implementation of the manual download procedure, you must upload
+your application to Google Play as a "draft" to make your expansion files available for
+download:</p>
+
+<ol>
+  <li>Upload your APK and corresponding expansion files using the Google Play Developer
+Console.</li>
+  <li>Fill in the necessary application details (title, screenshots, etc.). You can come back and
+finalize these details before publishing your application.
+  <p>Click the <strong>Save</strong> button. <em>Do not click Publish.</em> This saves
+the application as a draft, such that your application is not published for Google Play users,
+but the expansion files are available for you to test the download process.</p></li>
+  <li>Install the application on your test device using the Eclipse tools or <a
+href="{@docRoot}guide/developing/tools/adb.html">{@code adb}</a>.</li>
+  <li>Launch the app.</li>
+</ol>
+
+<p>If everything works as expected, your application should begin downloading the expansion
+files as soon as the main activity starts.</p>
+
+
+
+
+<h2 id="Updating">Updating Your Application</h2>
+
+<p>One of the great benefits to using expansion files on Google Play is the ability to
+update your application without re-downloading all of the original assets. Because Google Play
+allows you to provide two expansion files with each APK, you can use the second file as a "patch"
+that provides updates and new assets. Doing so avoids the
+need to re-download the main expansion file which could be large and expensive for users.</p>
+
+<p>The patch expansion file is technically the same as the main expansion file and neither
+the Android system nor Google Play perform actual patching between your main and patch expansion
+files. Your application code must perform any necessary patches itself.</p>
+
+<p>If you use ZIP files as your expansion files, the <a href="#ZipLib">APK Expansion Zip
+Library</a> that's included with the Apk Expansion package includes the ability to merge
+your
+patch file with the main expansion file.</p>
+
+<p class="note"><strong>Note:</strong> Even if you only need to make changes to the patch
+expansion file, you must still update the APK in order for Google Play to perform an update.
+If you don't require code changes in the application, you should simply update the <a
+href="{@docRoot}guide/topics/manifest/manifest-element.html#vcode">{@code versionCode}</a> in the
+manifest.</p>
+
+<p>As long as you don't change the main expansion file that's associated with the APK
+in the Developer Console, users who previously installed your application will not
+download the main expansion file. Existing users receive only the updated APK and the new patch
+expansion file (retaining the previous main expansion file).</p>
+
+<p>Here are a few issues to keep in mind regarding updates to expansion files:</p>
+
+<ul>
+  <li>There can be only two expansion files for your application at a time. One main expansion
+file and one patch expansion file. During an update to a file, Google Play deletes the
+previous version (and so must your application when performing manual updates).</li>
+  <li>When adding a patch expansion file, the Android system does not actually patch your
+application or main expansion file. You must design your application to support the patch data.
+However, the Apk Expansion package includes a library for using ZIP files
+as expansion files, which merges the data from the patch file into the main expansion file so
+you can easily read all the expansion file data.</li>
+</ul>
+
+
+
+<!-- Tools are not ready.
+     
+<h3>Using OBB tool and APIs</h3>
+
+<pre>
+$ mkobb.sh -d /data/myfiles -k my_secret_key -o /data/data.obb
+$ obbtool a -n com.example.myapp -v 1 -s seed_from_mkobb /data/data.obb
+</pre>
+
+<pre>
+storage = (StorageManager) getSystemService( STORAGE_SERVICE );
+storage.mountObb( obbFilepath, "my_secret_key", myListener );
+obbContentPath = storage.getMountedObbPath( obbFilepath );
+</pre>
+-->
diff --git a/docs/html/guide/market/licensing/adding-licensing.jd b/docs/html/guide/market/licensing/adding-licensing.jd
new file mode 100644
index 0000000..d4dd008
--- /dev/null
+++ b/docs/html/guide/market/licensing/adding-licensing.jd
@@ -0,0 +1,1072 @@
+page.title=Adding Licensing to Your App
+parent.title=Application Licensing
+parent.link=index.html
+@jd:body
+
+
+
+<div id="qv-wrapper">
+<div id="qv">
+  
+  <h2>In this document</h2>
+  <ol>
+  <li><a href="#manifest-permission">Adding the Licensing Permission</a></li>
+  <li><a href="#impl-Policy">Implementing a Policy</a>
+    <ol>
+      <li><a href="#custom-policies">Guidelines for custom policies</a></li>
+      <li><a href="#ServerManagedPolicy">ServerManagedPolicy</a></li>
+      <li><a href="#StrictPolicy">StrictPolicy</a></li>
+    </ol>
+  </li>
+  <li><a href="#impl-Obfuscator">Implementing an Obfuscator</a>
+    <ol>
+      <li><a href="#AESObfuscator">AESObfuscator</a></li>
+    </ol>
+  </li>
+  <li><a href="#impl-lc">Checking the License from an Activity</a>
+    <ol>
+      <li><a href="#lc-overview">Overview of license check and response</a></li>
+      <li><a href="#imports">Add imports</a></li>
+      <li><a href="#lc-impl">Implement LicenseCheckerCallback as a private inner class</a></li>
+      <li><a href="#thread-handler">Create a Handler for posting from LicenseCheckerCallback
+to the UI thread</a></li>
+      <li><a href="#lc-lcc">Instantiate LicenseChecker and LicenseCheckerCallback</a></li>
+      <li><a href="#check-access">Call checkAccess() to initiate the license check</a></li>
+      <li><a href="#account-key">Embed your public key for licensing</a></li>
+      <li><a href="#handler-cleanup">Call your LicenseChecker's onDestroy() method
+to close IPC connections</a></li>
+    </ol>
+  </li>
+  <li><a href="#impl-DeviceLimiter">Implementing a DeviceLimiter</a></li>
+  <li><a href="#app-obfuscation">Obfuscating Your Code</a></li>
+  <li><a href="#app-publishing">Publishing a Licensed Application</a>
+    <ol>
+      <li><a href="#">Removing Copy Protection</a></li>
+    </ol>
+  </li>
+  <li><a href="#support">Where to Get Support</a></li>
+</ol>
+  
+</div>
+</div>
+
+
+
+<p>After you've set up a publisher account and development environment (see <a
+href="setting-up.html">Setting Up for Licensing</a>), you are ready to add license verification to
+your app with the License Verification Library (LVL).</p>
+
+<p>Adding license verification with the LVL involves these tasks:</p>
+
+<ol>
+<li><a href="#manifest-permission">Adding the licensing permission</a> your application's manifest.</li>
+<li><a href="#impl-Policy">Implementing a Policy</a> &mdash; you can choose one of the full implementations provided in the LVL or create your own.</li>
+<li><a href="#impl-Obfuscator">Implementing an Obfuscator</a>, if your {@code Policy} will cache any
+license response data. </li>
+<li><a href="#impl-lc">Adding code to check the license</a> in your application's main
+Activity.</li>
+<li><a href="#impl-DeviceLimiter">Implementing a DeviceLimiter</a> (optional and not recommended for
+most applications).</li>
+</ol>
+
+<p>The sections below describe these tasks. When you are done with the
+integration, you should be able to compile your application successfully and you
+can begin testing, as described in <a
+href="{@docRoot}guide/market/licensing/setting-up.html#test-env">Setting Up the Test
+Environment</a>.</p>
+
+<p>For an overview of the full set of source files included in the LVL, see <a
+href="{@docRoot}guide/market/licensing/licensing-reference.html#lvl-summary">Summary of LVL Classes
+and Interfaces</a>.</p>
+
+
+<h2 id="manifest-permission">Adding the Licensing Permission</h2>
+
+<p>To use the Google Play application for sending a license check to the
+server, your application must request the proper permission,
+<code>com.android.vending.CHECK_LICENSE</code>. If your application does
+not declare the licensing permission but attempts to initiate a license check,
+the LVL throws a security exception.</p>
+
+<p>To request the licensing permission in your application, declare a <a
+href="{@docRoot}guide/topics/manifest/uses-permission-element.html"><code>&lt;uses-permission&gt;</code></a>
+element as a child of <code>&lt;manifest&gt;</code>, as follows: </p>
+
+<p style="margin-left:2em;"><code>&lt;uses-permission
+android:name="com.android.vending.CHECK_LICENSE"&gt;</code></p>
+
+<p>For example, here's how the LVL sample application declares the permission:
+</p>
+
+<pre>&lt;?xml version="1.0" encoding="utf-8"?&gt;
+
+&lt;manifest xmlns:android="http://schemas.android.com/apk/res/android" ..."&gt;
+    &lt;!-- Devices &gt;= 3 have version of Google Play that supports licensing. --&gt;
+    &lt;uses-sdk android:minSdkVersion="3" /&gt;
+    &lt;!-- Required permission to check licensing. --&gt;
+    &lt;uses-permission android:name="com.android.vending.CHECK_LICENSE" /&gt;
+    ...
+&lt;/manifest&gt;
+</pre>
+
+<p class="note"><strong>Note:</strong> Currently, you cannot declare the
+<code>CHECK_LICENSE</code> permission in the LVL library project's manifest,
+because the SDK Tools will not merge it into the manifests of dependent
+applications. Instead, you must declare the permission in each dependent
+application's manifest. </p>
+
+
+<h2 id="impl-Policy">Implementing a Policy</h2>
+
+<div class="sidebox-wrapper">
+<div class="sidebox">
+<h2>ServerManagedPolicy</h2>
+
+<p>The LVL includes a complete {@code Policy} implementation called ServerManagedPolicy
+that makes use of license-management settings provided by the Google Play
+server. </p>
+
+<p style="margin-top:.5em;">Use of ServerManagedPolicy as the basis for your
+Policy is strongly recommended. For more information, see <a
+href="#ServerManagedPolicy">ServerManagedPolicy</a> section, below.</p>
+
+</div>
+</div>
+
+<p>Google Play licensing service does not itself determine whether a
+given user with a given license should be granted access to your application.
+Rather, that responsibility is left to a {@code Policy} implementation that you provide
+in your application.</p>
+
+<p>Policy is an interface declared by the LVL that is designed to hold your
+application's logic for allowing or disallowing user access, based on the result
+of a license check. To use the LVL, your application <em>must</em> provide an
+implementation of {@code Policy}. </p>
+
+<p>The {@code Policy} interface declares two methods, <code>allowAccess()</code> and
+<code>processServerResponse()</code>, which are called by a {@code LicenseChecker}
+instance when processing a response from the license server. It also declares an
+enum called <code>LicenseResponse</code>, which specifies the license response
+value passed in calls to <code>processServerResponse()</code>. </p>
+
+<ul>
+<li><code>processServerResponse()</code> lets you preprocess the raw response
+data received from the licensing server, prior to determining whether to grant
+access.
+
+<p>A typical implementation would extract some or all fields from the license
+response and store the data locally to a persistent store, such as through
+{@link android.content.SharedPreferences} storage, to ensure that the data is
+accessible across application invocations and device power cycles. For example,
+a {@code Policy} would maintain the timestamp of the last successful license check, the
+retry count, the license validity period, and similar information in a
+persistent store, rather than resetting the values each time the application is
+launched.</p>
+
+<p>When storing response data locally, the {@code Policy} must ensure that the data is
+obfuscated (see <a href="#impl-Obfuscator">Implementing an Obfuscator</a>,
+below).</p></li>
+
+<li><code>allowAccess()</code> determines whether to grant the user access to
+your application, based on any available license response data (from the
+licensing server or from cache) or other application-specific information.  For
+example, your implementation of <code>allowAccess()</code> could take into
+account additional criteria, such as usage or other data retrieved from a
+backend server. In all cases, an implementation of <code>allowAccess()</code>
+should only return <code>true</code> if the user is licensed to use the
+application, as determined by the licensing server, or if there is a transient
+network or system problem that prevents the license check from completing. In
+such cases, your implementation can maintain a count of retry responses and
+provisionally allow access until the next license check is complete.</li>
+
+</ul>
+
+<p>To simplify the process of adding licensing to your application and to
+provide an illustration of how a {@code Policy} should be designed, the LVL includes
+two full {@code Policy} implementations that you can use without modification or
+adapt to your needs:</p>
+
+<ul>
+<li><a href="#ServerManagedPolicy">ServerManagedPolicy</a>, a flexible {@code Policy}
+that uses server-provided settings and cached responses to manage access across
+varied network conditions, and</li>
+<li><a href="#StrictPolicy">StrictPolicy</a>, which does not cache any response
+data and allows access <em>only</em> if the server returns a licensed
+response.</li>
+</ul>
+
+<p>For most applications, the use of ServerManagedPolicy is highly
+recommended. ServerManagedPolicy is the LVL default and is integrated with
+the LVL sample application.</p>
+
+
+<h3 id="custom-policies">Guidelines for custom policies</h3>
+
+<p>In your licensing implementation, you can use one of the complete policies
+provided in the LVL (ServerManagedPolicy or StrictPolicy) or you can create a
+custom policy. For any type of custom policy, there are several important design
+points to understand and account for in your implementation.</p>
+
+<p>The licensing server applies general request limits to guard against overuse
+of resources that could result in denial of service. When an application exceeds
+the request limit, the licensing server returns a 503 response, which gets
+passed through to your application as a general server error. This means that no
+license response will be available to the user until the limit is reset, which
+can affect the user for an indefinite period.</p>
+
+<p>If you are designing a custom policy, we recommend that the {@code Policy}:
+<ol>
+<!-- <li>Limits the number of points at which your app calls for a license check
+to the minimum. </li> -->
+<li>Caches (and properly obfuscates) the most recent successful license response
+in local persistent storage.</li>
+<li>Returns the cached response for all license checks, for as long as the
+cached response is valid, rather than making a request to the licensing server.
+Setting the response validity according to the server-provided <code>VT</code>
+extra is highly recommended. See <a
+href="{@docRoot}guide/market/licensing/licensing-reference.html#extras">Server Response Extras</a>
+for more information.</li>
+<li>Uses an exponential backoff period, if retrying any requests the result in
+errors. Note that the Google Play client automatically retries failed
+requests, so in most cases there is no need for your {@code Policy} to retry them.</li>
+<li>Provides for a "grace period" that allows the user to access your
+application for a limited time or number of uses, while a license check is being
+retried. The grace period benefits the user by allowing access until the next
+license check can be completed successfully and it benefits you by placing a
+hard limit on access to your application when there is no valid license response
+available.</li>
+</ol>
+
+<p>Designing your {@code Policy} according to the guidelines listed above is critical,
+because it ensures the best possible experience for users while giving you
+effective control over your application even in error conditions. </p>
+
+<p>Note that any {@code Policy} can use settings provided by the licensing server to
+help manage validity and caching, retry grace period, and more. Extracting the
+server-provided settings is straightforward and making use of them is highly
+recommended. See the ServerManagedPolicy implementation for an example of how to
+extract and use the extras. For a list of server settings and information about
+how to use them, see  <a
+href="{@docRoot}guide/market/licensing/licensing-reference.html#extras">Server Response
+Extras</a>.</p>
+
+<h3 id="ServerManagedPolicy">ServerManagedPolicy</h3>
+
+<div class="sidebox-wrapper">
+<div class="sidebox">
+<h2>Server Response Extras</h2>
+
+<p>For certain types of licensing responses, the licensing server appends extra
+settings to the responses, to help the application manage licensing effectively.
+</p>
+
+<p style="margin-top:.5em;">See <a
+href="{@docRoot}guide/market/licensing/licensing-reference.html#extras">Server Response Extras</a>
+for
+a list of settings and <code>ServerManagedPolicy.java</code> for information
+about how a {@code Policy} can use the extras.</p>
+
+</div>
+</div>
+
+<p>The LVL includes a full and recommended implementation of the {@code Policy}
+interface called ServerManagedPolicy. The implementation is integrated with the
+LVL classes and serves as the default {@code Policy} in the library. </p>
+
+<p>ServerManagedPolicy provides all of the handling for license and retry
+responses. It caches all of the response data locally in a
+{@link android.content.SharedPreferences} file, obfuscating it with the
+application's {@code Obfuscator} implementation. This ensures that the license response
+data is secure and persists across device power cycles. ServerManagedPolicy
+provides concrete implementations of the interface methods
+<code>processServerResponse()</code> and <code>allowAccess()</code> and also
+includes a set of supporting methods and types for managing license
+responses.</p>
+
+<p>Importantly, a key feature of ServerMangedPolicy is its use of
+server-provided settings as the basis for managing licensing across an
+application's refund period and through varying network and error conditions.
+When an application contacts the Google Play server for a license check, the
+server appends several settings as key-value pairs in the extras field of certain
+license response types. For example, the server provides recommended values for the
+application's license validity period, retry grace period, and maximum allowable
+retry count, among others. ServerManagedPolicy extracts the values from the
+license response in its <code>processServerResponse()</code> method and checks
+them in its <code>allowAccess()</code> method. For a list of the server-provided
+settings used by ServerManagedPolicy, see <a
+href="{@docRoot}guide/market/licensing/licensing-reference.html#extras">Server Response
+Extras</a>.</p>
+
+<p>For convenience, best performance, and the benefit of using license settings
+from the Google Play server, <strong>using ServerManagedPolicy as your
+licensing {@code Policy} is strongly recommended</strong>. </p>
+
+<p>If you are concerned about the security of license response data that is
+stored locally in {@link android.content.SharedPreferences}, you can use a stronger obfuscation
+algorithm or design a stricter {@code Policy} that does not store license data. The LVL
+includes an example of such a {@code Policy} &mdash; see <a
+href="#StrictPolicy">StrictPolicy</a> for more information.</p>
+
+<p>To use ServerManagedPolicy, simply import it to your Activity, create an
+instance, and pass a reference to the instance when constructing your
+{@code LicenseChecker}. See <a href="#lc-lcc">Instantiate LicenseChecker and
+LicenseCheckerCallback</a> for more information. </p>
+
+<h3 id="StrictPolicy">StrictPolicy</h3>
+
+<p>The LVL includes an alternative full implementation of the {@code Policy} interface
+called StrictPolicy. The StrictPolicy implementation provides a more restrictive
+Policy than ServerManagedPolicy, in that it does not allow the user to access
+the application unless a license response is received from the server at the
+time of access that indicates that the user is licensed.</p>
+
+<p>The principal feature of StrictPolicy is that it does not store <em>any</em>
+license response data locally, in a persistent store. Because no data is stored,
+retry requests are not tracked and cached responses can not be used to fulfill
+license checks. The {@code Policy} allows access only if:</p>
+
+<ul>
+<li>The license response is received from the licensing server, and </li>
+<li>The license response indicates that the user is licensed to access the
+application. </li>
+</ul>
+
+<p>Using StrictPolicy is appropriate if your primary concern is to ensure that,
+in all possible cases, no user will be allowed to access the application unless
+the user is confirmed to be licensed at the time of use. Additionally, the
+Policy offers slightly more security than ServerManagedPolicy &mdash; since
+there is no data cached locally, there is no way a malicious user could tamper
+with the cached data and obtain access to the application.</p>
+
+<p>At the same time, this {@code Policy} presents a challenge for normal users, since it
+means that they won't be able to access the application when there is no network
+(cell or Wi-Fi) connection available. Another side-effect is that your
+application will send more license check requests to the server, since using a
+cached response is not possible.</p>
+
+<p>Overall, this policy represents a tradeoff of some degree of user convenience
+for absolute security and control over access. Consider the tradeoff carefully
+before using this {@code Policy}.</p>
+
+<p>To use StrictPolicy, simply import it to your Activity, create an instance,
+and pass a reference to it when constructing your {@code LicenseChecker}. See
+<a href="#lc-lcc">Instantiate LicenseChecker and LicenseCheckerCallback</a>
+for more information. </p>
+
+<h2 id="impl-Obfuscator">Implementing an Obfuscator</h2>
+
+<div class="sidebox-wrapper">
+<div class="sidebox">
+<h2>AESObfuscator</h2>
+
+<p>The LVL includes a full {@code Obfuscator} implementation in the
+<code>AESObfuscator.java</code> file. The {@code Obfuscator} uses AES encryption to
+obfuscate/unobfuscate data. If you are using a {@code Policy} (such as
+ServerManagedPolicy) that caches license response data, using AESObfuscator as
+basis for your {@code Obfuscator} implementation is highly recommended. </p>
+
+</div>
+</div>
+
+<p>A typical {@code Policy} implementation needs to save the license response data for
+an application to a persistent store, so that it is accessible across
+application invocations and device power cycles.  For example, a {@code Policy} would
+maintain the timestamp of the last successful license check, the retry count,
+the license validity period, and similar information in a persistent store,
+rather than resetting the values each time the application is launched. The
+default {@code Policy} included in the LVL, ServerManagedPolicy, stores license response
+data in a {@link android.content.SharedPreferences} instance, to ensure that the
+data is persistent. </p>
+
+<p>Because the {@code Policy} will use stored license response data to determine whether
+to allow or disallow access to the application, it <em>must</em> ensure that any
+stored data is secure and cannot be reused or manipulated by a root user on a
+device. Specifically, the {@code Policy} must always obfuscate the data before storing
+it, using a key that is unique for the application and device. Obfuscating using
+a key that is both application-specific and device-specific is critical, because
+it prevents the obfuscated data from being shared among applications and
+devices.</p>
+
+<p>The LVL assists the application with storing its license response data in a
+secure, persistent manner. First, it provides an {@code Obfuscator}
+interface that lets your application supply the obfuscation algorithm of its
+choice for stored data. Building on that, the LVL provides the helper class
+PreferenceObfuscator, which handles most of the work of calling the
+application's {@code Obfuscator} class and reading and writing the obfuscated data in a
+{@link android.content.SharedPreferences} instance. </p>
+
+<p>The LVL provides a full {@code Obfuscator} implementation called
+AESObfuscator that uses AES encryption to obfuscate data. You can
+use AESObfuscator in your application without modification or you
+can adapt it to your needs. For more information, see the next section.</p>
+
+
+<h3 id="AESObfuscator">AESObfuscator</h3>
+
+<p>The LVL includes a full and recommended implementation of the {@code Obfuscator}
+interface called AESObfuscator. The implementation is integrated with the
+LVL sample application and serves as the default {@code Obfuscator} in the library. </p>
+
+<p>AESObfuscator provides secure obfuscation of data by using AES to
+encrypt and decrypt the data as it is written to or read from storage.
+The {@code Obfuscator} seeds the encryption using three data fields provided
+by the application: </p>
+
+<ol>
+<li>A salt &mdash; an array of random bytes to use for each (un)obfuscation. </li>
+<li>An application identifier string, typically the package name of the application.</li>
+<li>A device identifier string, derived from as many device-specific sources
+as possible, so as to make it as unique.</li>
+</ol>
+
+<p>To use AESObfuscator, first import it to your Activity. Declare a private
+static final array to hold the salt bytes and initialize it to 20 randomly
+generated bytes.</p>
+
+<pre>    ...
+    // Generate 20 random bytes, and put them here.
+    private static final byte[] SALT = new byte[] {
+     -46, 65, 30, -128, -103, -57, 74, -64, 51, 88, -95,
+     -45, 77, -117, -36, -113, -11, 32, -64, 89
+     };
+    ...
+</pre>
+
+<p>Next, declare a variable to hold a device identifier and generate a value for
+it in any way needed. For example, the sample application included in the LVL
+queries the system settings for the
+<code>android.Settings.Secure.ANDROID_ID</code>, which is unique to each device.
+</p>
+
+<p>Note that, depending on the APIs you use, your application might need to
+request additional permissions in order to acquire device-specific information.
+For example, to query the {@link android.telephony.TelephonyManager} to obtain
+the device IMEI or related data, the application will also need to request the
+<code>android.permission.READ_PHONE_STATE</code> permission in its manifest.</p>
+
+<p>Before requesting new permissions for the <em>sole purpose</em> of acquiring
+device-specific information for use in your {@code Obfuscator}, consider
+how doing so might affect your application or its filtering on Google Play
+(since some permissions can cause the SDK build tools to add
+the associated <code>&lt;uses-feature&gt;</code>).</p>
+
+<p>Finally, construct an instance of AESObfuscator, passing the salt,
+application identifier, and device identifier. You can construct the instance
+directly, while constructing your {@code Policy} and {@code LicenseChecker}. For example:</p>
+
+<pre>    ...
+    // Construct the LicenseChecker with a Policy.
+    mChecker = new LicenseChecker(
+        this, new ServerManagedPolicy(this,
+            new AESObfuscator(SALT, getPackageName(), deviceId)),
+        BASE64_PUBLIC_KEY  // Your public licensing key.
+        );
+    ...
+</pre>
+
+<p>For a complete example, see MainActivity in the LVL sample application.</p>
+
+
+<h2 id="impl-lc">Checking the License from an Activity</h2>
+
+<p>Once you've implemented a {@code Policy} for managing access to your application, the
+next step is to add a license check to your application, which initiates a query
+to the licensing server if needed and manages access to the application based on
+the license response. All of the work of adding the license check and handling
+the response takes place in your main {@link android.app.Activity} source file.
+</p>
+
+<p>To add the license check and handle the response, you must:</p>
+
+<ol>
+    <li><a href="#imports">Add imports</a></li>
+    <li><a href="#lc-impl">Implement LicenseCheckerCallback</a> as a private inner class</li>
+    <li><a href="#thread-handler">Create a Handler</a> for posting from LicenseCheckerCallback to the UI thread</li>
+    <li><a href="#lc-lcc">Instantiate LicenseChecker</a> and LicenseCheckerCallback</li>
+    <li><a href="#check-access">Call checkAccess()</a> to initiate the license check</li>
+    <li><a href="#account-key">Embed your public key</a> for licensing</li>
+    <li><a href="#handler-cleanup">Call your LicenseChecker's onDestroy() method</a> to close IPC connections.</li>
+</ol>
+
+<p>The sections below describe these tasks. </p>
+
+<h3 id="lc-overview">Overview of license check and response</h3>
+
+<div class="sidebox-wrapper">
+<div class="sidebox">
+<h2>Example: MainActivity</h2>
+
+<p>The sample application included with the LVL provides a full example of how
+to initiate a license check and handle the result, in the
+<code>MainActivity.java</code> file.</p>
+
+</div>
+</div>
+
+<p>In most cases, you should add the license check to your application's main
+{@link android.app.Activity}, in the {@link android.app.Activity#onCreate onCreate()} method. This
+ensures that when the user launches your application directly, the license check
+will be invoked immediately. In some cases, you can add license checks in other
+locations as well. For example, if your application includes multiple Activity
+components that other applications can start by {@link android.content.Intent},
+you could add license checks in those Activities.</p>
+
+<p>A license check consists of two main actions: </p>
+
+<ul>
+<li>A call to a method to initiate the license check &mdash; in the LVL, this is
+a call to the <code>checkAccess()</code> method of a {@code LicenseChecker} object that
+you construct.</li>
+<li>A callback that returns the result of the license check. In the LVL, this is
+a <code>LicenseCheckerCallback</code> interface that you implement. The
+interface declares two methods, <code>allow()</code> and
+<code>dontAllow()</code>, which are invoked by the library based on to the
+result of the license check. You implement these two methods with whatever logic
+you need, to allow or disallow the user access to your application. Note that
+these methods do not determine <em>whether</em> to allow access &mdash; that
+determination is the responsibility of your {@code Policy} implementation. Rather, these
+methods simply provide the application behaviors for <em>how</em> to allow and
+disallow access (and handle application errors).
+  <p>The <code>allow()</code> and <code>dontAllow()</code> methods do provide a "reason"
+for their response, which can be one of the {@code Policy} values, {@code LICENSED},
+{@code NOT_LICENSED}, or {@code RETRY}. In particular, you should handle the case in which
+the method receives the {@code RETRY} response for {@code dontAllow()} and provide the user with an
+"Retry" button, which might have happened because the service was unavailable during the
+request.</p></li>
+</ul>
+
+<div style="margin-bottom:2em;">
+
+<img src="{@docRoot}images/licensing_flow.png" style="text-align:left;margin-bottom:0;margin-left:3em;" />
+<div style="margin:.5em 0 1.5em 2em;padding:0"><strong>Figure 6.</strong> Overview of a
+typical license check interaction.</div>
+</div>
+
+<p>The diagram above illustrates how a typical license check takes place: </p>
+
+<ol>
+<li>Code in the application's main Activity instantiates {@code LicenseCheckerCallback}
+and {@code LicenseChecker} objects. When constructing {@code LicenseChecker}, the code passes in
+{@link android.content.Context}, a {@code Policy} implementation to use, and the
+publisher account's public key for licensing as parameters. </li>
+<li>The code then calls the <code>checkAccess()</code> method on the
+{@code LicenseChecker} object. The method implementation calls the {@code Policy} to determine
+whether there is a valid license response cached locally, in
+{@link android.content.SharedPreferences}.
+  <ul>
+    <li>If so, the <code>checkAccess()</code> implementation calls
+  <code>allow()</code>.</li>
+    <li>Otherwise, the {@code LicenseChecker} initiates a license check request that is sent
+  to the licensing server.</li>
+  </ul>
+
+<p class="note"><strong>Note:</strong> The licensing server always returns
+<code>LICENSED</code> when you perform a license check of a draft application.</p>
+</li>
+<li>When a response is received, {@code LicenseChecker} creates a LicenseValidator that
+verifies the signed license data and extracts the fields of the response, then
+passes them to your {@code Policy} for further evaluation.
+  <ul>
+    <li>If the license is valid, the {@code Policy} caches the response in
+{@link android.content.SharedPreferences} and notifies the validator, which then calls the
+<code>allow()</code> method on the {@code LicenseCheckerCallback} object. </li>
+    <li>If the license not valid, the {@code Policy} notifies the validator, which calls
+the <code>dontAllow()</code> method on {@code LicenseCheckerCallback}. </li>
+  </ul>
+</li>
+<li>In case of a recoverable local or server error, such as when the network is
+not available to send the request, {@code LicenseChecker} passes a {@code RETRY} response to
+your {@code Policy} object's <code>processServerResponse()</code> method. 
+  <p>Also, both the {@code allow()} and {@code dontAllow()} callback methods receive a
+<code>reason</code> argument. The {@code allow()} method's reason is usually {@code
+Policy.LICENSED} or {@code Policy.RETRY} and the {@code dontAllow()} reason is usually {@code
+Policy.NOT_LICENSED} or {@code Policy.RETRY}. These response values are useful so you can show
+an appropriate response for the user, such as by providing a "Retry" button when {@code
+dontAllow()} responds with {@code Policy.RETRY}, which might have been because the service was
+unavailable.</p></li>
+<li>In case of a application error, such as when the application attempts to
+check the license of an invalid package name, {@code LicenseChecker} passes an error
+response to the LicenseCheckerCallback's  <code>applicationError()</code>
+method. </li>
+</ol>
+
+<p>Note that, in addition to initiating the license check and handling the
+result, which are described in the sections below, your application also needs
+to provide a <a href="#impl-Policy">Policy implementation</a> and, if the {@code Policy}
+stores response data (such as ServerManagedPolicy), an <a
+href="#impl-Obfuscator">Obfuscator</a> implementation. </p>
+
+
+<h3 id="imports">Add imports</h3>
+
+<p>First, open the class file of the application's main Activity and import
+{@code LicenseChecker} and {@code LicenseCheckerCallback} from the LVL package.</p>
+
+<pre>    import com.android.vending.licensing.LicenseChecker;
+    import com.android.vending.licensing.LicenseCheckerCallback;</pre>
+
+<p>If you are using the default {@code Policy} implementation provided with the LVL,
+ServerManagedPolicy, import it also, together with the AESObfuscator. If you are
+using a custom {@code Policy} or {@code Obfuscator}, import those instead. </p>
+
+<pre>    import com.android.vending.licensing.ServerManagedPolicy;
+    import com.android.vending.licensing.AESObfuscator;</pre>
+
+<h3 id="lc-impl">Implement LicenseCheckerCallback as a private inner class</h3>
+
+<p>{@code LicenseCheckerCallback} is an interface provided by the LVL for handling
+result of a license check. To support licensing using the LVL, you must
+implement {@code LicenseCheckerCallback} and
+its methods to allow or disallow access to the application.</p>
+
+<p>The result of a license check is always a call to one of the
+{@code LicenseCheckerCallback} methods, made based on the validation of the response
+payload, the server response code itself, and any additional processing provided
+by your {@code Policy}. Your application can implement the methods in any way needed. In
+general, it's best to keep the methods simple, limiting them to managing UI
+state and application access. If you want to add further processing of license
+responses, such as by contacting a backend server or applying custom constraints,
+you should consider incorporating that code into your {@code Policy}, rather than
+putting it in the {@code LicenseCheckerCallback} methods. </p>
+
+<p>In most cases, you should declare your implementation of
+{@code LicenseCheckerCallback} as a private class inside your application's main
+Activity class. </p>
+
+<p>Implement the <code>allow()</code> and <code>dontAllow()</code> methods as
+needed. To start with, you can use simple result-handling behaviors in the
+methods, such as displaying the license result in a dialog. This helps you get
+your application running sooner and can assist with debugging. Later, after you
+have determined the exact behaviors you want, you can add more complex handling.
+</p>
+
+<p>Some suggestions for handling unlicensed responses in
+<code>dontAllow()</code> include: </p>
+
+<ul>
+<li>Display a "Try again" dialog to the user, including a button to initiate a
+new license check if the <code>reason</code> supplied is {@code Policy.RETRY}. </li>
+<li>Display a "Purchase this application" dialog, including a button that
+deep-links the user to the application's details page on Google Play, from which the
+use can purchase the application. For more information on how to set up such
+links, see <a
+href="{@docRoot}guide/publishing/publishing.html#marketintent">Linking to your apps
+on Google Play</a>. </li>
+<li>Display a Toast notification that indicates that the features of the
+application are limited because it is not licensed. </li>
+</ul>
+
+<p>The example below shows how the LVL sample application implements
+{@code LicenseCheckerCallback}, with methods that display the license check result in a
+dialog. </p>
+
+<pre>
+private class MyLicenseCheckerCallback implements LicenseCheckerCallback {
+    public void allow(int reason) {
+        if (isFinishing()) {
+            // Don't update UI if Activity is finishing.
+            return;
+        }
+        // Should allow user access.
+        displayResult(getString(R.string.allow));
+    }
+
+    public void dontAllow(int reason) {
+        if (isFinishing()) {
+            // Don't update UI if Activity is finishing.
+            return;
+        }
+        displayResult(getString(R.string.dont_allow));
+        
+        if (reason == Policy.RETRY) {
+            // If the reason received from the policy is RETRY, it was probably
+            // due to a loss of connection with the service, so we should give the
+            // user a chance to retry. So show a dialog to retry.
+            showDialog(DIALOG_RETRY);
+        } else {
+            // Otherwise, the user is not licensed to use this app.
+            // Your response should always inform the user that the application
+            // is not licensed, but your behavior at that point can vary. You might
+            // provide the user a limited access version of your app or you can
+            // take them to Google Play to purchase the app.
+            showDialog(DIALOG_GOTOMARKET);
+        }
+    }
+}
+</pre>
+
+<p>Additionally, you should implement the <code>applicationError()</code>
+method, which the LVL calls to let your application handle errors that are not
+retryable. For a list of such errors, see <a
+href="{@docRoot}guide/market/licensing/licensing-reference.html#server-response-codes">Server
+Response Codes</a> in the <a
+href="guide/market/licensing/licensing-reference.html">Licensing Reference</a>. You can implement
+the method in any way needed. In most cases, the
+method should log the error code and call <code>dontAllow()</code>.</p>
+
+<h3 id="thread-handler">Create a Handler for posting from LicenseCheckerCallback
+to the UI thread</h3>
+
+<p>During a license check, the LVL passes the request to the Google Play
+application, which handles communication with the licensing server. The LVL
+passes the request over asynchronous IPC (using {@link android.os.Binder}) so
+the actual processing and network communication do not take place on a thread
+managed by your application. Similarly, when the Google Play application
+receives the result, it invokes a  callback method over IPC, which in turn
+executes in an IPC thread pool in your application's process.</p>
+
+<p>The {@code LicenseChecker} class manages your application's IPC communication with
+the Google Play application, including the call that sends the request and
+the callback that receives the response. {@code LicenseChecker} also tracks open license
+requests and manages their timeouts. </p>
+
+<p>So that it can handle timeouts properly and also process incoming responses
+without affecting your application's UI thread, {@code LicenseChecker} spawns a
+background thread at instantiation. In the thread it does all processing of
+license check results, whether the result is a response received from the server
+or a timeout error. At the conclusion of processing, the LVL calls your
+{@code LicenseCheckerCallback} methods from the background thread. </p>
+
+<p>To your application, this means that:</p>
+
+<ol>
+<li>Your {@code LicenseCheckerCallback} methods will be invoked, in many cases, from a
+background thread.</li>
+<li>Those methods won't be able to update state or invoke any processing in the
+UI thread, unless you create a Handler in the UI thread and have your callback
+methods post to the Handler.</li>
+</ol>
+
+<p>If you want your {@code LicenseCheckerCallback} methods to update the UI thread,
+instantiate a {@link android.os.Handler} in the main Activity's
+{@link android.app.Activity#onCreate(android.os.Bundle) onCreate()} method,
+as shown below. In this example, the LVL sample application's
+{@code LicenseCheckerCallback} methods (see above) call <code>displayResult()</code> to
+update the UI thread through the Handler's
+{@link android.os.Handler#post(java.lang.Runnable) post()} method.</p>
+
+<pre>private Handler mHandler;
+
+    &#64;Override
+    public void onCreate(Bundle savedInstanceState) {
+        ...
+        mHandler = new Handler();
+    }
+</pre>
+
+<p>Then, in your {@code LicenseCheckerCallback} methods, you can use Handler methods to
+post Runnable or Message objects to the Handler. Here's how the sample
+application included in the LVL posts a Runnable to a Handler in the UI thread
+to display the license status.</p>
+
+<pre>    private void displayResult(final String result) {
+        mHandler.post(new Runnable() {
+            public void run() {
+                mStatusText.setText(result);
+                setProgressBarIndeterminateVisibility(false);
+                mCheckLicenseButton.setEnabled(true);
+            }
+        });
+    }
+</pre>
+
+<h3 id="lc-lcc">Instantiate LicenseChecker and LicenseCheckerCallback</h3>
+
+<p>In the main Activity's
+{@link android.app.Activity#onCreate(android.os.Bundle) onCreate()} method,
+create private instances of LicenseCheckerCallback and {@code LicenseChecker}. You must
+instantiate {@code LicenseCheckerCallback} first, because you need to pass a reference
+to that instance when you call the constructor for {@code LicenseChecker}. </p>
+
+<p>When you instantiate {@code LicenseChecker}, you need to pass in these parameters:</p>
+
+<ul>
+<li>The application {@link android.content.Context}</li>
+<li>A reference to the {@code Policy} implementation to use for the license check. In
+most cases, you would use the default {@code Policy} implementation provided by the LVL,
+ServerManagedPolicy. </li>
+<li>The String variable holding your publisher account's public key for
+licensing. </li>
+</ul>
+
+<p>If you are using ServerManagedPolicy, you won't need to access the class
+directly, so you can instantiate it in the {@code LicenseChecker} constructor,
+as shown in the example below. Note that you need to pass a reference to a new
+Obfuscator instance when you construct ServerManagedPolicy.</p>
+
+<p>The example below shows the instantiation of {@code LicenseChecker} and
+{@code LicenseCheckerCallback} from the <code>onCreate()</code> method of an Activity
+class. </p>
+
+<pre>public class MainActivity extends Activity {
+    ...
+    private LicenseCheckerCallback mLicenseCheckerCallback;
+    private LicenseChecker mChecker;
+
+    &#64;Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        ...
+        // Construct the LicenseCheckerCallback. The library calls this when done.
+        mLicenseCheckerCallback = new MyLicenseCheckerCallback();
+
+        // Construct the LicenseChecker with a Policy.
+        mChecker = new LicenseChecker(
+            this, new ServerManagedPolicy(this,
+                new AESObfuscator(SALT, getPackageName(), deviceId)),
+            BASE64_PUBLIC_KEY  // Your public licensing key.
+            );
+        ...
+    }
+}
+</pre>
+
+
+<p>Note that {@code LicenseChecker} calls the {@code LicenseCheckerCallback} methods from the UI
+thread <em>only</em> if there is valid license response cached locally. If the
+license check is sent to the server, the callbacks always originate from the
+background thread, even for network errors. </p>
+
+
+<h3 id="check-access">Call checkAccess() to initiate the license check</h3>
+
+<p>In your main Activity, add a call to the <code>checkAccess()</code> method of the
+{@code LicenseChecker} instance. In the call, pass a reference to your
+{@code LicenseCheckerCallback} instance as a parameter. If you need to handle any
+special UI effects or state management before the call, you might find it useful
+to call <code>checkAccess()</code> from a wrapper method. For example, the LVL
+sample application calls <code>checkAccess()</code> from a
+<code>doCheck()</code> wrapper method:</p>
+
+<pre>    &#64;Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        ...
+        // Call a wrapper method that initiates the license check
+        doCheck();
+        ...
+    }
+    ...
+    private void doCheck() {
+        mCheckLicenseButton.setEnabled(false);
+        setProgressBarIndeterminateVisibility(true);
+        mStatusText.setText(R.string.checking_license);
+        mChecker.checkAccess(mLicenseCheckerCallback);
+    }
+</pre>
+
+
+<h3 id="account-key">Embed your public key for licensing</h3>
+
+<p>For each publisher account, the Google Play service automatically
+generates a  2048-bit RSA public/private key pair that is used exclusively for
+licensing. The key pair is uniquely associated with the publisher account and is
+shared across all applications that are published through the account. Although
+associated with a publisher account, the key pair is <em>not</em> the same as
+the key that you use to sign your applications (or derived from it).</p>
+
+<p>The Google Play publisher site exposes the public key for licensing to any
+developer signed in to the publisher account, but it keeps the private key
+hidden from all users in a secure location. When an application requests a
+license check for an application published in your account, the licensing server
+signs the license response using the private key of your account's key pair.
+When the LVL receives the response, it uses the public key provided by the
+application to verify the signature of the license response. </p>
+
+<p>To add licensing to an application, you must obtain your publisher account's
+public key for licensing and copy it into your application. Here's how to find
+your account's public key for licensing:</p>
+
+<ol>
+<li>Go to the Google Play <a
+href="http://play.google.com/apps/publish">publisher site</a> and sign in.
+Make sure that you sign in to the account from which the application you are
+licensing is published (or will be published). </li>
+<li>In the account home page, locate the "Edit profile" link and click it. </li>
+<li>In the Edit Profile page, locate the "Licensing" pane, shown below. Your
+public key for licensing is given in the "Public key" text box. </li>
+</ol>
+
+<p>To add the public key to your application, simply copy/paste the key string
+from the text box into your application as the value of the String variable
+<code>BASE64_PUBLIC_KEY</code>. When you are copying, make sure that you have
+selected the entire key string, without omitting any characters. </p>
+
+<p>Here's an example from the LVL sample application:</p>
+
+<pre>    public class MainActivity extends Activity {
+        private static final String BASE64_PUBLIC_KEY = "MIIBIjANBgkqhkiG ... "; //truncated for this example
+    ...
+    }
+</pre>
+
+<h3 id="handler-cleanup">Call your LicenseChecker's onDestroy() method
+to close IPC connections</h3>
+
+<p>Finally, to let the LVL clean up before your application
+{@link android.content.Context} changes, add a call to the {@code LicenseChecker}'s
+<code>onDestroy()</code> method from your Activity's
+{@link android.app.Activity#onDestroy()} implementation. The call causes the
+{@code LicenseChecker} to properly close any open IPC connection to the Google Play
+application's ILicensingService and removes any local references to the service
+and handler.</p>
+
+<p>Failing to call the {@code LicenseChecker}'s <code>onDestroy()</code> method
+can lead to problems over the lifecycle of your application. For example, if the
+user changes screen orientation while a license check is active, the application
+{@link android.content.Context} is destroyed. If your application does not
+properly close the {@code LicenseChecker}'s IPC connection, your application will crash
+when the response is received. Similarly, if the user exits your application
+while a license check is in progress,  your application will crash when the
+response is received, unless it has properly called the
+{@code LicenseChecker}'s <code>onDestroy()</code> method to disconnect from the service.
+</p>
+
+<p>Here's an example from the sample application included in the LVL, where
+<code>mChecker</code> is the {@code LicenseChecker} instance:</p>
+
+<pre>    &#64;Override
+    protected void onDestroy() {
+        super.onDestroy();
+        mChecker.onDestroy();
+        ...
+    }
+</pre>
+
+<p>If you are extending or modifying {@code LicenseChecker}, you might also need to call
+the {@code LicenseChecker}'s <code>finishCheck()</code> method, to clean up any open IPC
+connections.</p>
+
+<h2 id="impl-DeviceLimiter">Implementing a DeviceLimiter</h2>
+
+<p>In some cases, you might want your {@code Policy} to limit the number of actual
+devices that are permitted to use a single license. This would prevent a user
+from moving a licensed application onto a number of devices and using the
+application on those devices under the same account ID. It would also prevent a
+user from "sharing" the application by providing the account information
+associated with the license to other individuals, who could then sign in to that
+account on their devices and access the license to the application. </p>
+
+<p>The LVL supports per-device licensing by providing a
+<code>DeviceLimiter</code> interface, which declares a single method,
+<code>allowDeviceAccess()</code>. When a LicenseValidator is handling a response
+from the licensing server, it calls <code>allowDeviceAccess()</code>, passing a
+user ID string extracted from the response.</p>
+
+<p>If you do not want to support device limitation, <strong>no work is
+required</strong> &mdash; the {@code LicenseChecker} class automatically uses a default
+implementation called NullDeviceLimiter. As the name suggests, NullDeviceLimiter
+is a "no-op" class whose <code>allowDeviceAccess()</code> method simply returns
+a <code>LICENSED</code> response for all users and devices. </p>
+
+<div style="border-left:4px solid #FFCF00;margin:1em;padding: 0 0 0 .5em">
+<p><strong>Caution:</strong> Per-device licensing is <em>not recommended for
+most applications</em> because:</p>
+<ul>
+<li>It requires that you provide a backend server to manage a users and devices
+mapping, and </li>
+<li>It could inadvertently result in a user being denied access to an
+application that they have legitimately purchased on another device.</li>
+</ul>
+</div>
+
+
+
+
+
+
+
+
+
+
+
+<h2 id="app-obfuscation">Obfuscating Your Code</h2>
+
+<p>To ensure the security of your application, particularly for a paid
+application that uses licensing and/or custom constraints and protections, it's
+very important to obfuscate your application code. Properly obfuscating your
+code makes it more difficult for a malicious user to decompile the application's
+bytecode, modify it &mdash; such as by removing the license check &mdash;
+and then recompile it.</p>
+
+<p>Several obfuscator programs are available for Android applications, including
+<a href="http://proguard.sourceforge.net/">ProGuard</a>, which also offers
+code-optimization features. The use of ProGuard or a similar program to obfuscate
+your code is <em>strongly recommended</em> for all applications that use Google
+Play Licensing. </p>
+
+<h2 id="app-publishing">Publishing a Licensed Application</h2>
+
+<p>When you are finished testing your license implementation, you are ready to
+publish the application on Google Play. Follow the normal steps to <a
+href="{@docRoot}guide/publishing/preparing.html">prepare</a>, <a
+href="{@docRoot}guide/publishing/app-signing.html">sign</a>, and then <a
+href="{@docRoot}guide/publishing/publishing.html">publish the application</a>.
+</p>
+
+<h3>Removing Copy Protection</h3>
+
+<p>After uploading your licensed application, remember to remove copy protection
+from the application, if it is currently used. To check and remove copy
+protection, sign in to the publisher site and go the application's upload
+details page. In the Publishing options section, make sure that the Copy
+Protection radio button selection is "Off".</p>
+
+
+<h2 id="support">Where to Get Support</h2>
+
+<p>If you have questions or encounter problems while implementing or deploying
+publishing in your applications, please use the support resources listed in the
+table below. By directing your queries to the correct forum, you can get the
+support you need more quickly. </p>
+
+<p class="table-caption"><strong>Table 2.</strong> Developer support resources
+for Google Play Licensing Service.</p>
+
+<table>
+
+<tr>
+<th>Support Type</th>
+<th>Resource</th>
+<th>Range of Topics</th>
+</tr>
+<tr>
+<td rowspan="2">Development and testing issues</td>
+<td>Google Groups: <a
+href="http://groups.google.com/group/android-developers">android-developers</a>
+</td>
+<td rowspan="2">LVL download and integration, library projects, {@code Policy}
+questions, user experience ideas, handling of responses, {@code Obfuscator}, IPC, test
+environment setup</td>
+</tr>
+<tr>
+<td>Stack Overflow: <a
+href="http://stackoverflow.com/questions/tagged/android">http://stackoverflow.com/questions/tagged/android</a></td>
+</tr>
+<tr>
+<td rowspan="2">Accounts, publishing, and deployment issues</td>
+<td><a href="http://www.google.com/support/forum/p/Android+Market">Google Play
+Help Forum</a></td>
+<td rowspan="2">Publisher accounts, licensing key pair, test accounts, server
+responses, test responses, application deployment and results</td>
+</tr>
+<tr>
+<td><a
+href="http://market.android.com/support/bin/answer.py?answer=186113">Market
+Licensing Support FAQ</a></td>
+</tr>
+<tr>
+<td>LVL issue tracker</td>
+<td><a href="http://code.google.com/p/marketlicensing/issues/">Marketlicensing
+project issue tracker</a></td>
+<td>Bug and issue reports related specifically to the LVL source code classes
+and interface implementations</td>
+</tr>
+
+</table>
+
+<p>For general information about how to post to the groups listed above, see <a
+href="{@docRoot}resources/community-groups.html">Developer Forums</a> document
+in the Resources tab.</p>
+
+
diff --git a/docs/html/guide/market/licensing/index.jd b/docs/html/guide/market/licensing/index.jd
new file mode 100644
index 0000000..1f15303
--- /dev/null
+++ b/docs/html/guide/market/licensing/index.jd
@@ -0,0 +1,61 @@
+page.title=Application Licensing
+@jd:body
+
+
+<p>Google Play offers a licensing service that lets you enforce licensing policies for
+applications that you publish on Google Play. With Google Play Licensing, your application can
+query Google Play at run time to obtain the licensing status for the current user, then allow or
+disallow further use as appropriate. </p>
+
+<p>Using the service, you can apply a flexible licensing policy on an application-by-application
+basis&mdash;each application can enforce licensing in the way most appropriate for it. If necessary,
+an application can apply custom constraints based on the licensing status obtained from Google Play.
+For example, an application can check the licensing status and then apply custom constraints
+that allow the user to run it unlicensed for a specific validity period. An application can also
+restrict use of the application to a specific device, in addition to any other constraints. </p>
+
+<p>The licensing service is a secure means of controlling access to your applications. When an
+application checks the licensing status, the Google Play server signs the licensing status
+response using a key pair that is uniquely associated with the publisher account. Your application
+stores the public key in its compiled <code>.apk</code> file and uses it to verify the licensing
+status response.</p>
+
+<p>Any application that you publish through Google Play can use the Google Play Licensing
+service. No special account or registration is needed. Additionally, because the service uses no
+dedicated framework APIs, you can add licensing to any application that uses a minimum API level of
+3 or higher.</p>
+
+<p class="note"><strong>Note:</strong> The Google Play Licensing service is primarily intended
+for paid applications that wish to verify that the current user did in fact pay for the application
+on Google Play. However, any application (including free apps) may use the licensing service
+to initiate the download of an APK expansion file. In which case, the request that your application
+sends to the licensing service is not to check whether the user paid for the app, but to request the
+URL of the expansion files. For information about downloading expansion files for your application,
+read the guide to <a href="{@docRoot}guide/market/expansion-files.html">APK Expansion Files</a>.</p>
+
+
+<p>To learn more about Google Play's application licensing service and start integrating it into
+your applications, read the following documents:</p>
+
+<dl>
+  <dt><strong><a href="{@docRoot}guide/market/licensing/overview.html">Licensing
+Overview</a></strong></dt>
+    <dd>Describes how the service works and what a typical licensing implementation looks
+like.</dd>
+  <dt><strong><a href="{@docRoot}guide/market/licensing/setting-up.html">Setting Up for
+Licensing</a></strong></dt>
+    <dd>Explains how to set up your Google Play account, development environment, and
+testing environment in order to add licensing to your app.</dd>
+  <dt><strong><a href="{@docRoot}guide/market/licensing/adding-licensing.html">Adding
+Licensing to Your App</a></strong></dt>
+    <dd>Provides a step-by-step guide to add licensing verification to your application.</dd>
+  <dt><strong><a href="{@docRoot}guide/market/licensing/licensing-reference.html">Licensing
+Reference</a></strong></dt>
+    <dd>Provides detailed information about the licensing library's classes and the service response
+codes.</dd>
+</dl>
+
+
+
+
+
diff --git a/docs/html/guide/market/licensing/licensing-reference.jd b/docs/html/guide/market/licensing/licensing-reference.jd
new file mode 100644
index 0000000..0a7e033
--- /dev/null
+++ b/docs/html/guide/market/licensing/licensing-reference.jd
@@ -0,0 +1,439 @@
+page.title=Licensing Reference
+parent.title=Application Licensing
+parent.link=index.html
+@jd:body
+
+
+
+<div id="qv-wrapper">
+<div id="qv">
+  
+  <h2>In this document</h2>
+  <ol>
+    <li><a href="#lvl-summary">LVL Classes and Interfaces</a></li>
+    <li><a href="#server-response-codes">Server Response Codes</a></li>
+    <li><a href="#extras">Server Response Extras</a></li>
+  </ol>
+
+</div>
+</div>
+
+
+<h2 id="lvl-summary">LVL Classes and Interfaces</h2>
+
+<p>Table 1 lists all of the source files in the License Verification
+Library (LVL) available through the Android SDK. All of the files are part of
+the <code>com.android.vending.licensing</code> package.</p>
+
+<p class="table-caption"><strong>Table 1.</strong> Summary of LVL library
+classes and interfaces.</p>
+
+<div style="width:99%">
+<table width="100%">
+
+<tr>
+<th width="15%">Category</th>
+<th width="20%">Name</th>
+<th width="100%">Description</th>
+</tr>
+
+<tr>
+<td rowspan="2">License check and result</td>
+<td>LicenseChecker</td>
+<td>Class that you instantiate (or subclass) to initiate a license check.</td>
+</tr>
+<tr>
+<td><em>LicenseCheckerCallback</em></td>
+<td>Interface that you implement to handle result of the license check.</td>
+</tr>
+
+<tr>
+<td rowspan="3" width="15%">Policy</td>
+<td width="20%"><em>Policy</em></td>
+<td width="100%">Interface that you implement to determine whether to allow
+access to the application, based on the license response. </td>
+</tr>
+<tr>
+<td>ServerManagedPolicy</td>
+<td width="100%">Default {@code Policy} implementation. Uses settings provided by the
+licensing server to manage local storage of license data, license validity,
+retry.</td>
+</tr>
+<tr>
+<td>StrictPolicy</td>
+<td>Alternative {@code Policy} implementation. Enforces licensing based on a direct
+license response from the server only. No caching or request retry.</td>
+</tr>
+
+<tr>
+<td rowspan="2" width="15%">Data obfuscation <br><em>(optional)</em></td>
+<td width="20%"><em>Obfuscator</em></td>
+<td width="100%">Interface that you implement if you are using a {@code Policy} (such as
+ServerManagedPolicy) that caches license response data in a persistent store.
+Applies an obfuscation algorithm to encode and decode data being written or
+read.</td>
+</tr>
+<tr>
+<td>AESObfuscator</td>
+<td>Default Obfuscator implementation that uses AES encryption/decryption
+algorithm to obfuscate/unobfuscate data.</td>
+</tr>
+
+<tr>
+<td rowspan="2" width="15%">Device limitation<br><em>(optional)</em></td>
+<td width="20%"><em>DeviceLimiter</em></td>
+<td width="100%">Interface that you implement if you want to restrict use of an
+application to a specific device. Called from LicenseValidator. Implementing
+DeviceLimiter is not recommended for most applications because it requires a
+backend server and may cause the user to lose access to licensed applications,
+unless designed with care.</td>
+</tr>
+<tr>
+<td>NullDeviceLimiter</td>
+<td>Default DeviceLimiter implementation that is a no-op (allows access to all
+devices).</td>
+</tr>
+
+<tr>
+<td rowspan="6" width="15%">Library core, no integration needed</td>
+<td width="20%">ResponseData</td>
+<td width="100%">Class that holds the fields of a license response.</td>
+</tr>
+<tr>
+<td>LicenseValidator</td>
+<td>Class that decrypts and verifies a response received from the licensing
+server.</td>
+</tr>
+<tr>
+<td>ValidationException</td>
+<td>Class that indicates errors that occur when validating the integrity of data
+managed by an Obfuscator.</td>
+</tr>
+<tr>
+<td>PreferenceObfuscator</td>
+<td>Utility class that writes/reads obfuscated data to the system's
+{@link android.content.SharedPreferences} store.</td>
+</tr>
+<tr>
+<td><em>ILicensingService</em></td>
+<td>One-way IPC interface over which a license check request is passed to the
+Google Play client.</td>
+</tr>
+<tr>
+<td><em>ILicenseResultListener</em></td>
+<td>One-way IPC callback implementation over which the application receives an
+asynchronous response from the licensing server.</td>
+</tr>
+
+</table>
+</div>
+
+
+<h2 id="server-response-codes">Server Response Codes</h2>
+
+<p>Table 2 lists all of the license response codes supported by the
+licensing server. In general, an application should handle all of these response
+codes. By default, the LicenseValidator class in the LVL provides all of the
+necessary handling of these response codes for you. </p>
+
+<p class="table-caption"><strong>Table 2.</strong> Summary of response codes
+returned by the Google Play server in a license response.</p>
+
+<table>
+
+<tr>
+<th>Response Code</th>
+<th>Description</th>
+<th>Signed?</th>
+<th>Extras</th>
+<th>Comments</th>
+</tr>
+<tr>
+<td>{@code LICENSED}</td>
+<td>The application is licensed to the user. The user has purchased the
+application or the application only exists as a draft.</td>
+<td>Yes</td>
+<td><code>VT</code>,&nbsp;<code>GT</code>, <code>GR</code></td>
+<td><em>Allow access according to {@code Policy} constraints.</em></td>
+</tr>
+<tr>
+<td>{@code LICENSED_OLD_KEY}</td>
+<td>The application is licensed to the user, but there is an updated application
+version available that is signed with a different key. </td>
+<td>Yes </td>
+<td><code>VT</code>, <code>GT</code>, <code>GR</code>, <code>UT</code></td>
+<td><em>Optionally allow access according to {@code Policy} constraints.</em>
+<p style="margin-top:.5em;">Can indicate that the key pair used by the installed
+application version is invalid or compromised. The application can allow access
+if needed or inform the user that an upgrade is available and limit further use
+until upgrade.</p>
+</td>
+</tr>
+<tr>
+<td>{@code NOT_LICENSED}</td>
+<td>The application is not licensed to the user.</td>
+<td>No</td>
+<td></td>
+<td><em>Do not allow access.</em></td>
+</tr>
+<tr>
+<td>{@code ERROR_CONTACTING_SERVER}</td>
+<td>Local error &mdash; the Google Play application was not able to reach the
+licensing server, possibly because of network availability problems. </td>
+<td>No</td>
+<td></td>
+<td><em>Retry the license check according to {@code Policy} retry limits.</em></td>
+</tr>
+<tr>
+<td>{@code ERROR_SERVER_FAILURE}</td>
+<td>Server error &mdash; the server could not load the publisher account's key
+pair for licensing.</td>
+<td>No</td>
+<td></td>
+<td><em>Retry the license check according to {@code Policy} retry limits.</em>
+</td>
+</tr>
+<tr>
+<td>{@code ERROR_INVALID_PACKAGE_NAME}</td>
+<td>Local error &mdash; the application requested a license check for a package
+that is not installed on the device. </td>
+<td>No </td>
+<td></td>
+<td><em>Do not retry the license check.</em>
+<p style="margin-top:.5em;">Typically caused by a development error.</p>
+</td>
+</tr>
+<tr>
+<td>{@code ERROR_NON_MATCHING_UID}</td>
+<td>Local error &mdash; the application requested a license check for a package
+whose UID (package, user ID pair) does not match that of the requesting
+application. </td>
+<td>No </td>
+<td></td>
+<td><em>Do not retry the license check.</em>
+<p style="margin-top:.5em;">Typically caused by a development error.</p>
+</td>
+</tr>
+<tr>
+<td>{@code ERROR_NOT_MARKET_MANAGED}</td>
+<td>Server error &mdash; the application (package name) was not recognized by
+Google Play. </td>
+<td>No</td>
+<td></td>
+<td><em>Do not retry the license check.</em>
+<p style="margin-top:.5em;">Can indicate that the application was not published
+through Google Play or that there is an development error in the licensing
+implementation.</p>
+</td>
+</tr>
+
+</table>
+
+<p class="note"><strong>Note:</strong> As documented in <a
+href="{@docRoot}guide/market/licensing/setting-up.html#test-env">
+Setting Up The Testing Environment</a>, the response code can be manually
+overridden for the application developer and any registered test users via the
+Google Play publisher site.
+<br/><br/>
+Additionally, as noted above, applications that are in draft mode (in other
+words, applications that have been uploaded but have <em>never</em> been
+published) will return {@code LICENSED} for all users, even if not listed as a test
+user. Since the application has never been offered for download, it is assumed
+that any users running it must have obtained it from an authorized channel for
+testing purposes.</p>
+
+
+
+
+<h2 id="extras">Server Response Extras</h2>
+
+<p>To assist your application in managing access to the application across the application refund
+period and provide other information, The licensing server includes several pieces of
+information in the license responses. Specifically, the service provides recommended values for the
+application's license validity period, retry grace period, maximum allowable retry count, and other
+settings. If your application uses <a href="{@docRoot}guide/market/expansion-files.html">APK
+expansion files</a>, the response also includes the file names, sizes, and URLs. The server appends
+the settings as key-value pairs in the license response "extras" field. </p>
+
+<p>Any {@code Policy} implementation can extract the extras settings from the license
+response and use them as needed. The LVL default {@code Policy} implementation, <a
+href="{@docRoot}guide/market/licensing/adding-licensing.html#ServerManagedPolicy">{@code
+ServerManagedPolicy}</a>, serves as a working
+implementation and an illustration of how to obtain, store, and use the
+settings. </p>
+
+<p class="table-caption"><strong>Table 3.</strong> Summary of
+license-management settings supplied by the Google Play server in a license
+response.</p>
+
+<table>
+<tr>
+<th>Extra</th><th>Description</th>
+</tr>
+
+<tr>
+  <td>{@code VT}</td>
+  <td>License validity timestamp. Specifies the date/time at which the current
+(cached) license response expires and must be rechecked on the licensing server. See the section
+below about <a href="#VT">License validity period</a>.
+ </td>
+</tr>
+<tr>
+  <td>{@code GT}</td>
+  <td>Grace period timestamp. Specifies the end of the period during which a
+Policy may allow access to the application, even though the response status is
+{@code RETRY}. <p>The value is managed by the server, however a typical value would be 5
+or more days. See the section
+below about <a href="#GTGR">Retry period and maximum retry count</a>.</p></td>
+</tr>
+<tr>
+  <td>{@code GR}</td>
+  <td>Maximum retries count. Specifies how many consecutive {@code RETRY} license checks
+the {@code Policy} should allow, before denying the user access to the application.
+<p>The value is managed by the server, however a typical value would be "10" or
+higher. See the section
+below about <a href="#GTGR">Retry period and maximum retry count</a>.</p></td>
+</tr>
+<tr>
+  <td>{@code UT}</td>
+  <td>Update timestamp. Specifies the day/time when the most recent update to
+this application was uploaded and published. <p>The server returns this extra
+only for {@code LICENSED_OLD_KEYS} responses, to allow the {@code Policy} to determine how much
+time has elapsed since an update was published with new licensing keys before
+denying the user access to the application. </p></td>
+</tr>
+
+
+<!-- APK EXPANSION FILE RESPONSES -->
+
+<tr>
+  <td>{@code FILE_URL1} or {@code FILE_URL2}</td>
+  <td>The URL for an expansion file (1 is for the main file, 2 is the patch file). Use this to
+download the file over HTTP.</td>
+</tr>
+<tr>
+  <td>{@code FILE_NAME1} or {@code FILE_NAME2}</td>
+  <td>The expansion file's name (1 is for the main file, 2 is the patch file). You must use this
+name when saving the file on the device.</td>
+</tr>
+<tr>
+  <td>{@code FILE_SIZE1} or {@code FILE_SIZE2}</td>
+  <td>The size of the file in bytes (1 is for the main file, 2 is the patch file). Use this to
+assist with downloading and to ensure that enough space is available on the device's shared
+storage location before downloading.</td>
+</tr>
+
+</table>
+
+
+
+<h4 id="VT">License validity period</h4>
+
+<p>The Google Play licensing server sets a license validity period for all
+downloaded applications. The period expresses the interval of time over which an
+application's license status should be considered as unchanging and cacheable by
+a licensing {@code Policy} in the application. The licensing server includes the
+validity period in its response to all license checks, appending an
+end-of-validity timestamp to the response as an extra under the key {@code VT}. A
+{@code Policy} can extract the VT key value and use it to conditionally allow access to
+the application without rechecking the license, until the validity period
+expires. </p>
+
+<p>The license validity signals to a licensing {@code Policy} when it must recheck the
+licensing status with the licensing server. It is <em>not</em> intended to imply
+whether an application is actually licensed for use. That is, when an
+application's license validity period expires, this does not mean that the
+application is no longer licensed for use &mdash; rather, it indicates only that
+the {@code Policy} must recheck the licensing status with the server. It follows that,
+as long as the license validity period has not expired, it is acceptable for the
+{@code Policy} to cache the initial license status locally and return the cached license
+status instead of sending a new license check to the server.</p>
+
+<p>The licensing server manages the validity period as a means of helping the
+application properly enforce licensing across the refund period offered by
+Google Play for paid applications. It sets the validity period based on
+whether the application was purchased and, if so, how long ago. Specifically,
+the server sets a validity period as follows:</p>
+
+<ul>
+<li>For a paid application, the server sets the initial license validity period
+so that the license response remains valid for as long as the application is
+refundable. A licensing {@code Policy} in the application may cache the
+result of the initial license check and does not need to recheck the license
+until the validity period has expired.</li>
+<li>When an application is no longer refundable, the server
+sets a longer validity period &mdash; typically a number of days. </li>
+
+<!-- TODO: Verify the following behavior is still true w/ OBB: -->
+<li>For a free application, the server sets the validity period to a very high
+value (<code>long.MAX_VALUE</code>). This ensures that, provided the {@code Policy} has
+cached the validity timestamp locally, it will not need to recheck the
+license status of the application in the future.</li>
+</ul>
+
+<p>The {@code ServerManagedPolicy} implementation uses the extracted timestamp
+(<code>mValidityTimestamp</code>) as a primary condition for determining whether
+to recheck the license status with the server before allowing the user access to
+the application. </p>
+
+
+<h4 id="GTGR">Retry period and maximum retry count</h4>
+
+<p>In some cases, system or network conditions can prevent an application's
+license check from reaching the licensing server, or prevent the server's
+response from reaching the Google Play client application. For example, the
+user might launch an application when there is no cell network or data
+connection available&mdash;such as when on an airplane&mdash;or when the
+network connection is unstable or the cell signal is weak. </p>
+
+<p>When network problems prevent or interrupt a license check, the Google
+Play client notifies the application by returning a {@code RETRY} response code to
+the {@code Policy}'s <code>processServerResponse()</code> method. In the case of system
+problems, such as when the application is unable to bind with Google Play's
+{@code ILicensingService} implementation, the {@code LicenseChecker} library itself calls the
+Policy <code>processServerResonse()</code> method with a {@code RETRY} response code.
+</p>
+
+<p>In general, the {@code RETRY} response code is a signal to the application that an
+error has occurred that has prevented a license check from completing.
+
+<p>The Google Play server helps an application to manage licensing under
+error conditions by setting a retry "grace period" and a recommended maximum
+retries count. The server includes these values in all license check responses,
+appending them as extras under the keys {@code GT} and {@code GR}. </p>
+
+<p>The application {@code Policy} can extract the {@code GT} and {@code GR} extras and use them to
+conditionally allow access to the application, as follows:</p>
+
+<ul>
+<li>For a license check that results in a {@code RETRY} response, the {@code Policy} should
+cache the {@code RETRY} response code and increment a count of {@code RETRY} responses.</li>
+<li>The {@code Policy} should allow the user to access the application, provided that
+either the retry grace period is still active or the maximum retries count has
+not been reached.</li>
+</ul>
+
+<p>The {@code ServerManagedPolicy} uses the server-supplied {@code GT} and {@code GR} values as
+described above. The example below shows the conditional handling of the retry
+responses in the <code>allow()</code> method. The count of {@code RETRY} responses is
+maintained in the <code>processServerResponse()</code> method, not shown. </p>
+
+
+<pre>    
+public boolean allowAccess() {
+    long ts = System.currentTimeMillis();
+    if (mLastResponse == LicenseResponse.LICENSED) {
+        // Check if the LICENSED response occurred within the validity timeout.
+        if (ts &lt;= mValidityTimestamp) {
+            // Cached LICENSED response is still valid.
+            return true;
+        }
+    } else if (mLastResponse == LicenseResponse.RETRY &amp;&amp;
+                ts &lt; mLastResponseTime + MILLIS_PER_MINUTE) {
+        // Only allow access if we are within the retry period or we haven't used up our
+        // max retries.
+        return (ts &lt;= mRetryUntil || mRetryCount &lt;= mMaxRetries);
+    }
+    return false;
+}</pre>
+
diff --git a/docs/html/guide/market/licensing/overview.jd b/docs/html/guide/market/licensing/overview.jd
new file mode 100644
index 0000000..05a3a40
--- /dev/null
+++ b/docs/html/guide/market/licensing/overview.jd
@@ -0,0 +1,245 @@
+page.title=Licensing Overview
+parent.title=Application Licensing
+parent.link=index.html
+@jd:body
+
+
+<div id="qv-wrapper">
+<div id="qv">
+  
+  <h2>Quickview</h2>
+  <ul>
+    <li>Licensing allows you to verify your app was purchased from Google Play</li>
+    <li>Your app maintains control of how it enforces its licensing status</li>
+    <li>The service is free for all developers who publish on Google Play</li>
+  </ul>
+  
+  <h2>In this document</h2>
+  <ol>
+  <li><a href="#Secure">License Responses are Secure</a></li>
+  <li><a href="#LVL">Licensing Verification Library</a></li>
+  <li><a href="#Reqs">Requirements and Limitations</a></li>
+  <li><a href="#CopyProtection">Replacement for Copy Protection</a></li>
+</ol>
+  
+</div>
+</div>
+
+
+<p>Google Play Licensing is a network-based service that lets an application query a trusted
+Google Play licensing server to determine whether the application is licensed to the current
+device user. The licensing service is based on the capability of the Google Play licensing server
+to determine whether a given user is licensed to use a given application. Google Play considers a
+user to be licensed if the user is a recorded purchaser of the application.</p>
+
+<p>The request starts when your application makes a request to a service hosted by
+the Google Play client application. The Google Play application then sends a request to
+the licensing server and receives the result. The Google Play application sends
+the result to your application, which can allow or disallow further use of the
+application as needed.</p>
+
+<p class="note"><strong>Note:</strong> If a paid application has been uploaded to Google Play but
+saved only as a draft application (the app is unpublished), the licensing server considers all users
+to be licensed users of the application (because it's not even possible to purchase the app).
+This exception is necessary in order for you to perform testing of your licensing
+implementation.</p>
+
+
+<div class="figure" style="width:469px">
+<img src="{@docRoot}images/licensing_arch.png" alt=""/>
+<p class="img-caption"><strong>Figure 1.</strong> Your application initiates a
+license check through the License Verification Library and the Google Play
+client, which handles communication with the Google Play server.</p>
+</div>
+
+
+<p>To properly identify the user and determine the license status, the licensing server requires
+information about the application and user&mdash;your application and the Google Play client work
+together to assemble the information and the Google Play client passes it to the server. </p>
+
+<p>To help you add licensing to your application, the Android SDK provides a downloadable set of
+library sources that you can include in your application project: the "Google Market Licensing
+package." The License Verification Library (LVL) is a library you can add to your application that
+handles all of the licensing-related communication with the Google Play licensing service. With
+the LVL added to your application, your application can determine its licensing status for the
+current user by simply calling a method and implementing a callback that receives the status
+response.</p>
+
+<p>Your application does not query the licensing server
+directly, but instead calls the Google Play client over remote IPC to
+initiate a license request. In the license request:</p>
+
+<ul>
+<li>Your application provides: its package name, a nonce that is later used to
+validate any response from the server, and a callback over which the
+response can be returned asynchronously.</li>
+<li>The Google Play client collects the necessary information about the user and the device,
+such as the device's primary Google account username, IMSI, and other
+information. It then sends the license check request to the server on behalf of
+your application.</li>
+<li>The Google Play server evaluates the request using all available information, attempting
+to establish the user's identity to a sufficient level of confidence. The server
+then checks the user identity against purchase records for your application and
+returns a license response, which the Google Play client returns to your
+application over the IPC callback.</li>
+</ul>
+
+<p>You can choose when, and how often, you want your application to check its
+license and you have full control over how it handles the response, verifies the
+signed response data, and enforces access controls.</p>
+
+<p>Notice that during a license check, your application does not manage any
+network connections or use any licensing related APIs in the Android platform.</p>
+
+
+
+
+<h2 id="Secure">License Responses are Secure</h2>
+
+<p>To ensure the integrity of each license query, the server signs the license
+response data using an RSA key pair that is shared exclusively between the Google Play
+server and you.</p>
+
+<p>The licensing service generates a single licensing key pair for each
+publisher account and exposes the public key in your account's profile page. You must copy the
+public key from the web site and embed it in your application source code. The server retains the
+private key internally and uses it to sign license responses for the applications you
+publish with that account.</p>
+
+<p>When your application receives a signed response, it uses the embedded public
+key to verify the data. The use of public key cryptography in the licensing
+service makes it possible for the application to detect responses that have been
+tampered with or that are spoofed.</p>
+
+
+
+
+<h2 id="LVL">Licensing Verification Library</h2>
+
+<p>The Android SDK provides a downloadable component called the "Google Market Licensing package,"
+which includes the License Verification Library (LVL). The LVL greatly simplifies the process of
+adding licensing to your application and helps ensure a more secure, robust implementation for your
+application. The LVL provides internal classes that handle most of the standard operations of a
+license query, such as contacting the Google Play client to initiate a license request and
+verifying and validating the responses. It also exposes interfaces that let you easily plug in your
+custom code for defining licensing policy and managing access as needed by your application. The key
+LVL interfaces are: </p>
+
+<dl>
+<dt>{@code Policy}</dt>
+  <dd>Your implementation determines whether to allow access to the
+application, based on the license response received from the server and any
+other data available (such as from a backend server associated with your
+application). The implementation can evaluate the various fields of the license
+response and apply other constraints, if needed. The implementation also lets
+you manage the handling of license checks that result in errors, such as network
+errors.</dd>
+
+<dt>{@code LicenseCheckerCallback}</dt>
+  <dd>Your implementation manages access to the
+application, based on the result of the {@code Policy} object's handling of the license
+response. Your implementation can manage access in any way needed, including
+displaying the license result in the UI or directing the user to purchase the
+application (if not currently licensed).</dd>
+</dl>
+
+
+<p>To help you get started with a {@code Policy}, the LVL provides two fully complete
+{@code Policy} implementations that you can use without modification or adapt to your
+needs:</p>
+
+<dl>
+<dt><a href="adding-licensing.html#ServerManagedPolicy">{@code ServerManagedPolicy}</a></dt>
+  <dd>A flexible {@code Policy}
+that uses settings provided by the licensing server to manage response caching
+and access to the application while the device is offline (such as when the
+user is on an airplane). For most applications, the use of
+{@code ServerManagedPolicy} is highly recommended.</dd>
+
+<dt><a href="adding-licensing.html#StrictPolicy">{@code StrictPolicy}</a></dt>
+  <dd>A restrictive {@code Policy} that
+does not cache any response data and allows the application access <em>only</em>
+when the server returns a licensed response.</dd>
+</dl>
+
+<p>The LVL is available as a downloadable component of the Android SDK. The
+component includes both the LVL itself and an example application that shows how
+the library should be integrated with your application and how your application
+should manage response data, UI interaction, and error conditions. </p>
+
+<p>The LVL sources are provided as an Android <em>library project</em>, which
+means that you can maintain a single set of library sources and share them
+across multiple applications. A full test environment is also available through
+the SDK, so you can develop and test the licensing implementation in your
+applications before publishing them, even if you don't have access to a
+physical device.</p>
+
+
+
+
+<h2 id="Reqs">Requirements and Limitations</h2>
+
+<p>Google Play Licensing is designed to let you apply license controls to
+applications that you publish through Google Play. The service is not
+designed to let you control access to applications that are not published
+through Google Play or that are run on devices that do not offer the Google
+Play client. </p>
+
+<p>Here are some points to keep in mind as you implement licensing in your
+application: </p>
+
+<ul>
+<li>An application can use the service only if the Google Play client is
+installed on its host device and the device is running Android 1.5 (API level 3)
+or higher.</li>
+<li>To complete a license check, the licensing server must be accessible over
+the network. You can implement license caching behaviors to manage access to your application when
+there is no network connectivity. </li>
+<li>The security of your application's licensing controls ultimately relies on
+the design of your implementation itself. The service provides the building
+blocks that let you securely check licensing, but the actual enforcement and
+handling of the license are factors are up to you. By following the best
+practices in the following documents, you can help ensure that your implementation will be
+secure.</li>
+<li>Adding licensing to an application does not affect the way the application
+functions when run on a device that does not offer Google Play.</li>
+<li>You can implement licensing controls for a free app, but only if you're using the service to 
+provide <a
+href="{@docRoot}guide/market/expansion-files.html">APK expansion files</a>.</li>
+</ul>
+
+
+
+<h2 id="CopyProtection">Replacement for Copy Protection</h2>
+
+<p>Google Play Licensing is a flexible, secure mechanism for controlling
+access to your applications. It effectively replaces the Copy Protection
+mechanism offered on Google Play and gives you wider distribution
+potential for your applications. </p>
+
+<ul>
+<li>A limitation of the legacy Copy Protection mechanism on Google Play is
+that applications using it can be installed only on compatible devices that
+provide a secure internal storage environment. For example, a copy-protected
+application cannot be downloaded from Google Play to a device that provides root
+access, and the application cannot be installed to a device's SD card. </li>
+<li>With Google Play licensing, you can move to a license-based model in
+which access is not bound to the characteristics of the host device, but to your
+publisher account on Google Play and the licensing policy that you define.
+Your application can be installed and controlled on any compatible device on
+any storage, including SD card.</li>
+</ul>
+
+<p>Although no license mechanism can completely prevent all unauthorized use,
+the licensing service lets you control access for most types of normal usage,
+across all compatible devices, locked or unlocked, that run Android 1.5 or
+higher version of the platform.</p>
+
+<p>To begin adding application licensing to your application, continue to <a
+href="{@docRoot}guide/market/licensing/setting-up.html">Setting Up for Licensing</a>.</p>
+
+
+
+
+
+
diff --git a/docs/html/guide/market/licensing/setting-up.jd b/docs/html/guide/market/licensing/setting-up.jd
new file mode 100644
index 0000000..15214d1
--- /dev/null
+++ b/docs/html/guide/market/licensing/setting-up.jd
@@ -0,0 +1,707 @@
+page.title=Setting Up for Licensing
+parent.title=Application Licensing
+parent.link=index.html
+@jd:body
+
+
+<div id="qv-wrapper">
+<div id="qv">
+  
+  <h2>In this document</h2>
+  <ol>
+  <li><a href="#account">Setting Up a Publisher Account</a></li>
+  <li><a href="#dev-setup">Setting Up the Development Environment</a>
+    <ol>
+      <li><a href="#runtime-setup">Setting up the runtime environment</a></li>
+      <li><a href="#download-lvl">Downloading the LVL</a></li>
+      <li><a href="#lvl-setup">Setting Up the Licensing Verification Library</a></li>
+      <li><a href="#add-library">Including the LVL library project sources in your
+application</a></li>
+    </ol>
+  </li>
+  <li><a href="#test-env">Setting Up the Testing Environment</a>
+    <ol>
+      <li><a href="#test-response">Setting test responses for license checks</a></li>
+      <li><a href="#test-acct-setup">Setting up test accounts</a></li>
+      <li><a href="#acct-signin">Signing in to an authorized account in the runtime
+environment</a></li>
+    </ol>
+  </li>
+</ol>
+</div>
+</div>
+
+<p>Before you start adding license verification to your application, you need to set up your Google
+Play publishing account, your development environment, and test accounts required to verify
+your implementation.</p>
+
+
+<h2 id="account">Setting Up a Publisher Account</h2>
+
+<p>If you don't already have a publisher account for Google Play, you need to register for one
+using your Google account and agree to the terms of service on the Google Play publisher site:</p>
+
+<p style="margin-left:2em;"><a
+href="http://play.google.com/apps/publish">http://play.google.com/apps/publish</a>
+</p>
+
+<p>For more information, see <a
+href="{@docRoot}guide/publishing/publishing.html">Publishing on Google Play</a>.</p>
+
+<p>If you already have a publisher account on Google Play, use your existing
+account to set up licensing.</p>
+
+<p>Using your publisher account on Google Play, you can:</p>
+
+<ul>
+<li>Obtain a public key for licensing</li>
+<li>Debug and test an application's licensing implementation, prior to
+publishing the application</li>
+<li>Publish the applications to which you have added licensing support</li>
+</ul>
+
+<h4>Administrative settings for licensing</h4>
+
+<p>You can manage several
+administrative controls for Google Play licensing on the publisher site. The controls are available
+in the Edit Profile page, in the "Licensing" panel, shown in figure 1. The controls
+let you: </p>
+
+<ul>
+<li>Set up multiple "test accounts," identified by email address. The licensing
+server allows users signed in to test accounts on a device or emulator to send
+license checks and receive static test responses.</li>
+<li>Obtain the account's public key for licensing. When you are implementing
+licensing in an application, you must copy the public key string into the
+application.</li>
+<li>Configure static test responses that the server sends, when it receives a
+license check for an application uploaded to the publisher account, from a user
+signed in to the publisher account or a test account.</li>
+</ul>
+
+
+<img src="{@docRoot}images/licensing_public_key.png" alt=""/>
+<p class="img-caption"><strong>Figure 1.</strong> The Licensing
+panel of your account's Edit Profile page lets you manage administrative
+settings for licensing.</p>
+
+<p>For more information about how to work with test accounts and static test
+responses, see <a href="#test-env">Setting Up a Testing Environment</a>, below.
+
+
+
+<h2 id="dev-setup">Setting Up the Development Environment</h2>
+
+<p>Setting up your environment for licensing involves these tasks:</p>
+
+<ol>
+<li><a href="#runtime-setup">Setting up the runtime environment</a> for development</li>
+<li><a href="#download-lvl">Downloading the LVL</a> into your SDK </li>
+<li><a href="#lvl-setup">Setting up the Licensing Verification Library</a></li>
+<li><a href="#add-library">Including the LVL library project in your application</a></li>
+</ol>
+
+<p>The sections below describe these tasks. When you are done with setup,
+you can begin <a href="{@docRoot}guide/market/licensing/adding-licensing.html">Adding
+Licensing to Your App</a>.</p>
+
+<p>To get started, you need to set up a proper runtime environment on which
+you can run, debug, and test your application's implementation of license
+checking and enforcement. </p>
+
+
+<h3 id="runtime-setup">Setting up the runtime environment</h3>
+
+<p>As described earlier, applications check licensing status not by contacting
+the licensing server directly, but by binding to a service provided by the
+Google Play application and initiating a license check request. The Google
+Play service then handles the direct communication with the licensing server
+and finally routes the response back to your application. To debug and test
+licensing in your application, you need to set up a runtime environment that
+includes the necessary Google Play service, so that your application is able
+to send license check requests to the licensing server. </p>
+
+<p>There are two types of runtime environment that you can use: </p>
+
+<ul>
+<li>An Android-powered device that includes the Google Play application, or</li>
+<li>An Android emulator running the Google APIs Add-on, API level 8 (release 2)
+or higher</li>
+</ul>
+
+<h4 id="runtime-device">Running on a device</h4>
+
+<p>To use an Android-powered device for
+debugging and testing licensing, the device must:</p>
+
+<ul>
+<li>Run a compatible version of Android 1.5 or later (API level
+3 or higher) platform, <em>and</em> </li>
+<li>Run a system image on which the Google Play client application
+is preinstalled. </li>
+</ul>
+
+<p>If Google Play is not preinstalled in the system image, your application won't
+be able to communicate with the Google Play licensing server. </p>
+
+<p>For general information about how to set up a device for use in developing
+Android applications, see <a
+href="{@docRoot}guide/developing/device.html">Using Hardware Devices</a>.</p>
+
+<h4 id="runtime-emulator">Running on an Android emulator</h4>
+
+<p>If you don't have a device available, you can use an Android emulator for debugging and testing
+licensing.</p>
+
+<p>Because the Android platforms provided in the Android SDK <em>do
+not</em> include Google Play, you need to download the Google APIs Add-On
+platform, API level 8 (or higher), from the SDK repository. After downloading
+the add-on, you need to create an AVD configuration that uses that system image.
+</p>
+
+<p>The Google APIs Add-On does not include the full Google Play client.
+However, it does provide: </p>
+
+<ul>
+<li>An Google Play background service that implements the
+<code>ILicensingService</code> remote interface, so that your application can
+send license checks over the network to the licensing server. </li>
+<li>A set of underlying account services that let you add an a Google account on
+the AVD and sign in using your publisher account or test account credentials.
+<p>Signing in using your publisher or test account enables you to debug and test
+your application without having publish it. For more information see <a
+href="#acct-signin">Signing in to an authorized account</a>, below.</p></li>
+</ul>
+
+<p>Several versions of the add-on are available through the SDK Manager, but only
+<strong>Google APIs Add-On, API 8 (release 2) or higher</strong> includes the necessary Google
+Play services.</p>
+
+
+<img src="{@docRoot}images/licensing_gapis_8.png" alt=""/>
+<p class="img-caption"><strong>Figure 2.</strong> Google APIs
+Add-On, API 8 (release 2) or higher lets you debug and test your licensing
+implementation in an emulator.</p>
+
+<p>To set up an emulator for adding licensing to an application, follow
+these steps: </p>
+
+<ol>
+  <li>Launch the Android SDK Manager. </li>
+  <li>In the <strong>Available Packages</strong> panel, select and download the
+SDK component "Google APIs (Google Inc.) - API Level 8" (or higher) from the SDK
+repository, as shown in figure 2.
+  <p>When the download is complete, use the Android SDK Manager to
+create a new AVD based on that component, described next.</p></li>
+  <li>In the <strong>Virtual
+Devices</strong> panel of the Android SDK Manager, click
+<strong>New</strong> and set the configuration details for the new AVD. </li>
+  <li>In the dialog that appears, assign a descriptive name to the AVD and then
+use the "Target" menu to choose the "Google APIs (Google Inc.) - API Level 8" as
+the system image to run on the new AVD. Set the other configuration details as
+needed and then click <strong>Create AVD</strong> to finish. The SDK tools
+create the new AVD configuration, which then appears in the list of available
+Android Virtual Devices.</li>
+</ol>
+
+<p>If you are not familiar with AVDs or how to use them, see <a
+href="{@docRoot}guide/developing/devices/index.html">Managing Virtual Devices</a>.</p>
+
+<h4 id="project-update">Updating your project configuration</h4>
+
+<p>After you set up a runtime environment that meets the requirements described
+above &mdash; either on an actual device or on an emulator &mdash; make sure to
+update your application project or build scripts as needed, so that your compiled
+<code>.apk</code> files that use licensing are deployed into that environment.
+In particular, if you are developing in Eclipse, make sure that you set up a
+Run/Debug Configuration that targets the appropriate device or AVD. </p>
+
+<p>You do not need to make any changes to your application's
+build configuration, provided that the project is already configured to compile
+against a standard Android 1.5 (API level 3) or higher library. For example:
+
+<ul>
+<li>If you have an existing application that is compiled against
+the Android 1.5 library, you do not need to make any changes to your
+build configuration to support licensing. The build target meets the minimum
+requirements for licensing, so you would continue building
+against the same version of the Android platform.</li>
+
+<li>Similarly, if you are building against Android 1.5 (API level 3) but
+are using an emulator running the Google APIs Add-On API 8 as the application's
+runtime environment, there is no need to change your application's build
+configuration. </li>
+</ul>
+
+<p>In general, adding licensing to an application should have no impact
+whatsoever on the application's build configuration.</p>
+
+
+<h3 id="download-lvl">Downloading the LVL</h3>
+
+<p>The License Verification Library (LVL) is a collection of helper classes that
+greatly simplify the work that you need to do to add licensing to your
+application. In all cases, we recommend that you download the LVL and use it as
+the basis for the licensing implementation in your application.</p>
+
+<p>The LVL is available as a downloadable component of the Android SDK. The
+component includes: </p>
+
+<ul>
+<li>The LVL sources, stored inside an Android library project. </li>
+<li>An example application called "sample" that depends on the LVL library
+project. The example illustrates how an application uses the library helper
+classes to check and enforce licensing.</li>
+</ul>
+
+<p>To download the LVL component into your development environment, use the
+Android SDK Manager. Launch the Android SDK Manager and then
+select the "Google Market Licensing" component, as shown in figure 3.
+Accept the terms and click <strong>Install Selected</strong> to begin the download. </p>
+
+<img src="{@docRoot}images/licensing_package.png" alt=""/>
+<p class="img-caption"><strong>Figure 3.</strong> The Licensing package contains the LVL and
+the LVL sample application.</p>
+
+<p>When the download is complete, the Android SDK Manager installs both
+the LVL library project and the example application into these directories: </p>
+
+<p style="margin-left:2em"><code>&lt;<em>sdk</em>&gt;/extras/google/market_licensing/library/</code>
+&nbsp;&nbsp;(the LVL library project)<br />
+<code>&lt;<em>sdk</em>&gt;/extras/google/market_licensing/sample/</code>&nbsp;&nbsp;(the example
+application)</p>
+
+<p>If you aren't familiar with how to download components into your SDK, see the
+<a href="{@docRoot}sdk/adding-components.html">Adding SDK Components</a>
+document. </p>
+
+
+<h3 id="lvl-setup">Setting Up the Licensing Verification Library</h3>
+
+<p>After downloading the LVL to your computer, you need to set it up in your
+development environment, either as an Android library project or by
+copying (or importing) the library sources directly into your existing
+application package. In general, using the LVL as a library project is recommended,
+since it lets you reuse your licensing code across multiple applications and
+maintain it more easily over time. Note that the LVL is not designed to be
+compiled separately and added to an application as a static .jar file. </p>
+
+<h4>Moving the library sources to a new location</h4>
+
+<p>Because you will be customizing the LVL sources to some extent, you should
+make sure to <em>move or copy</em> the library sources (the entire
+directory at <code>&lt;<em>sdk</em>&gt;/market_licensing/library/</code>)
+to a working directory outside of the SDK. You should then use the relocated
+sources as your working set. If you are using a source-code management
+system, add and track the sources that are in the working location rather
+than those in default location in the SDK. </p>
+
+<p>Moving the library sources is important is because, when you later update the
+Licensing package, the SDK installs the new files to the same location as
+the older files. Moving your working library files to a safe location ensures
+that your work won't be inadvertently overwritten should you download a new
+version of the LVL.</p>
+
+<h4>Creating the LVL as a library project</h4>
+
+<div class="sidebox-wrapper">
+<div class="sidebox">
+<h2>Working with library projects</h2>
+
+<p>The LVL is provided as an Android library project, which means that you can
+share its code and resources across multiple applications. </p>
+
+<p style="margin-top:.5em;">If you aren't familiar with library projects or how
+to use them, see <a href="{@docRoot}guide/developing/projects/index.html#LibraryProjects">
+Managing Projects</a>.
+</p>
+</div>
+</div>
+
+<p>The recommended way of using the LVL is setting it up as a new Android
+<em>library project</em>. A library project is a type of development project
+that holds shared Android source code and resources. Other Android application
+projects can reference the library project and, at build time, include its
+compiled sources in their <code>.apk</code> files. In the context of licensing,
+this means that you can do most of your licensing development once, in a library
+project, then include the library sources in your various application projects.
+In this way, you can easily maintain a uniform implementation of licensing
+across all of your projects and maintain it centrally. </p>
+
+<p>The LVL is provided as a configured library project &mdash; once you have
+downloaded it, you can start using it right away. </p>
+
+<p>If you are working in Eclipse with ADT, you need to add the LVL to your
+workspace as a new development project, in the same way as you would a new
+application project. </p>
+
+<ol>
+<li>Use the New Project Wizard to create a new
+project from existing sources. Select the LVL's <code>library</code> directory
+(the directory containing the library's AndroidManifest.xml file) as the project
+root.</li>
+<li>When you are creating the library project, you can select any application
+name, package, and set other fields as needed. </li>
+<li>For the library's build target, select Android 1.5 (API level 3) or higher.</li>
+</ol>
+
+<p> When created, the project is
+predefined as a library project in its <code>project.properties</code> file, so
+no further configuration is needed. </p>
+
+<p>For more information about how to create an application project or work with
+library projects in Eclipse, see <a
+href="{@docRoot}guide/developing/projects/projects-eclipse.html">Managing Projects from
+Eclipse with ADT</a>.</p>
+
+
+<h4>Copying the LVL sources to your application</h4>
+
+<p>As an alternative to adding the LVL as a library project, you can copy the
+library sources directly into your application. To do so, copy (or import) the
+LVL's <code>library/src/com</code> directory into your application's
+<code>src/</code> directory.</p>
+
+<p>If you add the LVL sources directly to your application, you can skip the
+next section and start working with the library, as described in <a
+href="{@docRoot}guide/market/licensing/adding-licensing.html">Adding
+Licensing to Your App</a>.</p>
+
+
+<h3 id="add-library">Including the LVL library project sources in your
+application</h3>
+
+<p>If you want to use the LVL sources as a library project, you need to add a
+reference to the LVL library project in your application project properties. This tells
+build tools to include the LVL library project sources in your application at
+compile time. The process for adding a reference to a library project depends
+on your development environment, as described below.</p>
+
+<p> If you are developing in Eclipse with ADT, you should already have added the
+library project to your workspace, as described in the previous section. If you
+haven't done that already, do it now before continuing. </p>
+
+<p>Next, open the application's project properties window, as shown below.
+Select the "Android" properties group and click <strong>Add</strong>, then
+choose the LVL library project (com_android_vending_licensing) and click
+<strong>OK</strong>. For more information, see
+<a href="{@docRoot}guide/developing/projects/projects-eclipse.html#SettingUpLibraryProject">
+Managing Projects from Eclipse with ADT</a></p>.
+
+
+<img src="{@docRoot}images/licensing_add_library.png" alt=""/>
+<p class="img-caption"><strong>Figure 4.</strong> If you are
+working in Eclipse with ADT, you can add the LVL library project to your
+application from the application's project properties.</p>
+
+
+<p>If you are developing using the SDK command-line tools, navigate to the
+directory containing your application project and open the
+<code>project.properties</code> file. Add a line to the file that specifies the
+<code>android.library.reference.&lt;n&gt;</code> key and the path to the
+library. For example: </p>
+
+<pre>android.library.reference.1=path/to/library_project</pre>
+
+<p>Alternatively, you can use this command to update the project
+properties, including the reference to the library project:</p>
+
+<pre class="no-pretty-print" style="color:black">android update lib-project
+--target <em>&lt;target_ID&gt;</em> \
+--path <em>path/to/my/app_project</em> \
+--library <em>path/to/my/library_project</em>
+</pre>
+
+<p>For more information about working with library projects,
+see <a href="{@docRoot}guide/developing/projects/projects-cmdline.html#SettingUpLibraryProject">
+Setting up a Library Project</a>.</p>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+<h2 id="test-env">Setting Up the Testing Environment</h2>
+
+<p>The Google Play publisher site provides configuration tools that let you
+and others test licensing on your application before it is published. As you are
+implementing licensing, you can make use of the publisher site tools to test
+your application's Policy and handling of different licensing responses and
+error conditions.</p>
+
+<p>The main components of the test environment for licensing include: </p>
+
+<ul>
+<li>A "Test response" configuration in your publisher account that lets you
+set the static licensing response returned, when the server processes a
+license check for an application uploaded to the publisher account, from a user
+signed in to the publisher account or a test account.</li>
+<li>An optional set of test accounts that will receive the static test
+response when they check the license of an application that you have uploaded
+(regardless whether the application is published or not).</li>
+<li>A runtime environment for the application that includes the Google Play
+application or Google APIs Add-On, on which the user is signed in to the
+publisher account or one of the test accounts.</li>
+</ul>
+
+<p>Setting up the test environment properly involves:</p>
+
+<ol>
+<li><a href="#test-response">Setting static test responses</a> that are returned by the licensing server.</li>
+<li><a href="#test-acct-setup">Setting up test accounts</a> as needed.</li>
+<li><a href="#acct-signin">Signing in</a> properly to an emulator or device, before initiating a license check test.</li>
+</ol>
+
+<p>The sections below provide more information.</p>
+
+
+<h3 id="test-response">Setting test responses for license checks</h3>
+
+<p>Google Play provides a configuration setting in your publisher account
+that lets you override the normal processing of a license check and return a
+specified static response code. The setting is for testing only and applies
+<em>only</em> to license checks for applications that you have uploaded, made by
+any user signed in to an emulator or device using the credentials of the
+publisher account or a registered test account. For other users, the server
+always processes license checks according to normal rules.  </p>
+
+<p>To set a test response for your account, sign in to your publisher account
+and click "Edit Profile". In the Edit Profile page, locate the Test Response
+menu in the Licensing panel, shown below. You can select from the full set of
+valid server response codes to control the response or condition you want to
+test in your application.</p>
+
+<p>In general, you should make sure to test your application's licensing
+implementation with every response code available in the Test Response menu.
+For a description of the codes, see <a
+href="{@docRoot}guide/market/licensing/licensing-reference.html#server-response-codes">Server
+Response Codes</a> in the <a
+href="{@docRoot}guide/market/licensing/licensing-reference.html">Licensing Reference</a>.</p>
+
+<img src="{@docRoot}images/licensing_test_response.png" alt=""/>
+<p class="img-caption"><strong>Figure 5.</strong> The Licensing
+panel of your account's Edit Profile page, showing the Test Accounts field and the
+Test Response menu.</p>
+
+<p>Note that the test response that you configure applies account-wide &mdash;
+that is, it applies not to a single application, but to <em>all</em>
+applications associated with the publisher account. If you are testing multiple
+applications at once, changing the test response will affect all of those
+applications on their next license check (if the user is signed in to
+the emulator or device using the publisher account or a test account).</p>
+
+<p>Before you can successfully receive a test response for a license check,
+you must sign in to the device or emulator on which the application
+is installed, and from which it is querying the server. Specifically, you must
+sign using either your publisher account or one of the test accounts that you
+have set up. For more information about test accounts, see the next section.</p>
+
+<p>See <a
+href="{@docRoot}guide/market/licensing/licensing-reference.html#server-response-codes">Server
+Response Codes</a> for a list of
+test responses available and their meanings. </p>
+
+
+<h3 id="test-acct-setup">Setting up test accounts</h3>
+
+<p>In some cases, you might want to let multiple teams of developers test
+licensing on applications that will ultimately be published through your
+publisher account, but without giving them access to your publisher account's
+sign-in credentials. To meet that need, the Google Play publisher site lets
+you set up one or more optional <em>test accounts</em> &mdash; accounts that are
+authorized to query the licensing server and receive static test responses from
+your publisher account.</p>
+
+<p>Test accounts are standard Google accounts that you register on your
+publisher account, such that they will receive the test response for
+applications that you have uploaded. Developers can then sign in to their
+devices or emulators using the test account credentials and initiate license
+checks from installed applications. When the licensing server receives a license
+check from a user of a test account, it returns the static test response
+configured for the publisher account.  </p>
+
+<p>Necessarily, there are limitations on the access and permissions given to
+users signed in through test accounts, including:</p>
+
+<ul>
+<li>Test account users can query the licensing server only for applications that
+are already uploaded to the publisher account. </li>
+<li>Test account users do not have permission to upload applications to your
+publisher account.</li>
+<li>Test account users do not have permission to set the publisher account's
+static test response.</li>
+</ul>
+
+<p>The table below summarizes the differences in capabilities, between the
+publisher account, a test account, and any other account.</p>
+
+<p class="table-caption" id="acct-types-table"><strong>Table 1.</strong>
+Differences in account types for testing licensing.</p>
+
+<table>
+<tr>
+<th>Account Type</th>
+<th>Can check license before upload?</th>
+<th>Can receive test response?</th>
+<th>Can set test response?</th>
+</tr>
+
+<tr>
+<td>Publisher account</td>
+<td>Yes</td>
+<td>Yes</td>
+<td>Yes</td>
+</tr>
+
+<tr>
+<td>Test account</td>
+<td>No</td>
+<td>Yes</td>
+<td>No</td>
+</tr>
+
+<tr>
+<td>Other</td>
+<td>No</td>
+<td>No</td>
+<td>No</td>
+</tr>
+</table>
+
+<h4 id="reg-test-acct">Registering test accounts on the publisher account</h4>
+
+<p>To get started, you need to register each test account in your publisher
+account. As shown in Figure 5, you
+register test accounts in the Licensing panel of your publisher account's Edit
+Profile page. Simply enter the accounts as a comma-delimited list and click
+<strong>Save</strong> to save your profile changes.</p>
+
+<p>You can use any Google account as a test account. If you want to own and
+control the test accounts, you can create the accounts yourself and distribute
+the credentials to your developers or testers.</p>
+
+<h4 id="test-app-upload">Handling application upload and distribution for test
+account users</h4>
+
+<p>As mentioned above, users of test accounts can only receive static test
+responses for applications that are uploaded to the publisher account. Since
+those users do not have permission to upload applications, as the publisher you
+will need to work with those users to collect apps for upload and distribute
+uploaded apps for testing. You can handle collection and distribution in any way
+that is convenient. </p>
+
+<p>Once an application is uploaded and becomes known to the licensing server,
+developers and testers can continue modify the application in their local
+development environment, without having to upload new versions. You only need to
+upload a new version if the local application increments the
+<code>versionCode</code> attribute in the manifest file. </p>
+
+<h4 id="test-key">Distributing your public key to test account users</h4>
+
+<p>The licensing server handles static test responses in the normal way,
+including signing the license response data, adding extras parameters, and so
+on. To support developers who are implementing licensing using test accounts,
+rather than the publisher account, you will need to distribute
+your public key to them. Developers without access to the publisher site do not
+have access to your public key, and without the key they won't be able to
+verify license responses. </p>
+
+<p>Note that if you decide to generate a new licensing key pair for your account
+for some reason, you need to notify all users of test accounts. For
+testers, you can embed the new key in the application package and distribute it
+to users. For developers, you will need to distribute the new key to them
+directly. </p>
+
+
+<h3 id="acct-signin">Signing in to an authorized account in the runtime
+environment</h3>
+
+<p>The licensing service is designed to determine whether a given user is
+licensed to use a given application &mdash; during a license check, the Google
+Play application gathers the user ID from the primary account on the system
+and sends it to the server, together with the package name of the application
+and other information. However, if there is no user information available, the
+license check cannot succeed, so the Google Play application terminates the
+request and returns an error to the application. </p>
+
+<p>During testing, to ensure that your application can successfully query the
+licensing server, you must make sure that you sign in to an account <em>on the
+device or emulator</em> using:</p>
+
+<ul>
+<li>The credentials of a publisher account, or</li>
+<li>The credentials of a test account that is registered with a publisher
+account</li>
+</ul>
+
+
+<div class="sidebox-wrapper">
+<div class="sidebox">
+<h2>Signing in to a Google account on an emulator</h2>
+
+<p>If you are testing licensing on an emulator, you need to sign in to a Google
+account on the emulator. If you do not see an option to create a new Google
+account, the problem might be that your AVD is running a standard Android system
+image, rather than the Google APIs Add-On, API 8 (release 2) or higher. </p>
+
+<p style="margin-top:.5em;">For more information, see <a
+href="#runtime-setup">Setting up the runtime environment</a>, above.</p>
+
+</div>
+</div>
+
+<p>Signing in using a publisher account offers the advantage of letting your
+applications receive static test responses even before the applications are
+uploaded to the publisher site.</p>
+
+<p>If you are part of a larger organization or are working with external groups
+on applications that will be published through your site, you will more likely
+want to distribute test accounts instead, then use those to sign in during
+testing. </p>
+
+<p>To sign in on a device or emulator, follow the steps below. The preferred
+approach is to sign in as the primary account &mdash; however, if there are
+other accounts already in use on the device or emulator, you can create an
+additional account and sign in to it using the publisher or test account
+credentials.  </p>
+
+<ol>
+<li>Open Settings &gt; Accounts &amp; sync</li>
+<li>Select <strong>Add Account</strong> and choose to add a "Google" account.
+</li>
+<li>Select <strong>Next</strong> and then <strong>Sign in</strong>.</li>
+<li>Enter the username and password of either the publisher account or a test
+account that is registered in the publisher account.</li>
+<li>Select <strong>Sign in</strong>. The system signs you in to the new
+account.</li>
+</ol>
+
+<p>Once you are signed in, you can begin testing licensing in your application
+(if you have completed the LVL integration steps above). When your application
+initiates a license check, it will receive a response containing the static test
+response configured on the publisher account. </p>
+
+<p>Note that, if you are using an emulator, you will need to sign in to the
+publisher account or test account each time you wipe data when restarting the
+emulator.</p>
+
+<p>Once you've completed the setup procedures, continue to <a
+href="{@docRoot}guide/market/licensing/adding-licensing.html">Adding Licensing to Your App</a>.</p>
+
+
+
diff --git a/docs/html/guide/market/publishing/multiple-apks.jd b/docs/html/guide/market/publishing/multiple-apks.jd
index ff70e85..e7cfa33 100644
--- a/docs/html/guide/market/publishing/multiple-apks.jd
+++ b/docs/html/guide/market/publishing/multiple-apks.jd
@@ -45,7 +45,7 @@
 
   <h2>See also</h2>
 <ol>
-  <li><a href="{@docRoot}guide/appendix/market-filters.html">Market Filters</a></li>
+  <li><a href="{@docRoot}guide/appendix/market-filters.html">Filters on Google Play</a></li>
   <li><a href="{@docRoot}guide/practices/screens_support.html">Supporting Multiple Screens</a></li>
   <li><a href="{@docRoot}sdk/compatibility-library.html">Compatibility
 Package</a></li>
@@ -55,10 +55,10 @@
 </div>
 </div>
 
-<p>Multiple APK support is a feature in Android Market that allows you to publish different APKs
+<p>Multiple APK support is a feature on Google Play that allows you to publish different APKs
 for your application that are each targeted to different device configurations. Each APK is a
 complete and independent version of your application, but they share the same application listing on
-Android Market and must share the same package name and be signed with the same release key. This
+Google Play and must share the same package name and be signed with the same release key. This
 feature is useful for cases in which your application cannot reach all desired devices with a single
 APK.</p>
 
@@ -73,8 +73,8 @@
 
 <p>Although <strong>we encourage you to develop and publish a single APK</strong> that supports as
 many device configurations as possible, doing so is sometimes not possible. To help
-you publish your application for as many devices as possible, Android Market allows you to
-publish multiple APKs under the same application listing. Android Market then supplies each APK to
+you publish your application for as many devices as possible, Google Play allows you to
+publish multiple APKs under the same application listing. Google Play then supplies each APK to
 the appropriate devices based on configuration support you've declared in the manifest file of each
 APK.</p>
 
@@ -86,7 +86,7 @@
   <li>Support different platform versions with each APK.</li>
 </ul>
 
-<p>Currently, these are the only device characteristics that Android Market supports for publishing
+<p>Currently, these are the only device characteristics that Google Play supports for publishing
 multiple APKs as the same application.</p>
 
 <p class="note"><strong>Note:</strong> You should generally use multiple APKs to support
@@ -100,8 +100,8 @@
 
 <h2 id="Concepts">Publishing Concepts</h2>
 
-<p>Before you start publishing multiple APKs on Android Market, you must understand a few
-concepts regarding how the Android Market publisher site works.</p>
+<p>Before you start publishing multiple APKs on Google Play, you must understand a few
+concepts regarding how the Google Play publisher site works.</p>
 
 <h3 id="Active">Active APKs</h3>
 
@@ -111,20 +111,20 @@
   <p>When editing your application, there are two buttons on the top-right side of the page. The
 first button is either <strong>Publish</strong> or <strong>Unpublish</strong> and the second
 button is always <strong>Save</strong> (but its behavior changes).</p>
-  <p>When your application is new or you have unpublished it from Market, the first
+  <p>When your application is new or you have unpublished it from Google Play, the first
 button says <strong>Publish</strong>. Clicking it will publish any APKs listed as
-Active, making them available on Android Market. Also while your application is new
+Active, making them available on Google Play. Also while your application is new
 or unpublished, clicking <strong>Save</strong> will save any changes you've made, such
 as information added to the Product details and APKs you've uploaded, but nothing is made visible on
-Android Market&mdash;this allows you to save your changes and sign out of the publisher site before
+Google Play&mdash;this allows you to save your changes and sign out of the publisher site before
 deciding to publish.</p>
  <p>Once you've published your application, the first button changes to
 <strong>Unpublish</strong>. Clicking it in this state unpublishes your application so that none
-of the APKs are available on Android Market. Also while published, the behavior of the
+of the APKs are available on Google Play. Also while published, the behavior of the
 <strong>Save</strong> button is different. In this state, clicking <strong>Save</strong> not
-only saves all your changes, but also publishes them to Android Market. For example, if you've
+only saves all your changes, but also publishes them to Google Play. For example, if you've
 already published your application and then make changes to your product details or activate new
-APKs, clicking <strong>Save</strong> makes all those changes live on Android Market.</p>
+APKs, clicking <strong>Save</strong> makes all those changes live on Google Play.</p>
 </div>
 </div>
 
@@ -135,14 +135,14 @@
 you're about to publish.</p>
 
 <p>If there are no errors, any "active" APK will be published to
-Android Market when you click the <strong>Publish</strong> button (if the application is
+Google Play when you click the <strong>Publish</strong> button (if the application is
 unpublished) or when you click the <strong>Save</strong> button (if the application is
 already published).</p>
 
 
 <h3 id="SimpleAndAdvanced">Simple mode and advanced mode</h3>
 
-<p>The Android Market publisher site provides two modes for managing the APKs associated with
+<p>The Google Play publisher site provides two modes for managing the APKs associated with
 your application: <em>simple mode</em> and <em>advanced mode</em>. You can switch between these by
 clicking the
 link at the top-right corner of the <strong>APK files</strong> tab.</p>
@@ -164,21 +164,21 @@
 
 <h2 id="HowItWorks">How Multiple APKs Work</h2>
 
-<p>The concept for using multiple APKs on Android Market is that you have just one entry in
-Android Market for your application, but different devices might download a different APK. This
+<p>The concept for using multiple APKs on Google Play is that you have just one entry in
+Google Play for your application, but different devices might download a different APK. This
 means that:</p>
 
 <ul>
   <li>You maintain only one set of product details (app description, icons, screenshots, etc.).
 This also means you <em>cannot</em> charge a different price for different APKs.</li>
-  <li>All users see only one version of your application on Android Market, so they are not
+  <li>All users see only one version of your application on Google Play, so they are not
 confused by different versions you may have published that are "for tablets" or
 "for phones."</li>
   <li>All user reviews are applied to the same application listing, even though users on different
 devices may have different APKs.</li>
   <li>If you publish different APKs for different versions of Android (for different API levels),
 then when a user's device receives a system update that qualifies them for a different APK you've
-published, Android Market updates the user's application to the APK designed for the higher version
+published, Google Play updates the user's application to the APK designed for the higher version
 of Android. Any system data associated with the application is retained (the same as with normal
 application updates when using a single APK).</li>
 </ul>
@@ -192,8 +192,8 @@
 <h3 id="SupportedFilters">Supported filters</h3>
 
 <p>Which devices receive each APK is determined by <a
-href="{@docRoot}guide/appendix/market-filters.html">Android Market filters</a> that are specified by
-elements in the manifest file of each APK. However, Android Market allows you to publish multiple
+href="{@docRoot}guide/appendix/market-filters.html">Google Play filters</a> that are specified by
+elements in the manifest file of each APK. However, Google Play allows you to publish multiple
 APKs only when each APK uses filters to support a variation of the following
 device characteristics:</p>
 
@@ -229,7 +229,7 @@
 href="{@docRoot}guide/topics/manifest/supports-screens-element.html">{@code
 &lt;supports-screens&gt;}</a> element are "true" if you do not declare them otherwise. However,
 because the {@code android:xlargeScreens} attribute was added in Android 2.3 (API level
-9), Android Market will assume that it is "false" if your application does not set either <a
+9), Google Play will assume that it is "false" if your application does not set either <a
 href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code
 android:minSdkVersion}</a> or <a
 href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code
@@ -266,7 +266,7 @@
 android:minSdkVersion}</a> value must have a higher <a
 href="{@docRoot}guide/topics/manifest/manifest-element.html#vcode">{@code android:versionCode}</a>
 value. This is also true if two APKs overlap their device support based on a different supported
-filter. This ensures that when a device receives a system update, Android Market can offer the user
+filter. This ensures that when a device receives a system update, Google Play can offer the user
 an update for your application (because updates are based on an increase in the app version code).
 This requirement is described further in the section below about <a href="#Rules">Rules for
 multiple APKs</a>.</li>
@@ -286,8 +286,8 @@
 </ul>
 
 <p>Other manifest elements that enable <a
-href="{@docRoot}guide/appendix/market-filters.html">Android Market filters</a>&mdash;but are not
-listed above&mdash;are still applied for each APK as usual. However, Android Market does not allow
+href="{@docRoot}guide/appendix/market-filters.html">Google Play filters</a>&mdash;but are not
+listed above&mdash;are still applied for each APK as usual. However, Google Play does not allow
 you to publish multiple APKs based on variations of them. Thus, you cannot publish
 multiple APKs if the above listed filters are the same for each APK (but the APKs differ based on
 other characteristics in the manifest file). For
@@ -312,7 +312,7 @@
 
   <li>Each APK <strong>must not exactly match the configuration support of another APK</strong>.
     <p>That is, each APK must declare slightly different support for at least one of
-the <a href="#MarketFiltersSupported">supported Market filters</a> (listed above).</p>
+the <a href="#SupportedFilters">supported Google Play filters</a> (listed above).</p>
     <p>Usually, you will differentiate your APKs based on a specific characteristic (such as the
 supported texture compression formats), and thus, each APK will declare support for different
 devices. However, it's OK to publish multiple APKs that overlap their support slightly. When two
@@ -330,11 +330,11 @@
   <li>An APK that requires a <strong>higher API level</strong> must have a <strong>higher
 version code</strong>.
     <p>This is true only when either: the APKs differ based <em>only</em> on the
-supported API levels (no other <a href="#SupportedMarketFilters">supported market filters</a>
+supported API levels (no other <a href="#SupportedFilters">supported filters</a>
 distinguish the APKs from each other) <em>or</em> when the APKs do use another supported filter, but
 there is an overlap between the APKs within that filter.</p>
     <p>This is important because a user's device receives an application update from
-Android Market only if the version code for the APK on Android Market is higher than the version
+Google Play only if the version code for the APK on Google Play is higher than the version
 code of the APK currently on the device. This ensures that if a device receives a system update that
 then qualifies it to install the APK for higher API levels, the device receives an application
 update because the version code increases.</p>
@@ -365,7 +365,7 @@
 
 </ul>
 
-<p>Failure to abide by the above rules results in an error on the Android Market publisher site
+<p>Failure to abide by the above rules results in an error on the Google Play publisher site
 when you activate your APKs&mdash;you will be unable to publish your application until you
 resolve the error.</p>
 
@@ -377,7 +377,7 @@
 APKs support the devices that then fall outside the supported range. For example, if an APK
 currently supports small and normal size screens and you change it to support only small screens,
 then you have shrunk the pool of supported devices and some devices will no longer see your
-application in Android Market. You can resolve this by adding another APK that supports normal size
+application on Google Play. You can resolve this by adding another APK that supports normal size
 screens so that all previously-supported devices are still supported.</li>
 
   <li>When there are "overlaps" between two or more APKs. For example, if an APK supports screen
@@ -467,8 +467,8 @@
 href="{@docRoot}guide/topics/manifest/manifest-element.html#vname">{@code android:versionName}</a>),
 so that it's easy for you to associate the version code and version name.</p>
 
-<p class="note"><strong>Note:</strong> When you increase the version code for an APK, Android
-Market will prompt users of the previous version to update the application. Thus, to avoid
+<p class="note"><strong>Note:</strong> When you increase the version code for an APK, Google
+Play will prompt users of the previous version to update the application. Thus, to avoid
 unnecessary updates, you should not increase the version code for APKs that do not actually
 include changes.</p>
 
@@ -507,7 +507,7 @@
 <h2 id="SingleAPK">Using a Single APK Instead</h2>
 
 <p><strong>Creating multiple APKs for your application is not the normal procedure</strong> for
-publishing an application on Android Market. In most cases, you should be able to publish your
+publishing an application on Google Play. In most cases, you should be able to publish your
 application to most users with a single APK and we encourage that you do so. When you encounter
 a situation in which using a single APK becomes difficult, you should carefully consider all your
 options before deciding to publish multiple APKs.</p>
@@ -542,7 +542,7 @@
 For example, on a new tablet, the user receives your application and it runs with your
 tablet-optimized resources. This restore
 process does not work across different APKs, because each APK can potentially have different
-permissions that the user has not agreed to, so Android Market may not restore the application at
+permissions that the user has not agreed to, so Google Play may not restore the application at
 all. (If you use multiple APKs, the user receives either the exact same APK if it's compatible or
 nothing at all and must manually download your application to get the APK designed for the new
 device.)</p></li>
@@ -586,7 +586,7 @@
 
 <h3 id="ScreenOptions">Supporting multiple screens</h3>
 
-<p>Unless your APK file exceeds the Android Market size limit of 50MB, supporting multiple screens
+<p>Unless your APK file exceeds the Google Play size limit of 50MB, supporting multiple screens
 should always be done with a single APK. Since Android 1.6, the Android system manages most of the
 work required for your application to run successfully on a variety of screen sizes and
 densities.</p>
diff --git a/docs/html/guide/practices/compatibility.jd b/docs/html/guide/practices/compatibility.jd
index bb7a72e..5e514c4 100644
--- a/docs/html/guide/practices/compatibility.jd
+++ b/docs/html/guide/practices/compatibility.jd
@@ -7,7 +7,7 @@
 <h2>See also</h2>
  <ol>
 <li><a
-href="{@docRoot}guide/appendix/market-filters.html">Market Filters</a></li>
+href="{@docRoot}guide/appendix/market-filters.html">Filtering on Google Play</a></li>
 <li><a
 href="{@docRoot}guide/topics/resources/providing-resources.html#AlternativeResources">Providing Alternative Resources</a></li>
 <li><a
@@ -39,7 +39,7 @@
 your apps to do that, while at the same time letting you maintain control of
 what types of devices your app is available to. With a bit of forethought and
 some minor changes in your app's manifest file, you can ensure that users
-whose devices can’t run your app will never see it in the Android Market, and
+whose devices can’t run your app will never see it on Google Play, and
 will not get in trouble by downloading it. This page explains how you can
 control which devices have access to your apps, and how to prepare your apps to
 make sure they reach the right audience.</p>
@@ -64,7 +64,7 @@
 corresponding hardware or feature. But that’s not a problem: we also designed
 Android to prevent apps from being visible to devices which don’t have features
 the apps require. We’ve built support for this right into the SDK tools, and
-it’s part of the Android platform itself, as well as Android Market.</p>
+it’s part of the Android platform itself, as well as part of Google Play.</p>
 
 <p>As a developer, you have complete control of how and where your apps are
 available. Android provides tools as a first-class part of the platform that let
@@ -79,9 +79,9 @@
 <li>You state the features your app requires by declaring <a
 href="{@docRoot}guide/topics/manifest/uses-feature-element.html"><code>&lt;uses-feature&gt;</code></a>
 elements its manifest file.</li>
-<li>Devices are required to declare the features they include to Android
-Market.</li>
-<li>Android Market uses your app’s stated requirements to filter it from devices
+<li>Devices are required to declare the features they include to Google
+Play.</li>
+<li>Google Play uses your app’s stated requirements to filter it from devices
 that don’t meet those requirements.</li>
 </ol>
 
@@ -103,24 +103,24 @@
  <div class="sidebox-wrapper"> 
   <img id="rule" src="{@docRoot}assets/images/grad-rule-qv.png"> 
   <div id="qv-sub-rule"> 
-    <img src="{@docRoot}assets/images/icon_market.jpg" style="float:left;margin:0;padding:0;"> 
-    <p style="color:#669999;">Filtering on Android Market</p>
+    <img src="{@docRoot}assets/images/icon_play.png" style="float:left;margin:0;padding:0;"> 
+    <p style="color:#669999;">Filtering on Google Play</p>
 
-    <p>Android Market filters the applications that are visible to users, so
+    <p>Google Play filters the applications that are visible to users, so
 that users can see and download only those applications that are compatible with
 their devices.</p>
 
-    <p style="margin-top:1em;">One of the ways Market filters applications is by
-feature compatibility. To do this, Market checks the
+    <p style="margin-top:1em;">One of the ways Google Play filters applications is by
+feature compatibility. To do this, Google Play checks the
 <code>&lt;uses-feature&gt;</code> elements in each application's manifest, to
-establish the app's feature needs. Market then shows or hides the application to
+establish the app's feature needs. Google Play then shows or hides the application to
 each user, based on a comparison with the features available on the user's
 device. 
 
 <p style="margin-top:1em;">For information about other filters that you can
 use to control the availability of your apps, see the 
-<a href="{@docRoot}guide/appendix/market-filters.html">Market
-Filters</a> document.</p>
+<a href="{@docRoot}guide/appendix/market-filters.html">Filters on Google Play</a>
+document.</p>
   </div> 
 </div>
 
@@ -142,8 +142,8 @@
 
 <p>When you write your application, you specify which features your app requires
 by listing their feature IDs in <code>&lt;uses-feature&gt;</code> elements in
-the <code>AndroidManifest.xml</code> file.  This is the information that Android
-Market uses to match your app to devices that can run it. For instance, if you
+the <code>AndroidManifest.xml</code> file.  This is the information that Google
+Play uses to match your app to devices that can run it. For instance, if you
 state that your app requires android.software.live_wallpapers, it won’t be shown
 to devices that don’t support Live Wallpapers.</p>
 
@@ -170,12 +170,12 @@
 business or legal reasons. For instance, an app that displays train schedules
 for the London Underground is unlikely to be useful to users outside the United
 Kingdom. Other apps might not be permitted in certain countries for business or
-legal reasons. For cases such as these, Android Market itself provides
+legal reasons. For cases such as these, Google Play itself provides
 developers with filtering options that allow them control their app’s
 availability for non-technical reasons.</p>
 
-<p>The help information for Android Market provides full details, but in a
-nutshell, developers can use the Market publisher UI to:</p>
+<p>The help information for Google Play provides full details, but in a
+nutshell, developers can use the Google Play publisher UI to:</p>
 
 <ul>
 <li>List the countries an app is available in.</li>
@@ -185,7 +185,7 @@
 <p>Filtering for technical compatibility (such as required hardware components)
 is always based on information contained within your <code>.apk</code> file. But
 filtering for non-technical reasons (such as geographic restrictions) is always
-handled in the Market user interface.</p>
+handled in the Google Play user interface.</p>
 
 <h3 id="futureproofing">Future-proofing</h3>
 
@@ -206,7 +206,7 @@
 barcode scanners do not function as well with cameras that do not auto-focus. To
 prevent users from having a bad experience with those apps, existing apps that
 obtain permission to use the Camera were assumed by default to require
-auto-focus. This allowed Android Market to filter those apps from devices that
+auto-focus. This allowed Google Play to filter those apps from devices that
 lack auto-focus.</li>
 
 <li>Android 2.2, meanwhile, allowed the microphone to be optional on some
diff --git a/docs/html/guide/practices/design/accessibility.jd b/docs/html/guide/practices/design/accessibility.jd
index a66a974..72da04e 100644
--- a/docs/html/guide/practices/design/accessibility.jd
+++ b/docs/html/guide/practices/design/accessibility.jd
@@ -332,11 +332,10 @@
 
 <p>You can simulate the experience for many users by enabling an accessibility service that speaks
 as you move around the screen.  One such service is <a
-href="https://market.android.com/details?id=com.google.android.marvin.talkback">TalkBack</a>, by the
+href="https://play.google.com/store/details?id=com.google.android.marvin.talkback">TalkBack</a>, by the
 <a href="http://code.google.com/p/eyes-free/">Eyes-Free Project</a>.  It comes preinstalled on many
-Android-powered devices, but is also available for free from <a
-href="https://market.android.com/details?id=com.google.android.marvin.talkback">Android
-Market</a>.</p>
+Android-powered devices, but is also available for free from the <a
+href="https://play.google.com/store/details?id=com.google.android.marvin.talkback">Google Play</a> store.</p>
 
 <p>This service requires that you have a text-to-speech engine installed on your phone.  You can
 verify if you have one installed in the <strong>Text-to-speech</strong> settings menu by selecting
diff --git a/docs/html/guide/practices/optimizing-for-3.0.jd b/docs/html/guide/practices/optimizing-for-3.0.jd
index 39662f1..140c50c 100644
--- a/docs/html/guide/practices/optimizing-for-3.0.jd
+++ b/docs/html/guide/practices/optimizing-for-3.0.jd
@@ -481,7 +481,7 @@
 configurations of screen size and density, you can instead choose to limit the distribution of your
 application to certain types of screens, such as only tablets or only mobile devices. To do so, you
 can add elements to your Android manifest file that enable filtering based on screen configuration
-by external services such as Android Market.</p>
+by external services such as Google Play.</p>
 
 <p>However, before you decide to restrict your application to certain screen configurations, you
 should understand the techniques for <a
@@ -517,14 +517,14 @@
 &lt;/manifest>
 </pre>
 
-<p>External services such as Android Market read this manifest element and use it to ensure that
+<p>External services such as Google Play read this manifest element and use it to ensure that
 your application is available only to devices with an extra large screen.</p>
 
 <p class="note"><strong>Note:</strong> If you use the <a
 href="{@docRoot}guide/topics/manifest/supports-screens-element.html">{@code
 &lt;supports-screens>}</a> element for the reverse scenario (when your application is not compatible
 with <em>larger</em> screens) and set the larger screen size attributes to {@code "false"}, then
-external services such as Android Market <strong>do not</strong> apply filtering. Your application
+external services such as Google Play <strong>do not</strong> apply filtering. Your application
 will still be available to larger screens, but when it runs, it will not fill the screen&mdash;the
 system will draw it in a "postage stamp" window that's the same relative size as the screen size
 that your application does support. If you want to prevent your application from being downloaded on
@@ -541,7 +541,7 @@
 use the <a href="{@docRoot}guide/topics/manifest/compatible-screens-element.html">{@code
 &lt;compatible-screens>}</a> element to manage the distribution of your application based on the
 combination of screen size and density. External services such as
-Android Market uses this information to apply filtering to your application, so that only devices
+Google Play uses this information to apply filtering to your application, so that only devices
 that have a screen configuration with which you declare compatibility can download your
 application.</p>
 
@@ -551,7 +551,7 @@
 the {@code android:screenSize} and {@code android:screenDensity} attributes. Each {@code
 &lt;screen&gt;} element <strong>must include both attributes</strong> to specify an individual
 screen configuration&mdash;if either attribute is missing, then the element is invalid
-(external services such as Android Market will ignore it).</p>
+(external services such as Google Play will ignore it).</p>
 
 <p>For example, if your application is compatible with only small and normal screens, regardless
 of screen density, then you must specify eight different {@code &lt;screen&gt;} elements,
@@ -613,7 +613,7 @@
   <li><a href="#Telephony">Not all devices have telephony or other features</a>
   <p>If your application declares the {@code "android.hardware.telephony"} feature in the manifest,
 then it will not be available to devices that do not offer telephony (such as tablets), based on
-Android Market filtering. If your application can function properly without telephony, you should
+Google Play filtering. If your application can function properly without telephony, you should
 update your application to gracefully disable the telephony features when not available on a
 device.</p></li>
 </ul>
@@ -682,7 +682,7 @@
 <pre>&lt;uses-feature android:name="android.hardware.telephony" /></pre>
 
 <p>By default, this declares that your application <em>requires</em> telephony features. So,
-external services such as Android Market use this information to filter your application from
+external services such as Google Play use this information to filter your application from
 devices that do not offer telephony.</p>
 
 <p>If, however, your application uses, but does not require the feature, you should
diff --git a/docs/html/guide/practices/screens-distribution.jd b/docs/html/guide/practices/screens-distribution.jd
index 60c9c95..a7c4a8e 100644
--- a/docs/html/guide/practices/screens-distribution.jd
+++ b/docs/html/guide/practices/screens-distribution.jd
@@ -37,7 +37,7 @@
 configurations of screen size and density, you can instead choose to limit the distribution of your
 application to certain types of screens, such as only tablets and other large devices or only
 handsets and similar-sized devices. To do so, you can enable filtering by external services such as
-Android Market by adding elements to your manifest file that specify the screen configurations your
+Google Play by adding elements to your manifest file that specify the screen configurations your
 application supports.</p>
 
 <p>However, before you decide to restrict your application to certain screen configurations, you
@@ -58,7 +58,7 @@
 versions of your application for different screen configurations. In such a case, you can use the <a
 href="{@docRoot}guide/topics/manifest/compatible-screens-element.html">{@code
 &lt;compatible-screens>}</a> element to manage the distribution of your application based on
-combinations of screen size and density. External services such as Android Market use this
+combinations of screen size and density. External services such as Google Play use this
 information to apply filtering to your application, so that only devices that have a screen
 configuration with which you declare compatibility can download your application.</p>
 
@@ -68,7 +68,7 @@
 compatible, using both the {@code android:screenSize} and {@code android:screenDensity} attributes.
 Each {@code &lt;screen&gt;} element <strong>must include both attributes</strong> to specify an
 individual screen configuration&mdash;if either attribute is missing, then the element is invalid
-(external services such as Android Market will ignore it).</p>
+(external services such as Google Play will ignore it).</p>
 
 <p>For example, if your application is compatible with only small and normal size screens,
 regardless of screen density, you must specify eight different {@code &lt;screen&gt;} elements,
@@ -173,7 +173,7 @@
 href="{@docRoot}guide/topics/manifest/supports-screens-element.html">{@code
 &lt;supports-screens>}</a> element for the reverse scenario (when your application is not compatible
 with <em>larger</em> screens) and set the larger screen size attributes to {@code "false"}, then
-external services such as Android Market <strong>do not</strong> apply filtering. Your application
+external services such as Google Play <strong>do not</strong> apply filtering. Your application
 will still be available to larger screens, but when it runs, it will not resize to fit the screen.
 Instead, the system will emulate a handset screen size (about 320dp x 480dp; see <a
 href="{@docRoot}guide/practices/screen-compat-mode.html">Screen Compatibility Mode</a> for more
@@ -197,13 +197,13 @@
 
 <h2 id="MultiApks">Publishing Multiple APKs for Different Screens</h2>
 
-<p>Although we recommend that you publish one APK for your application, Android Market allows
+<p>Although we recommend that you publish one APK for your application, Google Play allows
 you to publish multiple APKs for the same
 application when each APK supports a different set of screen configurations (as declared in
 the manifest file). For example, if you want to publish both a handset version and a tablet
 version of your application, but you're unable to make the same APK work for both screen sizes,
 you can actually publish two APKs for the same application listing. Depending on each device's
-screen configuration, Android Market will deliver it the APK that you've declared to support that
+screen configuration, Google Play will deliver it the APK that you've declared to support that
 device's screen.</p>
 
 <p>Beware, however, that publishing multiple APKs for the same application is
@@ -212,5 +212,5 @@
 sizes, especially, is within reason using a single APK, as long as you follow the guide to
 <a href="{@docRoot}guide/practices/screens_support.html">Supporting Multiple Screens</a>.</p>
 
-<p>If you need more information about how to publish multiple APKs on Android Market, read <a
+<p>If you need more information about how to publish multiple APKs on Google Play, read <a
 href="{@docRoot}guide/market/publishing/multiple-apks.html">Multiple APK Support</a>.</p>
diff --git a/docs/html/guide/practices/screens_support.jd b/docs/html/guide/practices/screens_support.jd
index fb121bd..29dff26 100644
--- a/docs/html/guide/practices/screens_support.jd
+++ b/docs/html/guide/practices/screens_support.jd
@@ -882,8 +882,8 @@
 
   <p class="caution"><strong>Caution:</strong> The Android system does not pay attention to this
 attribute, so it does not affect how your application behaves at runtime. Instead, it is used
-to enable filtering for your application on services such as Android Market. However,
-<strong>Android Market currently does not support this attribute for filtering</strong> (on Android
+to enable filtering for your application on services such as Google Play. However,
+<strong>Google Play currently does not support this attribute for filtering</strong> (on Android
 3.2), so you should continue using the other size attributes if your application does not support
 small screens.</p>
 </dd>
diff --git a/docs/html/guide/practices/ui_guidelines/activity_task_design.jd b/docs/html/guide/practices/ui_guidelines/activity_task_design.jd
index 9be72ee..f8ca3f8 100644
--- a/docs/html/guide/practices/ui_guidelines/activity_task_design.jd
+++ b/docs/html/guide/practices/ui_guidelines/activity_task_design.jd
@@ -886,7 +886,7 @@
   You can perform this test when initializing the user interface.
   For instance, you could disable the user control that initiates
   the Intent object, or display a message to the user that lets them go
-  to a location, such as the Market, to download its application.
+  to a location, such as Google Play, to download its application.
   In this way, your code can start the activity (using either startActivity() 
   or startActivityForResult()) only if the intent has tested to resolve
   to an activity that is actually present.
diff --git a/docs/html/guide/practices/ui_guidelines/icon_design_launcher.jd b/docs/html/guide/practices/ui_guidelines/icon_design_launcher.jd
index 6b686b1..4b6768f 100644
--- a/docs/html/guide/practices/ui_guidelines/icon_design_launcher.jd
+++ b/docs/html/guide/practices/ui_guidelines/icon_design_launcher.jd
@@ -49,9 +49,9 @@
 href="{@docRoot}guide/practices/ui_guidelines/icon_design.html#design-tips">Tips for Designers</a>
 for suggestions on how to work with multiple sets of icons.</p>
 
-<p>A high-resolution version of your application launcher icon is also required by Android Market
+<p>A high-resolution version of your application launcher icon is also required by Google Play
 for use in application listings. For more details on this, see <a
-href="#icons_in_market">Application Icons in Android Market</a> below.</p>
+href="#icons_in_market">Application Icons on Google Play</a> below.</p>
 
 
 <p class="note"><strong>Note:</strong>
@@ -81,7 +81,7 @@
 
 <ol>
   <li>Promote the brand and tell the story of the app.</li>
-  <li>Help users discover the app in Android Market.</li>
+  <li>Help users discover the app on Google Play.</li>
   <li>Function well in the Launcher.</li>
 </ol>
 
@@ -100,19 +100,19 @@
 </ul>
 
 
-<h3 id="help_users_discover">Help users discover the app in Android Market</h3>
+<h3 id="help_users_discover">Help users discover the app on Google Play</h3>
 
-<p>App launcher icons are the first look that prospective users will get of your app in Android
-Market. A high quality app icon can influence users to find out more as they scroll through lists of
+<p>App launcher icons are the first look that prospective users will get of your app on Google Play.
+A high quality app icon can influence users to find out more as they scroll through lists of
 applications.</p>
 
 <p>Quality matters here. A well-designed icon can be a strong signal that your app
 is of similarly high quality. Consider working with an icon designer to develop the app’s launcher
 icon.</p>
 
-<p class="note"><strong>Note:</strong> Android Market requires a high-resolution version of your
-icon; for more details on this, see <a href="#icons_in_market">Application Icons in Android
-Market</a> below.</p>
+<p class="note"><strong>Note:</strong> Google Play requires a high-resolution version of your
+icon; for more details on this, see <a href="#icons_in_market">Application Icons in Google
+Play</a> below.</p>
 
 
 <h3 id="function_well_in_launcher">Function well in the Launcher</h3>
@@ -239,21 +239,21 @@
 that launcher icons are legible across on any background color.</p>
 
 
-<h3 id="icons_in_market">Application Icons in Android Market</h3>
+<h3 id="icons_in_market">Application Icons on Google Play</h3>
 
 <p>If you are <a href="{@docRoot}guide/publishing/publishing.html">publishing your application on
-Android Market</a>, you will also need to provide a 512 x 512 pixel, high-resolution application icon
-in the <a href="http://market.android.com/publish">developer console</a> at upload time. This icon
-will be used in various locations in Android Market and does not replace your launcher icon.</p>
+Google Play</a>, you will also need to provide a 512 x 512 pixel, high-resolution application icon
+in the <a href="http://play.google.com/apps/publish">developer console</a> at upload time. This icon
+will be used in various locations on Google Play and does not replace your launcher icon.</p>
 
 <p>For tips and recommendations on creating high-resolution launcher icons that can easily be scaled
 up to 512x512, see <a href="{@docRoot}guide/practices/ui_guidelines/icon_design.html#design-tips">
 Tips for Designers</a>.</p>
 
-<p>For information and specifications about high-resolution application icons in Android Market, see
+<p>For information and specifications about high-resolution application icons on Google Play, see
 the following article:</p>
 
 <p style="margin-left:2em"><a href="http://market.android.com/support/bin/answer.py?answer=1078870">
-Graphic Assets for your Application (Android Market Help) &raquo;</a>
+Graphic Assets for your Application (Google Play Help) &raquo;</a>
 
 <br><br>
diff --git a/docs/html/guide/practices/ui_guidelines/icon_design_launcher_archive.jd b/docs/html/guide/practices/ui_guidelines/icon_design_launcher_archive.jd
index ea036cd..85a3cc8 100644
--- a/docs/html/guide/practices/ui_guidelines/icon_design_launcher_archive.jd
+++ b/docs/html/guide/practices/ui_guidelines/icon_design_launcher_archive.jd
@@ -56,13 +56,13 @@
 
 
 
-<h2 id="market">Application Icons in Android Market</h2>
+<h2 id="market">Application Icons on Google Play</h2>
 
 <p>If you are <a href="{@docRoot}guide/publishing/publishing.html">publishing
-your application on Android Market</a>, you will also need to provide a 512x512
+your application on Google Play</a>, you will also need to provide a 512x512
 pixel, high-resolution application icon in the <a
-href="http://market.android.com/publish">developer console</a> at upload-time.
-This icon will be used in various locations in Android Market and does
+href="http://play.google.com/apps/publish">developer console</a> at upload-time.
+This icon will be used in various locations on Google Play and does
 not replace your launcher icon.</p>
 
 <p>For tips and recommendations on creating high-resolution launcher icons that
@@ -71,11 +71,11 @@
 Tips for Designers</a>.</p>
 
 <p>For information and specifications about high-resolution application
-icons in Android Market, see the following article:</p>
+icons on Google Play, see the following article:</p>
 
 <p style="margin-left:2em"><a
 href="http://market.android.com/support/bin/answer.py?answer=1078870">
-  Graphic Assets for your Application (Android Market Help) &raquo;</a>
+  Graphic Assets for your Application (Google Play Help) &raquo;</a>
 
 
 
diff --git a/docs/html/guide/publishing/app-signing.jd b/docs/html/guide/publishing/app-signing.jd
index 9abcdf7..e86ec30 100644
--- a/docs/html/guide/publishing/app-signing.jd
+++ b/docs/html/guide/publishing/app-signing.jd
@@ -82,7 +82,7 @@
 use to build your application. There are two build modes: <em>debug mode</em> and <em>release
 mode</em>. You use debug mode when you are developing and testing your application. You use
 release mode when you want to build a release version of your application that you can
-distribute directly to users or publish on an application marketplace such as Android Market.</p>
+distribute directly to users or publish on an application marketplace such as Google Play.</p>
 
 <p>When you build in <em>debug mode</em> the Android SDK build tools use the Keytool utility
 (included in the JDK) to create a debug key. Because the SDK build tools created the debug key,
@@ -158,10 +158,10 @@
 lifespan of <em>all versions of all of the applications</em>, including
 dependent applications that may be added to the suite in the future. </li>
 
-<li>If you plan to publish your application(s) on Android Market, the
+<li>If you plan to publish your application(s) on Google Play, the
 key you use to sign the application(s) must have a validity period
-ending after 22 October 2033. The Market server enforces this requirement
-to ensure that users can seamlessly upgrade Market applications when
+ending after 22 October 2033. Google Play enforces this requirement
+to ensure that users can seamlessly upgrade applications when
 new versions are available. </li>
 </ul>
 
@@ -292,7 +292,7 @@
 with the application</li>
 <li>Has a validity period that exceeds the expected lifespan of the application
 or application suite. A validity period of more than 25 years is recommended.
-<p>If you plan to publish your application(s) on Android Market, note that a
+<p>If you plan to publish your application(s) on Google Play, note that a
 validity period ending after 22 October 2033 is a requirement. You can not upload an
 application if it is signed with a key whose validity expires before that date.
 </p></li>
diff --git a/docs/html/guide/publishing/licensing.html b/docs/html/guide/publishing/licensing.html
new file mode 100644
index 0000000..8e97f32
--- /dev/null
+++ b/docs/html/guide/publishing/licensing.html
@@ -0,0 +1,11 @@
+<html>
+<head>
+<meta http-equiv="refresh"
+content="0;url=http://developer.android.com/guide/market/licensing/index.html">
+<title>Redirecting...</title>
+</head>
+<body>
+<p>You should have been redirected. Please <a
+href="http://developer.android.com/guide/market/licensing/index.html">click here</a>.</p>
+</body>
+</html>
\ No newline at end of file
diff --git a/docs/html/guide/publishing/licensing.jd b/docs/html/guide/publishing/licensing.jd
deleted file mode 100644
index 609241b..0000000
--- a/docs/html/guide/publishing/licensing.jd
+++ /dev/null
@@ -1,2388 +0,0 @@
-page.title=Application Licensing
-@jd:body
-
-<div id="qv-wrapper">
-<div id="qv">
-
-  <h2>Quickview</h2>
-  <ul>
-    <li>Licensing lets you protect your application on any device that includes Android Market.</li>
-    <li>Your app maintains control of how it enforces its licensing status. </li>
-    <li>Adding licensing to an app is straightforward, using the library available through the SDK.</li>
-    <li>The service is free and is available to all developers who publish on Android Market. </li>
-  </ul>
-
-  <h2>In this document</h2>
-  <ol>
-    <li><a href="#account">Setting Up A Publisher Account</a></li>
-    <li><a href="#dev-setup">Setting Up the Development Environment</a></li>
-    <li><a href="#app-integration">Integrating the LVL with Your Application</a>
-    <ol>
-       <li><a href="#add-library">Including the LVL</a></li>
-       <li><a href="#manifest-permission">Adding the licensing permission</a></li>
-       <li><a href="#impl-Policy">Implementing a Policy</a></li>
-       <li><a href="#impl-Obfuscator">Implementing an Obfuscator</a></li>
-       <li><a href="#impl-lc">Checking the license</a></li>
-       <li><a href="#impl-DeviceLimiter">Implementing a DeviceLimiter</a></li>
-    </ol></li>
-    <li><a href="#test-env">Setting Up the Test Environment</a>
-    <ol>
-       <li><a href="#test-response">Test responses</a></li>
-       <li><a href="#test-acct-setup">Test accounts</a></li>
-       <li><a href="#acct-signin">Signing in on a device or emulator</a></li>
-    </ol></li>
-    <li><a href="#app-obfuscation">Obfuscating Your Application</a></li>
-    <li><a href="#app-publishing">Publishing a Licensed Application</a></li>
-    <li><a href="#support">Where to Get Support</a></li>
-  </ol>
-
-  <h2>Appendix</h2>
-  <ol>
-    <li><a href="#lvl-summary">Summary of LVL Classes and Interfaces</a></li>
-    <li><a href="#server-response-codes">Server Response Codes</a></li>
-    <li><a href="#extras">Server Response Extras</a></li>
-  </ol>
-
-</div>
-</div>
-
-<p>Android Market offers a licensing service that lets you enforce licensing
-policies for paid applications that you publish through Android Market. With
-Android Market Licensing, your applications can query Android Market at run time to
-obtain their licensing status for the current user, then allow or disallow
-further use as appropriate. </p>
-
-<p>Using the service, you can apply a flexible licensing policy on an
-application-by-application basis &mdash; each application can enforce licensing
-in the way most appropriate for it. If necessary, an application can apply custom
-constraints based on the licensing status obtained from Android Market.
-For example, an application can check the licensing status and then apply custom
-constraints that allow the user to run it unlicensed for a specific number
-of times, or for a specific validity period. An application can also restrict use of the
-application to a specific device, in addition to any other constraints. </p>
-
-<p>The licensing service is a secure means of controlling access to your
-applications. When an application checks the licensing status, the Market server
-signs the licensing status response using a key pair that is uniquely associated
-with the publisher account. Your application stores the public key in its
-compiled <code>.apk</code> file and uses it to verify the licensing status
-response.</p>
-
-<p>Any application that you publish through Android Market can use the Android
-Market Licensing service. No special account or registration is needed.
-Additionally, because the service uses no dedicated framework APIs, you can add
-licensing to any legacy application that uses a minimum API level of 3 or
-higher.</p>
-
-<p>To help you add licensing to your application, the Android SDK provides
-library sources that you can include in your application project. The
-License Verification Library (LVL) handles all of
-the licensing-related communication with the Android Market client and the
-licensing service. With the LVL integrated, your application can determine its
-licensing status for the current user by simply calling a library checker method
-and implementing a callback that receives the status.</p>
-
-<p>This document explains how the licensing service works and how to add it to
-your application. </p>
-
-
-<h2 id="overview">Overview</h2>
-
-<p>Android Market Licensing is a network-based service that lets an application
-on an Android-powered device query a trusted licensing server, to determine
-whether the application is licensed to the current device user. After receiving
-the server response, the application can then allow or disallow further use of
-the application as needed. In the service, the role of the licensing server is
-to provide the license status for the current user; the application itself is
-responsible for querying the server and conditionally granting access to the
-application. </p>
-
-<h4>Application, Android Market client, and server</h4>
-
-<p>The licensing service is based on the capability of the Android Market server
-to determine whether a given user is licensed to use a given application. The licensing server
-considers a user to be licensed if the user is a recorded purchaser of an application. If a paid
-application has been uploaded to Android Market but saved only as a draft application (in
-other words, the app is unpublished), the licensing server considers all users to be licensed users
-of the application. Keep in mind, you cannot implement Android Market Licensing in a free
-application.</p>
-
-<p>To properly identify
-the user and determine the license status, the server requires information about
-the application and user &mdash; the application and the Android Market client
-work together to assemble the information and pass it to the server. </p>
-
-<p>In the licensing service, an application does not query the licensing server
-directly, but instead calls the Android Market client over remote IPC to
-initiate a license request. In the license request:</p>
-
-<ul>
-<li>The application provides its package name and a nonce that is later used to
-validate any response from the server, as well as a callback over which the
-response can be returned asynchronously.</li>
-<li>The Android Market client, which has greater permissions than the
-application, collects the necessary information about the user and the device,
-such as the device's primary Google account username, IMSI, and other
-information. It then sends the license check request to the server on behalf of
-the application.</li>
-<li>The server evaluates the request using all available information, attempting
-to establish the user's identity to a sufficient level of confidence. The server
-then checks the user identity against purchase records for the application and
-returns a license response, which the Android Market client returns to the
-application over the IPC callback.</li>
-</ul>
-
-<p>Notice that during a license check, the application does not manage any
-network connections or use any licensing related APIs in the Android platform.
-</p>
-
-<div class="figure" style="width:469px">
-<img src="{@docRoot}images/licensing_arch.png" alt=""/>
-<p class="img-caption"><strong>Figure 1.</strong> Your application initiates a
-license check through the LVL and the Android Market
-client, which handles communication with the Market server.</p>
-</div>
-
-<h4>License responses secured through public key cryptography</h4>
-
-<p>To ensure the integrity of each license query, the server signs the license
-response data using an RSA key pair that is shared exclusively between the
-server and the application publisher.</p>
-
-<p>The licensing service generates a single licensing key pair for each
-publisher account and exposes the public key in the account's profile page. The
-publisher copies the public key and embeds it in the application source code,
-then compiles and publishes the <code>.apk.</code> The server retains the
-private key internally and uses it to sign license responses for applications
-published on that account. </p>
-
-<p>When the application receives a signed response, it uses the embedded public
-key to verify the data. The use of public key cryptography in the licensing
-service makes it possible for the application to detect responses that have been
-tampered with or that are spoofed.</p>
-
-<h4>Use of licensing in your application</h4>
-
-<p>To use licensing in your application, add code to the application to
-initiate a license check request and handle the response when it is received.
-You can choose when, and how often, you want your application to check its
-license and you have full control over how it handles the response, verifies the
-signed response data, and enforces access controls. </p>
-
-<p>To simplify the process of adding support for licensing, download and
-integrate the Licensing Verification Library, described below. Integration is
-straightforward.</p>
-
-<p>When you are finished integrating the LVL, use a test environment
-provided by the publisher site to test your application's handling of server
-responses. </p>
-
-<p>Finally, publish the application <code>.apk</code> on Market using the
-normal process. If you previously used the copy-protection provided by Android
-Market, you can remove it from applications that use licensing. </p>
-
-<h4>Licensing Verification Library simplifies implementation</h4>
-
-<p>The Android SDK includes a License Verification Library (LVL) that you can
-download and use as the basis for your application's licensing implementation.
-The LVL greatly simplifies the process of adding licensing to your application
-and helps ensure a more secure, robust implementation for your application. The
-LVL provides internal classes that handle most of the standard operations of a
-license query, such as contacting Android Market to initiate a license request
-and verifying and validating the responses. It also exposes key interfaces that
-let you easily plug in your custom code for defining licensing policy and
-managing access as needed by your application. The key LVL interfaces are: </p>
-
-<ul>
-<li>Policy &mdash; your implementation determines whether to allow access to the
-application, based on the license response received from the server and any
-other data available (such as from a backend server associated with your
-application). The implementation can evaluate the various fields of the license
-response and apply other constraints, if needed. The implementation also lets
-you manage the handling of license checks that result in errors, such as network
-errors.</li>
-<li>LicenseCheckerCallback &mdash; your implementation manages access to the
-application, based on the result of the Policy's handling of the license
-response. Your implementation can manage access in any way needed, including
-displaying the license result in the UI or directing the user to purchase the
-application (if not currently licensed). </li>
-</ul>
-
-<p>To help you get started with a Policy, the LVL provides two fully complete
-Policy implementations that you can use without modification or adapt to your
-needs:</p>
-
-<ul>
-<li><a href="#ServerManagedPolicy">ServerManagedPolicy</a> is a flexible Policy
-that uses settings provided by the licensing server to manage response caching
-and access to the application while the device is offline (such as when the
-user is on an airplane). For most applications, the use of
-ServerManagedPolicy is highly recommended. </li>
-<li><a href="#StrictPolicy">StrictPolicy</a> is a restrictive Policy that
-does not cache any response data and allows the application access <em>only</em>
-when the server returns a licensed response.</li>
-</ul>
-
-<p>The LVL is available as a downloadable component of the Android SDK. The
-component includes both the LVL itself and an example application that shows how
-the library should be integrated with your application and how your application
-should manage response data, UI interaction, and error conditions. </p>
-
-<p>The LVL sources are provided as an Android <em>library project</em>, which
-means that you can maintain a single set of library sources and share them
-across multiple applications. A full test environment is also available through
-the SDK, so you can develop and test the licensing implementation in your
-applications before publishing them, even if you don't have access to a
-physical device.</p>
-
-<h4>Requirements and limitations</h4>
-
-<p>Android Market Licensing is designed to let you apply license controls to
-applications that you publish through Android Market. The service is not
-designed to let you control access to applications that are not published
-through Android Market or that are run on devices that do not offer the Android
-Market client. </p>
-
-<p>Here are some points to keep in mind as you implement licensing in your
-application: </p>
-
-<ul>
-<li>Only paid applications published through Market can use the
-service.</li>
-<li>An application can use the service only if the Android Market client is
-installed on its host device and the device is running Android 1.5 (API level 3)
-or higher.</li>
-<li>To complete a license check, the licensing server must be accessible over
-the network. You can implement license caching behaviors to manage access when
-there is no network connectivity. </li>
-<li>The security of your application's licensing controls ultimately relies on
-the design of your implementation itself. The service provides the building
-blocks that let you securely check licensing, but the actual enforcement and
-handling of the license are factors in your control. By following the best
-practices in this document, you can help ensure that your implementation will be
-secure.</li>
-<li>Adding licensing to an application does not affect the way the application
-functions when run on a device that does not offer Android Market.</li>
-<li>Licensing is currently for paid apps only, since draft apps are
-licensed for all users. If your application is already published as a free app,
-you won't be able to upload a new version that uses licensing.</li>
-</ul>
-
-<h4>Replacement for Copy Protection</h4>
-
-<p>Android Market Licensing is a flexible, secure mechanism for controlling
-access to your applications. It effectively replaces the Copy Protection
-mechanism offered on Android Market and gives you wider distribution
-potential for your applications. </p>
-
-<ul>
-<li>A limitation of the legacy Copy Protection mechanism on Android Market is
-that applications using it can be installed only on compatible devices that
-provide a secure internal storage environment. For example, a copy-protected
-application cannot be downloaded from Market to a device that provides root
-access, and the application cannot be installed to a device's SD card. </li>
-<li>With Android Market licensing, you can move to a license-based model in
-which access is not bound to the characteristics of the host device, but to your
-publisher account on Android Market and the licensing policy that you define.
-Your application can be installed and controlled on any compatible device on
-any storage, including SD card.</li>
-</ul>
-
-<p>Although no license mechanism can completely prevent all unauthorized use,
-the licensing service lets you control access for most types of normal usage,
-across all compatible devices, locked or unlocked, that run Android 1.5 or
-higher version of the platform.</p>
-
-<p>The sections below describe how to add Android Market licensing to your
-applications. </p>
-
-<h2 id="account">Setting Up a Publisher Account</h2>
-
-<p>Android Market licensing lets you manage access to applications that
-users have downloaded from Android Market. To use licensing in an application,
-you need to have a publisher account on Android Market so that you can
-publish the application to users. </p>
-
-<p>If you don't already have a publisher account, you need to register for one
-using your Google account and agree to the terms of service. Once you are
-registered, you can upload applications at your convenience and begin debugging
-and testing your licensing implementation. For more information about publishing
-on Android Market, see <a
-href="{@docRoot}guide/publishing/publishing.html">Publishing Your
-Applications</a></p>
-
-<p>To register as an Android Market developer and set up your publisher account,
-visit the Android Market publisher site:</p>
-
-<p style="margin-left:2em;"><a
-href="http://market.android.com/publish">http://market.android.com/publish</a>
-</p>
-
-<p>If you already have a publisher account on Android Market, use your existing
-account to set up licensing. You <em>do not</em> need to register for a new
-account to support licensing (and doing so is not recommended, especially if you
-are adding licensing support to applications that you have already published).
-In all cases, if you have published applications, you manage licensing for those
-applications through the account on which the applications are published. </p>
-
-<p>Once your publisher account is set up, use the account to:</p>
-
-<ul>
-<li>Obtain a public key for licensing</li>
-<li>Debug and test an application's licensing implementation, prior to
-publishing the application</li>
-<li>Publish the applications to which you have added licensing support</li>
-</ul>
-
-<h4>Administrative settings for licensing</h4>
-
-<p>Once you are signed into your publisher account, you can manage several
-administrative controls for Android Market licensing. The controls are available
-in the Edit Profile page, in the "Licensing" panel, shown below. The controls
-let you: </p>
-
-<ul>
-<li>Set up multiple "test accounts", identified by email address. The licensing
-server allows users signed into test accounts on a device or emulator to send
-license checks and receive static test responses.</li>
-<li>Obtain the account's public key for licensing. When you are implementing
-licensing in an application, you must copy the public key string into the
-application.</li>
-<li>Configure static test responses that the server sends, when it receives a
-license check for an application uploaded to the publisher account, from a user
-signed in to the publisher account or a test account.</li>
-</ul>
-
-<div style="margin-bottom:2em;">
-
-<img src="{@docRoot}images/licensing_public_key.png" style="text-align:left;margin-bottom:0;" />
-<div style="margin:0 2em;padding:0"><strong>Figure 2.</strong> The Licensing
-panel of your account's Edit Profile page lets you manage administrative
-settings for licensing.</div>
-</div>
-
-<p>For more information about how to work with test accounts and static test
-responses, see <a href="#test-env">Setting Up a Testing Environment</a>, below.
-
-<h2 id="dev-setup">Setting Up the Development Environment</h2>
-
-<p>Once you've set up your publisher account on Android Market, the next step is
-to set up your development environment for licensing. </p>
-
-<p>Setting up your environment for licensing involves these tasks:</p>
-
-<ol>
-<li><a href="#download-sdk">Downloading the latest SDK</a>, if you haven't already done so </li>
-<li><a href="#runtime-setup">Setting up the runtime environment</a> for development</li>
-<li><a href="#download-lvl">Downloading the Market Licensing component</a> into your SDK </li>
-<li><a href="#lvl-setup">Setting up the Licensing Verification Library</a></li>
-<li><a href="#add-library">Including the LVL library project in your application</a></li>
-</ol>
-
-<p>The sections below describe these tasks. When you are done with setup,
-you can begin <a href="#app-integration">integrating the LVL into your applications</a>.</p>
-
-<p>To get started, you need to set up a proper runtime environment on which
-you can run, debug and test your application's implementation of license
-checking and enforcement. </p>
-
-
-<h3 id="download-sdk">Downloading the latest SDK</h3>
-
-<div class="sidebox-wrapper">
-<div class="sidebox">
-<h2>Licensing sample application</h2>
-
-<p>To work with Android Market licensing, you need a functioning Android
-application to which you can add licensing support. </p>
-
-<p style="margin-top:.5em;">If you are new to Android
-and don't yet have a functioning application, the LVL component includes a sample
-application that you can set up as a new application project. The sample provides
-a complete, working example of how licensing works. For more information, see <a
-href="#download-lvl">Downloading the LVL</a>.</p>
-
-</div>
-</div>
-
-<p>If you haven't done so, you need to download the Android SDK before you can
-develop Android applications. The SDK provides the tools that you need to build
-and debug Android applications, including applications that use Android Market
-licensing. For complete information, including installation instructions, see
-the <a href="{@docRoot}sdk/index.html">Android SDK</a>. </p>
-
-<p>If you have already installed the SDK, make sure to update the
-SDK tools and ADT Plugin to the latest versions. You can update the SDK tools
-using the Android SDK and AVD Manager and ADT through <strong>Help</strong> &gt;
-<strong>Software Updates...</strong> in Eclipse. </p>
-
-<p>After you've installed the latest SDK and tools, set up your development
-environment as described below. </p>
-
-
-<h3 id="runtime-setup">Setting up the runtime environment</h3>
-
-<p>As described earlier, applications check licensing status not by contacting
-the licensing server directly, but by binding to a service provided by the
-Android Market application and initiating a license check request. The Android
-Market service then handles the direct communication with the licensing server
-and finally routes the response back to your application. To debug and test
-licensing in your application, you need to set up a runtime environment that
-includes the necessary Android Market service, so that your application is able
-to send license check requests to the licensing server. </p>
-
-<p>There are two types of runtime environment that you can use: </p>
-
-<ul>
-<li>An Android-powered device that includes the Android Market application, or</li>
-<li>An Android emulator running the Google APIs Add-on, API level 8 (release 2)
-or higher</li>
-</ul>
-
-<p>The sections below provide more information. </p>
-
-<h4 id="runtime-device">Running on a device</h4>
-
-<p>You can use an Android-powered device as the runtime environment for
-debugging and testing licensing on your application.</p>
-
-<p>The device you use must:</p>
-
-<ul>
-<li>Run a standard version of the Android 1.5 or later (API level
-3 or higher) platform, <em>and</em> </li>
-<li>Run a system image on which the Android Market client application
-is preinstalled. </li>
-</ul>
-
-<p>If Android Market is not preinstalled in the system image, your application won't
-be able to communicate with the Android Market licensing server. </p>
-
-<p>For general information about how to set up a device for use in developing
-Android applications, see <a
-href="{@docRoot}guide/developing/device.html">Developing on a Device</a>.</p>
-
-<h4 id="runtime-emulator">Running on an Android emulator</h4>
-
-<p>You can also use an Android emulator as your runtime
-environment for debugging and testing licensing.</p>
-
-<p>Because the standard Android platforms provided in the Android SDK <em>do
-not</em> include Android Market, you need to download the Google APIs Add-On
-platform, API Level 8 (or higher), from the SDK repository. After downloading
-the add-on, you need to create an AVD configuration that uses that system image.
-</p>
-
-<p>The Google APIs Add-On does not include the full Android Market client.
-However, it does provide: </p>
-
-<ul>
-<li>An Android Market background service that implements the
-ILicensingService remote interface, so that your application can
-send license checks over the network to the licensing server. </li>
-<li>A set of underlying account services that let you add an a Google account on
-the AVD and sign in using your publisher account or test account credentials.
-Signing in using your publisher or test account enables you to debug and test
-your application without having publish it. For more information see <a
-href="#acct-signin">Signing in to an authorized account</a>, below.</li>
-</ul>
-
-<p>Several versions of the add-on are available in the SDK repository, but only
-<strong>Google APIs Add-On, API 8 (release 2) or higher</strong> version of the
-add-on includes the necessary Android Market services. This means that you
-cannot use Google APIs Add-On API 7 or lower as a runtime environment for
-developing licensing on an emulator.</p>
-
-<div style="margin-bottom:2em;">
-
-<img src="{@docRoot}images/licensing_gapis_8.png" style="text-align:left;margin-bottom:0;" />
-<div style="margin:0 2em;padding:0"><strong>Figure 3.</strong> Google APIs
-Add-On, API 8 (release 2) or higher lets you debug and test your licensing
-implementation in an emulator.</div>
-</div>
-
-<p>To set up an emulator for adding licensing to an application, follow
-these steps: </p>
-
-<ol>
-  <li>Launch the Android SDK and AVD Manager. </li>
-  <li>In the <strong>Available Packages</strong> panel, select and download the
-SDK component "Google APIs (Google Inc.) - API Level 8" (or higher) from the SDK
-repository, as shown in the figure above.
-  <p>When the download is complete, use the Android SDK and AVD Manager to
-create a new AVD based on that component, described next.</p></li>
-  <li>In the <strong>Virtual
-Devices</strong> panel of the Android SDK and AVD Manager, click
-<strong>New</strong> and set the configuration details for the new AVD. </li>
-  <li>In the dialog that appears, assign a descriptive name to the AVD and then
-use the "Target" menu to choose the "Google APIs (Google Inc.) - API Level 8" as
-the system image to run on the new AVD. Set the other configuration details as
-needed and then click <strong>Create AVD</strong> to finish. The SDK tools
-create the new AVD configuration, which then appears in the list of available
-Android Virtual Devices.</li>
-</ol>
-
-<p>If you are not familiar with AVDs or how to use them, see <a
-href="{@docRoot}guide/developing/devices/index.html">Managing Virtual Devices</a>.</p>
-
-<h4 id="project-update">Updating your project configuration</h4>
-
-<p>After you set up a runtime environment that meets the requirements described
-above &mdash; either on an actual device or on an emulator &mdash; make sure to
-update your application project or build scripts as needed, so that your compiled
-<code>.apk</code> files that use licensing are deployed into that environment.
-In particular, if you are developing in Eclipse, make sure that you set up a
-Run/Debug Configuration that targets the appropriate device or AVD. </p>
-
-<p>You do not need to make any changes to your application's
-build configuration, provided that the project is already configured to compile
-against a standard Android 1.5 (API level 3) or higher library. For example:
-
-<ul>
-<li>If you have an existing application that is compiled against
-the Android 1.5 library, you do not need to make any changes to your
-build configuration to support licensing. The build target meets the minimum
-requirements for licensing, so you would continue building
-against the same version of the Android platform.</li>
-
-<li>Similarly, if you are building against Android 1.5 (API level 3) but
-are using an emulator running the Google APIs Add-On API 8 as the application's
-runtime environment, there is no need to change your application's build
-configuration. </li>
-</ul>
-
-<p>In general, adding licensing to an application should have no impact
-whatsoever on the application's build configuration.</p>
-
-
-<h3 id="download-lvl">Downloading the LVL</h3>
-
-<p>The License Verification Library (LVL) is a collection of helper classes that
-greatly simplify the work that you need to do to add licensing to your
-application. In all cases, we recommend that you download the LVL and use it as
-the basis for the licensing implementation in your application.</p>
-
-<p>The LVL is available as a downloadable component of the Android SDK. The
-component includes: </p>
-
-<ul>
-<li>The LVL sources, stored inside an Android library project. </li>
-<li>An example application called "sample" that depends on the LVL library
-project. The example illustrates how an application uses the library helper
-classes to check and enforce licensing.</li>
-</ul>
-
-<p>To download the LVL component into your development environment, use the
-Android SDK and AVD Manager. Launch the Android SDK and AVD Manager and then
-select the "Market Licensing" component, as shown in the figure below.
-Accept the terms and click <strong>Install Selected</strong> to begin the download. </p>
-
-<div style="margin-bottom:2em;">
-
-<img src="{@docRoot}images/licensing_package.png" style="text-align:left;margin-bottom:0;" />
-<div style="margin:0 2em;padding:0"><strong>Figure 4.</strong> The Market
-Licensing package contains the LVL and the LVL sample application. </div>
-</div>
-
-<p>When the download is complete, the Android SDK and AVD Manager installs both
-the LVL library project and the example application into these directories: </p>
-
-<p style="margin-left:2em"><code>&lt;<em>sdk</em>&gt;/extras/google/market_licensing/library/</code>
-&nbsp;&nbsp;(the LVL library project)<br />
-<code>&lt;<em>sdk</em>&gt;/extras/google/market_licensing/sample/</code>&nbsp;&nbsp;(the example
-application)</p>
-
-<p>If you aren't familiar with how to download components into your SDK, see the
-<a href="{@docRoot}sdk/adding-components.html">Adding SDK Components</a>
-document. </p>
-
-
-<h3 id="lvl-setup">Setting Up the Licensing Verification Library</h3>
-
-<p>After downloading the LVL to your computer, you need to set it up in your
-development environment, either as an Android library project or by
-copying (or importing) the library sources directly into your existing
-application package. In general, using the LVL as a library project is recommended,
-since it lets you reuse your licensing code across multiple applications and
-maintain it more easily over time. Note that the LVL is not designed to be
-compiled separately and added to an application as a static .jar file. </p>
-
-<h4>Moving the library sources to a new location</h4>
-
-<p>Because you will be customizing the LVL sources to some extent, you should
-make sure to <em>move or copy</em> the library sources (the entire
-directory at <code>&lt;<em>sdk</em>&gt;/market_licensing/library/</code>)
-to a working directory outside of the SDK. You should then use the relocated
-sources as your working set. If you are using a source-code management
-system, add and track the sources that are in the working location rather
-than those in default location in the SDK. </p>
-
-<p>Moving the library sources is important is because, when you later update the
-Market licensing package, the SDK installs the new files to the same location as
-the older files. Moving your working library files to a safe location ensures
-that your work won't be inadvertently overwritten should you download a new
-version of the LVL.</p>
-
-<h4>Creating the LVL as a library project</h4>
-
-<div class="sidebox-wrapper">
-<div class="sidebox">
-<h2>Working with library projects</h2>
-
-<p>The LVL is provided as an Android library project, which means that you can
-share its code and resources across multiple applications. </p>
-
-<p style="margin-top:.5em;">If you aren't familiar with library projects or how
-to use them, see <a href="{@docRoot}guide/developing/projects/index.html#LibraryProjects">
-Managing Projects</a>.
-</p>
-</div>
-</div>
-
-<p>The recommended way of using the LVL is setting it up as a new Android
-<em>library project</em>. A library project is a type of development project
-that holds shared Android source code and resources. Other Android application
-projects can reference the library project and, at build time, include its
-compiled sources in their <code>.apk</code> files. In the context of licensing,
-this means that you can do most of your licensing development once, in a library
-project, then include the library sources in your various application projects.
-In this way, you can easily maintain a uniform implementation of licensing
-across all of your projects and maintain it centrally. </p>
-
-<p>The LVL is provided as a configured library project &mdash; once you have
-downloaded it, you can start using it right away. </p>
-
-<p>If you are working in Eclipse with ADT, you need to add the LVL to your
-workspace as a new development project, in the same way as you would a new
-application project. </p>
-
-<ol>
-<li>Use the New Project Wizard to create a new
-project from existing sources. Select the LVL's <code>library</code> directory
-(the directory containing the library's AndroidManifest.xml file) as the project
-root.</li>
-<li>When you are creating the library project, you can select any application
-name, package, and set other fields as needed. </li>
-<li>For the library's build target, select Android 1.5 (API level 3) or higher.</li>
-</ol>
-
-<p> When created, the project is
-predefined as a library project in its <code>project.properties</code> file, so
-no further configuration is needed. </p>
-
-<p>For more information about how to create an application project or work with
-library projects in Eclipse, see <a
-href="{@docRoot}guide/developing/projects/projects-eclipse.html">Managing Projects from
-Eclipse with ADT</a></p>.
-
-<h4>Copying the LVL sources to your application</h4>
-
-<p>As an alternative to adding the LVL as a library project, you can copy the
-library sources directly into your application. To do so, copy (or import) the
-LVL's <code>library/src/com</code> directory into your application's
-<code>src/</code> directory.</p>
-
-<p>If you add the LVL sources directly to your application, you can skip the
-next section and start working with the library, as described in <a
-href="#app-integration"></a>.</p>
-
-
-<h3 id="add-library">Including the LVL library project sources in your
-application</h3>
-
-<p>If you want to use the LVL sources as a library project, you need to add a
-reference to the LVL library project in your application project properties. This tells
-build tools to include the LVL library project sources in your application at
-compile time. The process for adding a reference to a library project depends
-on your development environment, as described below.</p>
-
-<p> If you are developing in Eclipse with ADT, you should already have added the
-library project to your workspace, as described in the previous section. If you
-haven't done that already, do it now before continuing. </p>
-
-<p>Next, open the application's project properties window, as shown below.
-Select the "Android" properties group and click <strong>Add</strong>, then
-choose the LVL library project (com_android_vending_licensing) and click
-<strong>OK</strong>. For more information, see
-<a href="{@docRoot}guide/developing/projects/projects-eclipse.html#SettingUpLibraryProject">
-Managing Projects from Eclipse with ADT</a></p>.
-
-<div style="margin-bottom:2em;">
-
-<img src="{@docRoot}images/licensing_add_library.png" style="text-align:left;margin-bottom:0;" />
-<div style="margin:0 2em;padding:0"><strong>Figure 5.</strong> If you are
-working in Eclipse with ADT, you can add the LVL library project to your
-application from the application's project properties.</div>
-</div>
-
-<p>If you are developing using the SDK command-line tools, navigate to the
-directory containing your application project and open the
-<code>project.properties</code> file. Add a line to the file that specifies the
-<code>android.library.reference.&lt;n&gt;</code> key and the path to the
-library. For example: </p>
-
-<pre>android.library.reference.1=path/to/library_project</pre>
-
-<p>Alternatively, you can use this command to update the project
-properties, including the reference to the library project:</p>
-
-<pre class="no-pretty-print" style="color:black">android update lib-project
---target <em>&lt;target_ID&gt;</em> \
---path <em>path/to/my/app_project</em> \
---library <em>path/to/my/library_project</em>
-</pre>
-
-<p>For more information about working with library projects,
-see <a href="{@docRoot}guide/developing/projects/projects-cmdline.html#SettingUpLibraryProject">
-Managing Projects from the Command Line</a></p>.
-
-
-<h2 id="app-integration">Integrating the LVL with Your Application</h2>
-
-<p>Once you've followed the steps above to set up a publisher account and
-development environment, you are ready to begin integrating the LVL with your
-application. </p>
-
-<p>Integrating the LVL with your application code involves these tasks:</p>
-
-<ol>
-<li><a href="#manifest-permission">Adding the licensing permission</a> your application's manifest.</li>
-<li><a href="#impl-Policy">Implementing a Policy</a> &mdash; you can choose one of the full implementations provided in the LVL or create your own.</li>
-<li><a href="#impl-Obfuscator">Implementing an Obfuscator</a>, if your Policy will cache any license response data. </li>
-<li><a href="#impl-lc">Adding code to check the license</a> in your application's main Activity</li>
-<li><a href="#impl-DeviceLimiter">Implementing a DeviceLimiter</a> (optional and not recommended for most applications)</li>
-</ol>
-
-<p>The sections below describe these tasks. When you are done with the
-integration, you should be able to compile your application successfully and you
-can begin testing, as described in <a href="#test-env">Setting Up the Test
-Environment</a>.</p>
-
-<p>For an overview of the full set of source files included in the LVL, see <a
-href="#lvl-summary">Summary of LVL Classes and Interfaces</a>.</p>
-
-
-<h3 id="manifest-permission">Adding the licensing permission to your
-AndroidManifest.xml</h3>
-
-<p>To use the Android Market application for sending a license check to the
-server, your application must request the proper permission,
-<code>com.android.vending.CHECK_LICENSE</code>. If your application does
-not declare the licensing permission but attempts to initiate a license check,
-the LVL throws a security exception.</p>
-
-<p>To request the licensing permission in your application, declare a <a
-href="{@docRoot}guide/topics/manifest/uses-permission-element.html"><code>&lt;uses-permission&gt;</code></a>
-element as a child of <code>&lt;manifest&gt;</code>, as follows: </p>
-
-<p style="margin-left:2em;"><code>&lt;uses-permission
-android:name="com.android.vending.CHECK_LICENSE"&gt;</code></p>
-
-<p>For example, here's how the LVL sample application declares the permission:
-</p>
-
-<pre>&lt;?xml version="1.0" encoding="utf-8"?&gt;
-
-&lt;manifest xmlns:android="http://schemas.android.com/apk/res/android" ..."&gt;
-    &lt;!-- Devices &gt;= 3 have version of Android Market that supports licensing. --&gt;
-    &lt;uses-sdk android:minSdkVersion="3" /&gt;
-    &lt;!-- Required permission to check licensing. --&gt;
-    &lt;uses-permission android:name="com.android.vending.CHECK_LICENSE" /&gt;
-    ...
-&lt;/manifest&gt;
-</pre>
-
-<p class="note"><strong>Note:</strong> Currently, you cannot declare the
-<code>CHECK_LICENSE</code> permission in the LVL library project's manifest,
-because the SDK Tools will not merge it into the manifests of dependent
-applications. Instead, you must declare the permission in each dependent
-application's manifest. </p>
-
-
-<h3 id="impl-Policy">Implementing a Policy</h3>
-
-<div class="sidebox-wrapper">
-<div class="sidebox">
-<h2>ServerManagedPolicy</h2>
-
-<p>The LVL includes a complete Policy implementation called ServerManagedPolicy
-that makes use of license-management settings provided by the Android Market
-server. </p>
-
-<p style="margin-top:.5em;">Use of ServerManagedPolicy as the basis for your
-Policy is strongly recommended. For more information, see <a
-href="#ServerManagedPolicy">ServerManagedPolicy</a> section, below.</p>
-
-</div>
-</div>
-
-<p>Android Market licensing service does not itself determine whether a
-given user with a given license should be granted access to your application.
-Rather, that responsibility is left to a Policy implementation that you provide
-in your application.</p>
-
-<p>Policy is an interface declared by the LVL that is designed to hold your
-application's logic for allowing or disallowing user access, based on the result
-of a license check. To use the LVL, your application <em>must</em> provide an
-implementation of Policy. </p>
-
-<p>The Policy interface declares two methods, <code>allowAccess()</code> and
-<code>processServerResponse()</code>, which are called by a LicenseChecker
-instance when processing a response from the license server. It also declares an
-enum called <code>LicenseResponse</code>, which specifies the license response
-value passed in calls to <code>processServerResponse()</code>. </p>
-
-<ul>
-<li><code>processServerResponse()</code> lets you preprocess the raw response
-data received from the licensing server, prior to determining whether to grant
-access.
-
-<p>A typical implementation would extract some or all fields from the license
-response and store the data locally to a persistent store, such as through
-{@link android.content.SharedPreferences} storage, to ensure that the data is
-accessible across application invocations and device power cycles. For example,
-a Policy would maintain the timestamp of last successful license check, the
-retry count, the license validity period, and similar information in a
-persistent store, rather than resetting the values each time the application is
-launched.</p>
-
-<p>When storing response data locally, the Policy must ensure that the data is
-obfuscated (see <a href="#impl-Obfuscator">Implementing an Obfuscator</a>,
-below).</p></li>
-
-<li><code>allowAccess()</code> determines whether to grant the user access to
-your application, based on any available license response data (from the
-licensing server or from cache) or other application-specific information.  For
-example, your implementation of <code>allowAccess()</code> could take into
-account additional criteria, such as usage or other data retrieved from a
-backend server. In all cases, an implementation of <code>allowAccess()</code>
-should only return <code>true</code> if the user is licensed to use the
-application, as determined by the licensing server, or if there is a transient
-network or system problem that prevents the license check from completing. In
-such cases, your implementation can maintain a count of retry responses and
-provisionally allow access until the next license check is complete.</li>
-
-</ul>
-
-<p>To simplify the process of adding licensing to your application and to
-provide an illustration of how a Policy should be designed, the LVL includes
-two full Policy implementations that you can use without modification or
-adapt to your needs:</p>
-
-<ul>
-<li><a href="#ServerManagedPolicy">ServerManagedPolicy</a>, a flexible Policy
-that uses server-provided settings and cached responses to manage access across
-varied network conditions, and</li>
-<li><a href="#StrictPolicy">StrictPolicy</a>, which does not cache any response
-data and allows access <em>only</em> if the server returns a licensed
-response.</li>
-</ul>
-
-<p>For most applications, the use of ServerManagedPolicy is highly
-recommended. ServerManagedPolicy is the LVL default and is integrated with
-the LVL sample application.</p>
-
-
-<h4 id="custom-policies">Guidelines for custom policies</h4>
-
-<p>In your licensing implementation, you can use one of the complete policies
-provided in the LVL (ServerManagedPolicy or StrictPolicy) or you can create a
-custom policy. For any type of custom policy, there are several important design
-points to understand and account for in your implementation.</p>
-
-<p>The licensing server applies general request limits to guard against overuse
-of resources that could result in denial of service. When an application exceeds
-the request limit, the licensing server returns a 503 response, which gets
-passed through to your application as a general server error. This means that no
-license response will be available to the user until the limit is reset, which
-can affect the user for an indefinite period.</p>
-
-<p>If you are designing a custom policy, we recommend that the Policy:
-<ol>
-<!-- <li>Limits the number of points at which your app calls for a license check
-to the minimum. </li> -->
-<li>Caches (and properly obfuscates) the most recent successful license response
-in local persistent storage.</li>
-<li>Returns the cached response for all license checks, for as long as the
-cached response is valid, rather than making a request to the licensing server.
-Setting the response validity according to the server-provided <code>VT</code>
-extra is highly recommended. See <a href="#extras">Server Response Extras</a>
-for more information.</li>
-<li>Uses an exponential backoff period, if retrying any requests the result in
-errors. Note that the Android Market client automatically retries failed
-requests, so in most cases there is no need for your Policy to retry them.</li>
-<li>Provides for a "grace period" that allows the user to access your
-application for a limited time or number of uses, while a license check is being
-retried. The grace period benefits the user by allowing access until the next
-license check can be completed successfully and it benefits you by placing a
-hard limit on access to your application when there is no valid license response
-available.</li>
-</ol>
-
-<p>Designing your Policy according to the guidelines listed above is critical,
-because it ensures the best possible experience for users while giving you
-effective control over your application even in error conditions. </p>
-
-<p>Note that any Policy can use settings provided by the licensing server to
-help manage validity and caching, retry grace period, and more. Extracting the
-server-provided settings is straightforward and making use of them is highly
-recommended. See the ServerManagedPolicy implementation for an example of how to
-extract and use the extras. For a list of server settings and information about
-how to use them, see  <a href="#extras">Server Response Extras</a> in the
-Appendix of this document.</p>
-
-<h4 id="ServerManagedPolicy">ServerManagedPolicy</h4>
-
-<div class="sidebox-wrapper">
-<div class="sidebox">
-<h2>Server Response Extras</h2>
-
-<p>For certain types of licensing responses, the licensing server appends extra
-settings to the responses, to help the application manage licensing effectively.
-</p>
-
-<p style="margin-top:.5em;">See <a href="#extras">Server Response Extras</a> for
-a list of settings and <code>ServerManagedPolicy.java</code> for information
-about how a Policy can use the extras.</p>
-
-</div>
-</div>
-
-<p>The LVL includes a full and recommended implementation of the Policy
-interface called ServerManagedPolicy. The implementation is integrated with the
-LVL classes and serves as the default Policy in the library. </p>
-
-<p>ServerManagedPolicy provides all of the handling for license and retry
-responses. It caches all of the response data locally in a
-{@link android.content.SharedPreferences} file, obfuscating it with the
-application's Obfuscator implementation. This ensures that the license response
-data is secure and persists across device power cycles. ServerManagedPolicy
-provides concrete implementations of the interface methods
-<code>processServerResponse()</code> and <code>allowAccess()</code> and also
-includes a set of supporting methods and types for managing license
-responses.</p>
-
-<p>Importantly, a key feature of ServerMangedPolicy is its use of
-server-provided settings as the basis for managing licensing across an
-application's refund period and through varying network and error conditions.
-When an application contacts the Android Market server for a license check, the
-server appends several settings as key-value pairs in the extras field of certain
-license response types. For example, the server provides recommended values for the
-application's license validity period, retry grace period, and maximum allowable
-retry count, among others. ServerManagedPolicy extracts the values from the
-license response in its <code>processServerResponse()</code> method and checks
-them in its <code>allowAccess()</code> method. For a list of the server-provided
-settings used by ServerManagedPolicy, see <a href="#extras">Server Response
-Extras</a> in the Appendix of this document.</p>
-
-<p>For convenience, best performance, and the benefit of using license settings
-from the Android Market server, <strong>using ServerManagedPolicy as your
-licensing Policy is strongly recommended</strong>. </p>
-
-<p>If you are concerned about the security of license response data that is
-stored locally in SharedPreferences, you can use a stronger obfuscation
-algorithm or design a stricter Policy that does not store license data. The LVL
-includes an example of such a Policy &mdash; see <a
-href="#StrictPolicy">StrictPolicy</a> for more information.</p>
-
-<p>To use ServerManagedPolicy, simply import it to your Activity, create an
-instance, and pass a reference to the instance when constructing your
-LicenseChecker. See <a href="#lc-lcc">Instantiate LicenseChecker and
-LicenseCheckerCallback</a> for more information. </p>
-
-<h4 id="StrictPolicy">StrictPolicy</h4>
-
-<p>The LVL includes an alternative full implementation of the Policy interface
-called StrictPolicy. The StrictPolicy implementation provides a more restrictive
-Policy than ServerManagedPolicy, in that it does not allow the user to access
-the application unless a license response is received from the server at the
-time of access that indicates that the user is licensed.</p>
-
-<p>The principal feature of StrictPolicy is that it does not store <em>any</em>
-license response data locally, in a persistent store. Because no data is stored,
-retry requests are not tracked and cached responses can not be used to fulfill
-license checks. The Policy allows access only if:</p>
-
-<ul>
-<li>The license response is received from the licensing server, and </li>
-<li>The license response indicates that the user is licensed to access the
-application. </li>
-</ul>
-
-<p>Using StrictPolicy is appropriate if your primary concern is to ensure that,
-in all possible cases, no user will be allowed to access the application unless
-the user is confirmed to be licensed at the time of use. Additionally, the
-Policy offers slightly more security than ServerManagedPolicy &mdash; since
-there is no data cached locally, there is no way a malicious user could tamper
-with the cached data and obtain access to the application.</p>
-
-<p>At the same time, this Policy presents a challenge for normal users, since it
-means that they won't be able to access the application when there is no network
-(cell or wi-fi) connection available. Another side-effect is that your
-application will send more license check requests to the server, since using a
-cached response is not possible.</p>
-
-<p>Overall, this policy represents a tradeoff of some degree of user convenience
-for absolute security and control over access. Consider the tradeoff carefully
-before using this Policy.</p>
-
-<p>To use StrictPolicy, simply import it to your Activity, create an instance,
-and pass a reference to it when constructing your LicenseChecker. See
-<a href="#lc-lcc">Instantiate LicenseChecker and LicenseCheckerCallback</a>
-for more information. </p>
-
-<h3 id="impl-Obfuscator">Implementing an Obfuscator</h3>
-
-<div class="sidebox-wrapper">
-<div class="sidebox">
-<h2>AESObfuscator</h2>
-
-<p>The LVL includes a full Obfuscator implementation in the
-<code>AESObfuscator.java</code> file. The Obfuscator uses AES encryption to
-obfuscate/unobfuscate data. If you are using a Policy (such as
-ServerManagedPolicy) that caches license response data, using AESObfuscator as
-basis for your Obfuscator implementation is highly recommended. </p>
-
-</div>
-</div>
-
-<p>A typical Policy implementation needs to save the license response data for
-an application to a persistent store, so that it is accessible across
-application invocations and device power cycles.  For example, a Policy would
-maintain the timestamp of the last successful license check, the retry count,
-the license validity period, and similar information in a persistent store,
-rather than resetting the values each time the application is launched. The
-default Policy included in the LVL, ServerManagedPolicy, stores license response
-data in a {@link android.content.SharedPreferences} instance, to ensure that the
-data is persistent. </p>
-
-<p>Because the Policy will use stored license response data to determine whether
-to allow or disallow access to the application, it <em>must</em> ensure that any
-stored data is secure and cannot be reused or manipulated by a root user on a
-device. Specifically, the Policy must always obfuscate the data before storing
-it, using a key that is unique for the application and device. Obfuscating using
-a key that is both application-specific and device-specific is critical, because
-it prevents the obfuscated data from being shared among applications and
-devices.</p>
-
-<p>The LVL assists the application with storing its license response data in a
-secure, persistent manner. First, it provides an Obfuscator
-interface that lets your application supply the obfuscation algorithm of its
-choice for stored data. Building on that, the LVL provides the helper class
-PreferenceObfuscator, which handles most of the work of calling the
-application's Obfuscator class and reading and writing the obfuscated data in a
-SharedPreferences instance. </p>
-
-<p>The LVL provides a full Obfuscator implementation called
-AESObfuscator that uses AES encryption to obfuscate data. You can
-use AESObfuscator in your application without modification or you
-can adapt it to your needs. For more information, see the next section.</p>
-
-
-<h4 id="AESObfuscator">AESObfuscator</h4>
-
-<p>The LVL includes a full and recommended implementation of the Obfuscator
-interface called AESObfuscator. The implementation is integrated with the
-LVL sample application and serves as the default Obfuscator in the library. </p>
-
-<p>AESObfuscator provides secure obfuscation of data by using AES to
-encrypt and decrypt the data as it is written to or read from storage.
-The Obfuscator seeds the encryption using three data fields provided
-by the application: </p>
-
-<ol>
-<li>A salt &mdash; an array of random bytes to use for each (un)obfuscation. </li>
-<li>An application identifier string, typically the package name of the application.</li>
-<li>A device identifier string, derived from as many device-specific sources
-as possible, so as to make it as unique.</li>
-</ol>
-
-<p>To use AESObfuscator, first import it to your Activity. Declare a private
-static final array to hold the salt bytes and initialize it to 20 randomly
-generated bytes.</p>
-
-<pre>    ...
-    // Generate 20 random bytes, and put them here.
-    private static final byte[] SALT = new byte[] {
-     -46, 65, 30, -128, -103, -57, 74, -64, 51, 88, -95,
-     -45, 77, -117, -36, -113, -11, 32, -64, 89
-     };
-    ...
-</pre>
-
-<p>Next, declare a variable to hold a device identifier and generate a value for
-it in any way needed. For example, the sample application included in the LVL
-queries the system settings for the
-<code>android.Settings.Secure.ANDROID_ID</code>, which is unique to each device.
-</p>
-
-<p>Note that, depending on the APIs you use, your application might need to
-request additional permissions in order to acquire device-specific information.
-For example, to query the {@link android.telephony.TelephonyManager} to obtain
-the device IMEI or related data, the application will also need to request the
-<code>android.permission.READ_PHONE_STATE</code> permission in its manifest.</p>
-
-<p>Before requesting new permissions for the <em>sole purpose</em> of acquiring
-device-specific information for use in your Obfuscator, consider
-how doing so might affect your application or its filtering on Android Market
-(since some permissions can cause the SDK build tools to add
-the associated <code>&lt;uses-feature&gt;</code>).</p>
-
-<p>Finally, construct an instance of AESObfuscator, passing the salt,
-application identifier, and device identifier. You can construct the instance
-directly, while constructing your Policy and LicenseChecker. For example:</p>
-
-<pre>    ...
-    // Construct the LicenseChecker with a Policy.
-    mChecker = new LicenseChecker(
-        this, new ServerManagedPolicy(this,
-            new AESObfuscator(SALT, getPackageName(), deviceId)),
-        BASE64_PUBLIC_KEY  // Your public licensing key.
-        );
-    ...
-</pre>
-
-<p>For a complete example, see MainActivity in the LVL sample application.</p>
-
-
-<h3 id="impl-lc">Checking the license from your application's main Activity</h3>
-
-<p>Once you've implemented a Policy for managing access to your application, the
-next step is to add a license check to your application, which initiates a query
-to the licensing server if needed and manages access to the application based on
-the license response. All of the work of adding the license check and handling
-the response takes place in your main {@link android.app.Activity} source file.
-</p>
-
-<p>To add the license check and handle the response, you must:</p>
-
-<ol>
-    <li><a href="#imports">Add imports</a></li>
-    <li><a href="#lc-impl">Implement LicenseCheckerCallback</a> as a private inner class</li>
-    <li><a href="#thread-handler">Create a Handler</a> for posting from LicenseCheckerCallback to the UI thread</li>
-    <li><a href="#lc-lcc">Instantiate LicenseChecker</a> and LicenseCheckerCallback</li>
-    <li><a href="#check-access">Call checkAccess()</a> to initiate the license check</li>
-    <li><a href="#account-key">Embed your public key</a> for licensing</li>
-    <li><a href="#handler-cleanup">Call your LicenseChecker's onDestroy() method</a> to close IPC connections.</li>
-</ol>
-
-<p>The sections below describe these tasks. </p>
-
-<h4 id="lc-overview">Overview of license check and response</h4>
-
-<div class="sidebox-wrapper">
-<div class="sidebox">
-<h2>Example: MainActivity</h2>
-
-<p>The sample application included with the LVL provides a full example of how
-to initiate a license check and handle the result, in the
-<code>MainActivity.java</code> file.</p>
-
-</div>
-</div>
-
-<p>In most cases, you should add the license check to your application's main
-{@link android.app.Activity}, in the <code>onCreate()</code> method. This
-ensures that when the user launches your application directly, the license check
-will be invoked immediately. In some cases, you can add license checks in other
-locations as well. For example, if your application includes multiple Activity
-components that other applications can start by {@link android.content.Intent},
-you could add license checks in those Activities.</p>
-
-<p>A license check consists of two main actions: </p>
-
-<ul>
-<li>A call to a method to initiate the license check &mdash; in the LVL, this is
-a call to the <code>checkAccess()</code> method of a LicenseChecker object that
-you construct.</li>
-<li>A callback that returns the result of the license check. In the LVL, this is
-a <code>LicenseCheckerCallback</code> interface that you implement. The
-interface declares two methods, <code>allow()</code> and
-<code>dontAllow()</code>, which are invoked by the library based on to the
-result of the license check. You implement those two methods with whatever logic
-you need, to allow or disallow the user access to your application. Note that
-these methods do not determine <em>whether</em> to allow access &mdash; that
-determination is the responsibility of your Policy implementation. Rather, these
-methods simply provide the application behaviors for <em>how</em> to allow and
-disallow access (and handle application errors).</li>
-</ul>
-
-<div style="margin-bottom:2em;">
-
-<img src="{@docRoot}images/licensing_flow.png" style="text-align:left;margin-bottom:0;margin-left:3em;" />
-<div style="margin:.5em 0 1.5em 2em;padding:0"><strong>Figure 6.</strong> Overview of a
-typical license check interaction.</div>
-</div>
-
-<p>The diagram above illustrates how a typical license check takes place: </p>
-
-<ol>
-<li>Code in the application's main Activity instantiates LicenseCheckerCallback
-and LicenseChecker objects. When constructing LicenseChecker, the code passes in
-{@link android.content.Context}, a Policy implementation to use, and the
-publisher account's public key for licensing as parameters. </li>
-<li>The code then calls the <code>checkAccess()</code> method on the
-LicenseChecker object. The method implementation calls the Policy to determine
-whether there is a valid license response cached locally, in
-{@link android.content.SharedPreferences}.
-<ul>
-<li>If so, the <code>checkAccess()</code> implementation calls
-<code>allow()</code>.</li>
-<li>Otherwise, the LicenseChecker initiates a license check request that is sent
-to the licensing server.</li>
-</ul>
-<p class="note"><strong>Note:</strong> The licensing server always returns
-<code>LICENSED</code> when you perform a license check of a draft application.</p>
-</li>
-<li>When a response is received, LicenseChecker creates a LicenseValidator that
-verifies the signed license data and extracts the fields of the response, then
-passes them to your Policy for further evaluation.
-  <ul>
-    <li>If the license is valid, the Policy caches the response in
-SharedPreferences and notifies the validator, which then calls the
-<code>allow()</code> method on the LicenseCheckerCallback object. </li>
-    <li>If the license not valid, the Policy notifies the validator, which calls
-the <code>dontAllow()</code> method on LicenseCheckerCallback. </li>
-  </ul>
-</li>
-<li>In case of a recoverable local or server error, such as when the network is
-not available to send the request, LicenseChecker passes a RETRY response to
-your Policy's <code>processServerResponse()</code> method. </li>
-<li>In case of a application error, such as when the application attempts to
-check the license of an invalid package name, LicenseChecker passes an error
-response to the LicenseCheckerCallback's  <code>applicationError()</code>
-method. </li>
-</ol>
-
-<p>Note that, in addition to initiating the license check and handling the
-result, which are described in the sections below, your application also needs
-to provide a <a href="#impl-Policy">Policy implementation</a> and, if the Policy
-stores response data (such as ServerManagedPolicy), an <a
-href="#impl-Obfuscator">Obfuscator</a> implementation. </p>
-
-
-<h4 id="imports">Add imports</h4>
-
-<p>First, open the class file of the application's main Activity and import
-LicenseChecker and LicenseCheckerCallback from the LVL package.</p>
-
-<pre>    import com.android.vending.licensing.LicenseChecker;
-    import com.android.vending.licensing.LicenseCheckerCallback;</pre>
-
-<p>If you are using the default Policy implementation provided with the LVL,
-ServerManagedPolicy, import it also, together with the AESObfuscator. If you are
-using a custom Policy or Obfuscator, import those instead. </p>
-
-<pre>    import com.android.vending.licensing.ServerManagedPolicy;
-    import com.android.vending.licensing.AESObfuscator;</pre>
-
-<h4 id="lc-impl">Implement LicenseCheckerCallback as a private inner class</h4>
-
-<p>LicenseCheckerCallback is an interface provided by the LVL for handling
-result of a license check. To support licensing using the LVL, you must
-implement LicenseCheckerCallback and
-its methods to allow or disallow access to the application.</p>
-
-<p>The result of a license check is always a call to one of the
-LicenseCheckerCallback methods, made based on the validation of the response
-payload, the server response code itself, and any additional processing provided
-by your Policy. Your application can implement the methods in any way needed. In
-general, it's best to keep the methods simple, limiting them to managing UI
-state and application access. If you want to add further processing of license
-responses, such as by contacting a backend server or applying custom constraints,
-you should consider incorporating that code into your Policy, rather than
-putting it in the LicenseCheckerCallback methods. </p>
-
-<p>In most cases, you should declare your implementation of
-LicenseCheckerCallback as a private class inside your application's main
-Activity class. </p>
-
-<p>Implement the <code>allow()</code> and <code>dontAllow()</code> methods as
-needed. To start with, you can use simple result-handling behaviors in the
-methods, such as displaying the license result in a dialog. This helps you get
-your application running sooner and can assist with debugging. Later, after you
-have determined the exact behaviors you want, you can add more complex handling.
-</p>
-
-<p>Some suggestions for handling unlicensed responses in
-<code>dontAllow()</code> include: </p>
-
-<ul>
-<li>Display a "Try again" dialog to the user, including a button to initiate a
-new license check. </li>
-<li>Display a "Purchase this application" dialog, including a button that
-deep-links the user to the application's details page on Market, from which the
-use can purchase the application. For more information on how to set up such
-links, see <a
-href="{@docRoot}guide/publishing/publishing.html#marketintent">Using Intents to
-Launch the Market Application on a Device</a>. </li>
-<li>Display a Toast notification that indicates that the features of the
-application are limited because it is not licensed. </li>
-</ul>
-
-<p>The example below shows how the LVL sample application implements
-LicenseCheckerCallback, with methods that display the license check result in a
-dialog. </p>
-
-<pre>    private class MyLicenseCheckerCallback implements LicenseCheckerCallback {
-        public void allow() {
-            if (isFinishing()) {
-                // Don't update UI if Activity is finishing.
-                return;
-            }
-            // Should allow user access.
-            displayResult(getString(R.string.allow));
-        }
-
-        public void dontAllow() {
-            if (isFinishing()) {
-                // Don't update UI if Activity is finishing.
-                return;
-            }
-            displayResult(getString(R.string.dont_allow));
-            // Should not allow access. An app can handle as needed,
-            // typically by informing the user that the app is not licensed
-            // and then shutting down the app or limiting the user to a
-            // restricted set of features.
-            // In this example, we show a dialog that takes the user to Market.
-            showDialog(0);
-        }
-    }
-</pre>
-
-<p>Additionally, you should implement the <code>applicationError()</code>
-method, which the LVL calls to let your application handle errors that are not
-retryable. For a list of such errors, see <a
-href="#server-response-codes">Server Response Codes</a> in the Appendix of this
-document. You can implement the method in any way needed. In most cases, the
-method should log the error code and call <code>dontAllow()</code>.</p>
-
-<h4 id="thread-handler">Create a Handler for posting from LicenseCheckerCallback
-to the UI thread</h4>
-
-<p>During a license check, the LVL passes the request to the Android Market
-application, which handles communication with the licensing server. The LVL
-passes the request over asynchronous IPC (using {@link android.os.Binder}) so
-the actual processing and network communication do not take place on a thread
-managed by your application. Similarly, when the Android Market application
-receives the result, it invokes a  callback method over IPC, which in turn
-executes in an IPC thread pool in your application's process.</p>
-
-<p>The LicenseChecker class manages your application's IPC communication with
-the Android Market application, including the call that sends the request and
-the callback that receives the response. LicenseChecker also tracks open license
-requests and manages their timeouts. </p>
-
-<p>So that it can handle timeouts properly and also process incoming responses
-without affecting your application's UI thread, LicenseChecker spawns a
-background thread at instantiation. In the thread it does all processing of
-license check results, whether the result is a response received from the server
-or a timeout error. At the conclusion of processing, the LVL calls your
-LicenseCheckerCallback methods from the background thread. </p>
-
-<p>To your application, this means that:</p>
-
-<ol>
-<li>Your LicenseCheckerCallback methods will be invoked, in many cases, from a
-background thread.</li>
-<li>Those methods won't be able to update state or invoke any processing in the
-UI thread, unless you create a Handler in the UI thread and have your callback
-methods post to the Handler.</li>
-</ol>
-
-<p>If you want your LicenseCheckerCallback methods to update the UI thread,
-instantiate a {@link android.os.Handler} in the main Activity's
-{@link android.app.Activity#onCreate(android.os.Bundle) onCreate()} method,
-as shown below. In this example, the LVL sample application's
-LicenseCheckerCallback methods (see above) call <code>displayResult()</code> to
-update the UI thread through the Handler's
-{@link android.os.Handler#post(java.lang.Runnable) post()} method.</p>
-
-<pre>private Handler mHandler;
-
-    &#64;Override
-    public void onCreate(Bundle savedInstanceState) {
-        ...
-        mHandler = new Handler();
-    }
-</pre>
-
-<p>Then, in your LicenseCheckerCallback methods, you can use Handler methods to
-post Runnable or Message objects to the Handler. Here's how the sample
-application included in the LVL posts a Runnable to a Handler in the UI thread
-to display the license status.</p>
-
-<pre>    private void displayResult(final String result) {
-        mHandler.post(new Runnable() {
-            public void run() {
-                mStatusText.setText(result);
-                setProgressBarIndeterminateVisibility(false);
-                mCheckLicenseButton.setEnabled(true);
-            }
-        });
-    }
-</pre>
-
-<h4 id="lc-lcc">Instantiate LicenseChecker and LicenseCheckerCallback</h4>
-
-<p>In the main Activity's
-{@link android.app.Activity#onCreate(android.os.Bundle) onCreate()} method,
-create private instances of LicenseCheckerCallback and LicenseChecker. You must
-instantiate LicenseCheckerCallback first, because you need to pass a reference
-to that instance when you call the contructor for LicenseChecker. </p>
-
-<p>When you instantiate LicenseChecker, you need to pass in these parameters:</p>
-
-<ul>
-<li>The application {@link android.content.Context}</li>
-<li>A reference to the Policy implementation to use for the license check. In
-most cases, you would use the default Policy implementation provided by the LVL,
-ServerManagedPolicy. </li>
-<li>The String variable holding your publisher account's public key for
-licensing. </li>
-</ul>
-
-<p>If you are using ServerManagedPolicy, you won't need to access the class
-directly, so you can instantiate it in the LicenseChecker constructor,
-as shown in the example below. Note that you need to pass a reference to a new
-Obfuscator instance when you construct ServerManagedPolicy.</p>
-
-<p>The example below shows the instantiation of LicenseChecker and
-LicenseCheckerCallback from the <code>onCreate()</code> method of an Activity
-class. </p>
-
-<pre>public class MainActivity extends Activity {
-    ...
-    private LicenseCheckerCallback mLicenseCheckerCallback;
-    private LicenseChecker mChecker;
-
-    &#64;Override
-    public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        ...
-        // Construct the LicenseCheckerCallback. The library calls this when done.
-        mLicenseCheckerCallback = new MyLicenseCheckerCallback();
-
-        // Construct the LicenseChecker with a Policy.
-        mChecker = new LicenseChecker(
-            this, new ServerManagedPolicy(this,
-                new AESObfuscator(SALT, getPackageName(), deviceId)),
-            BASE64_PUBLIC_KEY  // Your public licensing key.
-            );
-        ...
-    }
-}
-</pre>
-
-
-<p>Note that LicenseChecker calls the LicenseCheckerCallback methods from the UI
-thread <em>only</em> if there is valid license response cached locally. If the
-license check is sent to the server, the callbacks always originate from the
-background thread, even for network errors. </p>
-
-
-<h4 id="check-access">Call checkAccess() to initiate the license check</h4>
-
-<p>In your main Activity, add a call to the <code>checkAccess()</code> method of the
-LicenseChecker instance. In the call, pass a reference to your
-LicenseCheckerCallback instance as a parameter. If you need to handle any
-special UI effects or state management before the call, you might find it useful
-to call <code>checkAccess()</code> from a wrapper method. For example, the LVL
-sample application calls <code>checkAccess()</code> from a
-<code>doCheck()</code> wrapper method:</p>
-
-<pre>    &#64;Override
-    public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        ...
-        // Call a wrapper method that initiates the license check
-        doCheck();
-        ...
-    }
-    ...
-    private void doCheck() {
-        mCheckLicenseButton.setEnabled(false);
-        setProgressBarIndeterminateVisibility(true);
-        mStatusText.setText(R.string.checking_license);
-        mChecker.checkAccess(mLicenseCheckerCallback);
-    }
-</pre>
-
-
-<h4 id="account-key">Embed your public key for licensing</h4>
-
-<p>For each publisher account, the Android Market service automatically
-generates a  2048-bit RSA public/private key pair that is used exclusively for
-licensing. The key pair is uniquely associated with the publisher account and is
-shared across all applications that are published through the account. Although
-associated with a publisher account, the key pair is <em>not</em> the same as
-the key that you use to sign your applications (or derived from it).</p>
-
-<p>The Android Market publisher site exposes the public key for licensing to any
-developer signed in to the publisher account, but it keeps the private key
-hidden from all users in a secure location. When an application requests a
-license check for an application published in your account, the licensing server
-signs the license response using the private key of your account's key pair.
-When the LVL receives the response, it uses the public key provided by the
-application to verify the signature of the license response. </p>
-
-<p>To add licensing to an application, you must obtain your publisher account's
-public key for licensing and copy it into your application. Here's how to find
-your account's public key for licensing:</p>
-
-<ol>
-<li>Go to the Android Market <a
-href="http://market.android.com/publish">publisher site</a> and sign in.
-Make sure that you sign in to the account from which the application you are
-licensing is published (or will be published). </li>
-<li>In the account home page, locate the "Edit profile" link and click it. </li>
-<li>In the Edit Profile page, locate the "Licensing" pane, shown below. Your
-public key for licensing is given in the "Public key" text box. </li>
-</ol>
-
-<p>To add the public key to your application, simply copy/paste the key string
-from the text box into your application as the value of the String variable
-<code>BASE64_PUBLIC_KEY</code>. When you are copying, make sure that you have
-selected the entire key string, without omitting any characters. </p>
-
-<p>Here's an example from the LVL sample application:</p>
-
-<pre>    public class MainActivity extends Activity {
-        private static final String BASE64_PUBLIC_KEY = "MIIBIjANBgkqhkiG ... "; //truncated for this example
-    ...
-    }
-</pre>
-
-<h4 id="handler-cleanup">Call your LicenseChecker's onDestroy() method
-to close IPC connections</h4>
-
-<p>Finally, to let the LVL clean up before your application
-{@link android.content.Context} changes, add a call to the LicenseChecker's
-<code>onDestroy()</code> method from your Activity's
-{@link android.app.Activity#onDestroy()} implementation. The call causes the
-LicenseChecker to properly close any open IPC connection to the Android Market
-application's ILicensingService and removes any local references to the service
-and handler.</p>
-
-<p>Failing to call the LicenseChecker's <code>onDestroy()</code> method
-can lead to problems over the lifecycle of your application. For example, if the
-user changes screen orientation while a license check is active, the application
-{@link android.content.Context} is destroyed. If your application does not
-properly close the LicenseChecker's IPC connection, your application will crash
-when the response is received. Similarly, if the user exits your application
-while a license check is in progress,  your application will crash when the
-response is received, unless it has properly called the
-LicenseChecker's <code>onDestroy()</code> method to disconnect from the service.
-</p>
-
-<p>Here's an example from the sample application included in the LVL, where
-<code>mChecker</code> is the LicenseChecker instance:</p>
-
-<pre>    &#64;Override
-    protected void onDestroy() {
-        super.onDestroy();
-        mChecker.onDestroy();
-        ...
-    }
-</pre>
-
-<p>If you are extending or modifying LicenseChecker, you might also need to call
-the LicenseChecker's <code>finishCheck()</code> method, to clean up any open IPC
-connections.</p>
-
-<h3 id="impl-DeviceLimiter">Implementing a DeviceLimiter</h3>
-
-<p>In some cases, you might want your Policy to limit the number of actual
-devices that are permitted to use a single license. This would prevent a user
-from moving a licensed application onto a number of devices and using the
-application on those devices under the same account ID. It would also prevent a
-user from "sharing" the application by providing the account information
-associated with the license to other individuals, who could then sign in to that
-account on their devices and access the license to the application. </p>
-
-<p>The LVL supports per-device licensing by providing a
-<code>DeviceLimiter</code> interface, which declares a single method,
-<code>allowDeviceAccess()</code>. When a LicenseValidator is handling a response
-from the licensing server, it calls <code>allowDeviceAccess()</code>, passing a
-user ID string extracted from the response.</p>
-
-<p>If you do not want to support device limitation, <strong>no work is
-required</strong> &mdash; the LicenseChecker class automatically uses a default
-implementation called NullDeviceLimiter. As the name suggests, NullDeviceLimiter
-is a "no-op" class whose <code>allowDeviceAccess()</code> method simply returns
-a <code>LICENSED</code> response for all users and devices. </p>
-
-<div style="border-left:4px solid #FFCF00;margin:1em;padding: 0 0 0 .5em">
-<p><strong>Caution:</strong> Per-device licensing is <em>not recommended for
-most applications</em> because:</p>
-<ul>
-<li>It requires that you provide a backend server to manage a users and devices
-mapping, and </li>
-<li>It could inadvertently result in a user being denied access to an
-application that they have legitimately purchased on another device.</li>
-</ul>
-</div>
-
-
-<h2 id="test-env">Setting Up the Testing Environment</h2>
-
-<p>The Android Market publisher site provides configuration tools that let you
-and others test licensing on your application before it is published. As you are
-implementing licensing, you can make use of the publisher site tools to test
-your application's Policy and handling of different licensing responses and
-error conditions.</p>
-
-<p>The main components of the test environment for licensing include: </p>
-
-<ul>
-<li>A "Test response" configuration in your publisher account that lets you
-set the static licensing response returned, when the server processes a
-license check for an application uploaded to the publisher account, from a user
-signed in to the publisher account or a test account.</li>
-<li>An optional set of test accounts that will receive the static test
-response when they check the license of an application that you have uploaded
-(regardless whether the application is published or not).</li>
-<li>A runtime environment for the application that includes the Android Market
-application or Google APIs Add-On, on which the user is signed in to the
-publisher account or one of the test accounts.</li>
-</ul>
-
-<p>Setting up the test environment properly involves:</p>
-
-<ol>
-<li><a href="#test-response">Setting static test responses</a> that are returned by the licensing server.</li>
-<li><a href="#test-acct-setup">Setting up test accounts</a> as needed.</li>
-<li><a href="#acct-signin">Signing in</a> properly to an emulator or device, before initiating a license check test.</li>
-</ol>
-
-<p>The sections below provide more information.</p>
-
-
-<h3 id="test-response">Setting test responses for license checks</h3>
-
-<p>Android Market provides a configuration setting in your publisher account
-that lets you override the normal processing of a license check and return a
-specified static response code. The setting is for testing only and applies
-<em>only</em> to license checks for applications that you have uploaded, made by
-any user signed in to an emulator or device using the credentials of the
-publisher account or a registered test account. For other users, the server
-always processes license checks according to normal rules.  </p>
-
-<p>To set a test response for your account, sign in to your publisher account
-and click "Edit Profile". In the Edit Profile page, locate the Test Response
-menu in the Licensing panel, shown below. You can select from the full set of
-valid server response codes to control the response or condition you want to
-test in your application.</p>
-
-<p>In general, you should make sure to test your application's licensing
-implementation with every response code available in the Test Response menu.
-For a description of the codes, see <a href="#server-response-codes">Server
-Response Codes</a> in the Appendix of this document.</p>
-
-<div style="margin-bottom:2em;" id="licensing_test_response">
-
-<img src="{@docRoot}images/licensing_test_response.png" style="text-align:left;margin-bottom:0;" />
-<div style="margin:0 2em;padding:0"><strong>Figure 7.</strong> The Licensing
-panel of your account's Edit Profile page, showing the Test Accounts field and the
-Test Response menu.</div>
-</div>
-
-<p>Note that the test response that you configure applies account-wide &mdash;
-that is, it applies not to a single application, but to <em>all</em>
-applications associated with the publisher account. If you are testing multiple
-applications at once, changing the test response will affect all of those
-applications on their next license check (if the user is signed into
-the emulator or device using the publisher account or a test account).</p>
-
-<p>Before you can successfully receive a test response for a license check,
-you must sign in to the device or emulator on which the application
-is installed, and from which it is querying the server. Specifically, you must
-sign using either your publisher account or one of the test accounts that you
-have set up. For more information about test accounts, see the next section.</p>
-
-<p>See <a href="#server-response-codes">Server Response Codes</a> for a list of
-test responses available and their meanings. </p>
-
-
-<h3 id="test-acct-setup">Setting up test accounts</h3>
-
-<p>In some cases, you might want to let multiple teams of developers test
-licensing on applications that will ultimately be published through your
-publisher account, but without giving them access to your publisher account's
-sign-in credentials. To meet that need, the Android Market publisher site lets
-you set up one or more optional <em>test accounts</em> &mdash; accounts that are
-authorized to query the licensing server and receive static test responses from
-your publisher account.</p>
-
-<p>Test accounts are standard Google accounts that you register on your
-publisher account, such that they will receive the test response for
-applications that you have uploaded. Developers can then sign in to their
-devices or emulators using the test account credentials and initiate license
-checks from installed applications. When the licensing server receives a license
-check from a user of a test account, it returns the static test response
-configured for the publisher account.  </p>
-
-<p>Necessarily, there are limitations on the access and permissions given to
-users signed in through test accounts, including:</p>
-
-<ul>
-<li>Test account users can query the licensing server only for applications that
-are already uploaded to the publisher account. </li>
-<li>Test account users do not have permission to upload applications to your
-publisher account.</li>
-<li>Test account users do not have permission to set the publisher account's
-static test response.</li>
-</ul>
-
-<p>The table below summarizes the differences in capabilities, between the
-publisher account, a test account, and any other account.</p>
-
-<p class="table-caption" id="acct-types-table"><strong>Table 1.</strong>
-Differences in account types for testing licensing.</p>
-
-<table>
-<tr>
-<th>Account Type</th>
-<th>Can check license before upload?</th>
-<th>Can receive test response?</th>
-<th>Can set test response?</th>
-</tr>
-
-<tr>
-<td>Publisher account</td>
-<td>Yes</td>
-<td>Yes</td>
-<td>Yes</td>
-</tr>
-
-<tr>
-<td>Test account</td>
-<td>No</td>
-<td>Yes</td>
-<td>No</td>
-</tr>
-
-<tr>
-<td>Other</td>
-<td>No</td>
-<td>No</td>
-<td>No</td>
-</tr>
-</table>
-
-<h4 id="reg-test-acct">Registering test accounts on the publisher account</h4>
-
-<p>To get started, you need to register each test account in your publisher
-account. As shown in <a href="#licensing_test_response">Figure 7</a>, above, you
-register test accounts in the Licensing panel of your publisher account's Edit
-Profile page. Simply enter the accounts as a comma-delimited list and click
-<strong>Save</strong> to save your profile changes.</p>
-
-<p>You can use any Google account as a test account. If you want to own and
-control the test accounts, you can create the accounts yourself and distribute
-the credentials to your developers or testers.</p>
-
-<h4 id="test-app-upload">Handling application upload and distribution for test
-account users</h4>
-
-<p>As mentioned above, users of test accounts can only receive static test
-responses for applications that are uploaded to the publisher account. Since
-those users do not have permission to upload applications, as the publisher you
-will need to work with those users to collect apps for upload and distribute
-uploaded apps for testing. You can handle collection and distribution in any way
-that is convenient. </p>
-
-<p>Once an application is uploaded and becomes known to the licensing server,
-developers and testers can continue modify the application in their local
-development environment, without having to upload new versions. You only need to
-upload a new version if the local application increments the
-<code>versionCode</code> attribute in the manifest file. </p>
-
-<h4 id="test-key">Distributing your public key to test account users</h4>
-
-<p>The licensing server handles static test responses in the normal way,
-including signing the license response data, adding extras parameters, and so
-on. To support developers who are implementing licensing using test accounts,
-rather than the publisher account, you will need to distribute
-your public key to them. Developers without access to the publisher site do not
-have access to your public key, and without the key they won't be able to
-verify license responses. </p>
-
-<p>Note that if you decide to generate a new licensing key pair for your account
-for some reason, you need to notify all users of test accounts. For
-testers, you can embed the new key in the application package and distribute it
-to users. For developers, you will need to distribute the new key to them
-directly. </p>
-
-
-<h3 id="acct-signin">Signing in to an authorized account in the runtime
-environment</h3>
-
-<p>The licensing service is designed to determine whether a given user is
-licensed to use a given application &mdash; during a license check, the Android
-Market application gathers the user ID from the primary account on the system
-and sends it to the server, together with the package name of the application
-and other information. However, if there is no user information available, the
-license check cannot succeed, so the Android Market application terminates the
-request and returns an error to the application. </p>
-
-<p>During testing, to ensure that your application can successfully query the
-licensing server, you must make sure that you sign in to an account <em>on the
-device or emulator</em> using:</p>
-
-<ul>
-<li>The credentials of a publisher account, or</li>
-<li>The credentials of a test account that is registered with a publisher
-account</li>
-</ul>
-
-
-<div class="sidebox-wrapper">
-<div class="sidebox">
-<h2>Signing in to a Google account on an emulator</h2>
-
-<p>If you are testing licensing on an emulator, you need to sign in to a Google
-account on the emulator. If you do not see an option to create a new Google
-account, the problem might be that your AVD is running a standard Android system
-image, rather than the Google APIs Add-On, API 8 (release 2) or higher. </p>
-
-<p style="margin-top:.5em;">For more information, see <a
-href="#runtime-setup">Setting up the runtime environment</a>, above.</p>
-
-</div>
-</div>
-
-<p>Signing in using a publisher account offers the advantage of letting your
-applications receive static test responses even before the applications are
-uploaded to the publisher site.</p>
-
-<p>If you are part of a larger organization or are working with external groups
-on applications that will be published through your site, you will more likely
-want to distribute test accounts instead, then use those to sign in during
-testing. </p>
-
-<p>To sign in on a device or emulator, follow the steps below. The preferred
-approach is to sign in as the primary account &mdash; however, if there are
-other accounts already in use on the device or emulator, you can create an
-additional account and sign in to it using the publisher or test account
-credentials.  </p>
-
-<ol>
-<li>Open Settings &gt; Accounts &amp; sync</li>
-<li>Select <strong>Add Account</strong> and choose to add a "Google" account.
-</li>
-<li>Select <strong>Next</strong> and then <strong>Sign in</strong>.</li>
-<li>Enter the username and password of either the publisher account or a test
-account that is registered in the publisher account.</li>
-<li>Select <strong>Sign in</strong>. The system signs you in to the new
-account.</li>
-</ol>
-
-<p>Once you are signed in, you can begin testing licensing in your application
-(if you have completed the LVL integration steps above). When your application
-initiates a license check, it will receive a response containing the static test
-response configured on the publisher account. </p>
-
-<p>Note that, if you are using an emulator, you will need to sign in to the
-publisher account or test account each time you wipe data when restarting the
-emulator.</p>
-
-<div style="margin:2em 1em 1em 1em;">
-
-<img src="{@docRoot}images/licensing_device_signin.png" style="text-align:left;" />
-<div style="margin:.25em 1.25em;padding:0"><strong>Figure 8.</strong> Example of
-setting up a Google account on a device or emulator.</div>
-</div>
-
-<h2 id="app-obfuscation">Obfuscating Your Application</h2>
-
-<p>To ensure the security of your application, particularly for a paid
-application that uses licensing and/or custom constraints and protections, it's
-very important to obfuscate your application code. Properly obfuscating your
-code makes it more difficult for a malicious user to decompile the application's
-bytecode, modify it &mdash; such as by removing the license check &mdash;
-and then recompile it.</p>
-
-<p>Several obfuscator programs are available for Android applications, including
-<a href="http://proguard.sourceforge.net/">ProGuard</a>, which also offers
-code-optimization features. The use of ProGuard or a similar program to obfuscate
-your code is <em>strongly recommended</em> for all applications that use Android
-Market Licensing. </p>
-
-<h2 id="app-publishing">Publishing a Licensed Application</h2>
-
-<p>When you are finished testing your license implementation, you are ready to
-publish the application on Android Market. Follow the normal steps to <a
-href="{@docRoot}guide/publishing/preparing.html">prepare</a>, <a
-href="{@docRoot}guide/publishing/app-signing.html">sign</a>, and then <a
-href="{@docRoot}guide/publishing/publishing.html">publish the application</a>.
-</p>
-
-<h4>Removing Copy Protection</h4>
-
-<p>After uploading your licensed application, remember to remove copy protection
-from the application, if it is currently used. To check and remove copy
-protection, sign in to the publisher site and go the application's upload
-details page. In the Publishing options section, make sure that the Copy
-Protection radio button selection is "Off".</p>
-
-<h4>Considerations for Free Apps</h4>
-
-<p>Licensing is currently supported only for paid applications. If you already
-published your application as free, you won't be able to upload an updated
-version that includes licensing (that is, an application that uses the same
-package name and that includes the <a href="#manifest-permission">licensing
-permission</a>). Here are some points to keep in mind:</p>
-
-<ul>
-<li>If you want to offer a free version of your application that provides a
-reduced feature set (or that offers the full feature set for trial period), the
-free version of your application must not include the licensing permission and
-must use a different package name than the paid version of the app.</li>
-<li>If you want to offer a paid version of your free application that uses
-licensing, you can do so under a new package name.</li>
-</ul>
-
-<h2 id="support">Where to Get Support</h2>
-
-<p>If you have questions or encounter problems while implementing or deploying
-publishing in your applications, please use the support resources listed in the
-table below. By directing your queries to the correct forum, you can get the
-support you need more quickly. </p>
-
-<p class="table-caption"><strong>Table 2.</strong> Developer support resources
-for Android Market Licensing Service.</p>
-
-<table>
-
-<tr>
-<th>Support Type</th>
-<th>Resource</th>
-<th>Range of Topics</th>
-</tr>
-<tr>
-<td rowspan="2">Development and testing issues</td>
-<td>Google Groups: <a
-href="http://groups.google.com/group/android-developers">android-developers</a>
-</td>
-<td rowspan="2">LVL download and integration, library projects, Policy
-questions, user experience ideas, handling of responses, Obfuscator, IPC, test
-environment setup</td>
-</tr>
-<tr>
-<td>Stack Overflow: <a
-href="http://stackoverflow.com/questions/tagged/android">http://stackoverflow.com/questions/tagged/android</a></td>
-</tr>
-<tr>
-<td rowspan="2">Accounts, publishing, and deployment issues</td>
-<td><a href="http://www.google.com/support/forum/p/Android+Market">Android
-Market Help Forum</a></td>
-<td rowspan="2">Publisher accounts, licensing key pair, test accounts, server
-responses, test responses, application deployment and results</td>
-</tr>
-<tr>
-<td><a
-href="http://market.android.com/support/bin/answer.py?answer=186113">Market
-Licensing Support FAQ</a></td>
-</tr>
-<tr>
-<td>LVL issue tracker</td>
-<td><a href="http://code.google.com/p/marketlicensing/issues/">Marketlicensing
-project issue tracker</a></td>
-<td>Bug and issue reports related specifically to the LVL source code classes
-and interface implementations</td>
-</tr>
-
-</table>
-
-<p>For general information about how to post to the groups listed above, see <a
-href="{@docRoot}resources/community-groups.html">Developer Forums</a> document
-in the Resources tab.</p>
-
-<h2 id="lvl-summary">Summary of LVL Classes and Interfaces</h2>
-
-<p>The table below lists all of the source files in the License Verification
-Library (LVL) available through the Android SDK. All of the files are part of
-the <code>com.android.vending.licensing</code> package.</p>
-
-<p class="table-caption"><strong>Table A-1.</strong> Summary of LVL library
-classes and interfaces.</p>
-
-<div style="width:99%">
-<table width="100%">
-
-<tr>
-<th width="15%">Category</th>
-<th width="20%">Name</th>
-<th width="100%">Description</th>
-</tr>
-
-<tr>
-<td rowspan="2">License check and result</td>
-<td>LicenseChecker</td>
-<td>Class that you instantiate (or subclass) to initiate a license check.</td>
-</tr>
-<tr>
-<td><em>LicenseCheckerCallback</em></td>
-<td>Interface that you implement to handle result of the license check.</td>
-</tr>
-
-<tr>
-<td rowspan="3" width="15%">Policy</td>
-<td width="20%"><em>Policy</em></td>
-<td width="100%">Interface that you implement to determine whether to allow
-access to the application, based on the license response. </td>
-</tr>
-<tr>
-<td>ServerManagedPolicy</td>
-<td width="100%">Default Policy implementation. Uses settings provided by the
-licensing server to manage local storage of license data, license validity,
-retry.</td>
-</tr>
-<tr>
-<td>StrictPolicy</td>
-<td>Alternative Policy implementation. Enforces licensing based on a direct
-license response from the server only. No caching or request retry.</td>
-</tr>
-
-<tr>
-<td rowspan="2" width="15%">Data obfuscation <br><em>(optional)</em></td>
-<td width="20%"><em>Obfuscator</em></td>
-<td width="100%">Interface that you implement if you are using a Policy (such as
-ServerManagedPolicy) that caches license response data in a persistent store.
-Applies an obfuscation algorithm to encode and decode data being written or
-read.</td>
-</tr>
-<tr>
-<td>AESObfuscator</td>
-<td>Default Obfuscator implementation that uses AES encryption/decryption
-algorithm to obfuscate/unobfuscate data.</td>
-</tr>
-
-<tr>
-<td rowspan="2" width="15%">Device limitation<br><em>(optional)</em></td>
-<td width="20%"><em>DeviceLimiter</em></td>
-<td width="100%">Interface that you implement if you want to restrict use of an
-application to a specific device. Called from LicenseValidator. Implementing
-DeviceLimiter is not recommended for most applications because it requires a
-backend server and may cause the user to lose access to licensed applications,
-unless designed with care.</td>
-</tr>
-<tr>
-<td>NullDeviceLimiter</td>
-<td>Default DeviceLimiter implementation that is a no-op (allows access to all
-devices).</td>
-</tr>
-
-<tr>
-<td rowspan="6" width="15%">Library core, no integration needed</td>
-<td width="20%">ResponseData</td>
-<td width="100%">Class that holds the fields of a license response.</td>
-</tr>
-<tr>
-<td>LicenseValidator</td>
-<td>Class that decrypts and verifies a response received from the licensing
-server.</td>
-</tr>
-<tr>
-<td>ValidationException</td>
-<td>Class that indicates errors that occur when validating the integrity of data
-managed by an Obfuscator.</td>
-</tr>
-<tr>
-<td>PreferenceObfuscator</td>
-<td>Utility class that writes/reads obfuscated data to the system's
-{@link android.content.SharedPreferences} store.</td>
-</tr>
-<tr>
-<td><em>ILicensingService</em></td>
-<td>One-way IPC interface over which a license check request is passed to the
-Android Market client.</td>
-</tr>
-<tr>
-<td><em>ILicenseResultListener</em></td>
-<td>One-way IPC callback implementation over which the application receives an
-asynchronous response from the licensing server.</td>
-</tr>
-
-</table>
-</div>
-
-
-<h2 id="server-response-codes">Server Response Codes</h2>
-
-<p>The table below lists all of the license response codes supported by the
-licensing server. In general, an application should handle all of these response
-codes. By default, the LicenseValidator class in the LVL provides all of the
-necessary handling of these response codes for you. </p>
-
-<p class="table-caption"><strong>Table A-2.</strong> Summary of response codes
-returned by the Android Market server in a license response.</p>
-
-<table>
-
-<tr>
-<th>Response Code</th>
-<th>Description</th>
-<th>Signed?</th>
-<th>Extras</th>
-<th>Comments</th>
-</tr>
-<tr>
-<td>LICENSED</td>
-<td>The application is licensed to the user. The user has purchased the
-application or the application only exists as a draft.</td>
-<td>Yes</td>
-<td><code>VT</code>,&nbsp;<code>GT</code>, <code>GR</code></td>
-<td><em>Allow access according to Policy constraints.</em></td>
-</tr>
-<tr>
-<td>LICENSED_OLD_KEY</td>
-<td>The application is licensed to the user, but there is an updated application
-version available that is signed with a different key. </td>
-<td>Yes </td>
-<td><code>VT</code>, <code>GT</code>, <code>GR</code>, <code>UT</code></td>
-<td><em>Optionally allow access according to Policy constraints.</em>
-<p style="margin-top:.5em;">Can indicate that the key pair used by the installed
-application version is invalid or compromised. The application can allow access
-if needed or inform the user that an upgrade is available and limit further use
-until upgrade.</p>
-</td>
-</tr>
-<tr>
-<td>NOT_LICENSED</td>
-<td>The application is not licensed to the user.</td>
-<td>No</td>
-<td></td>
-<td><em>Do not allow access.</em></td>
-</tr>
-<tr>
-<td>ERROR_CONTACTING_SERVER</td>
-<td>Local error &mdash; the Android Market application was not able to reach the
-licensing server, possibly because of network availability problems. </td>
-<td>No</td>
-<td></td>
-<td><em>Retry the license check according to Policy retry limits.</em></td>
-</tr>
-<tr>
-<td>ERROR_SERVER_FAILURE</td>
-<td>Server error &mdash; the server could not load the publisher account's key
-pair for licensing.</td>
-<td>No</td>
-<td></td>
-<td><em>Retry the license check according to Policy retry limits.</em>
-</td>
-</tr>
-<tr>
-<td>ERROR_INVALID_PACKAGE_NAME</td>
-<td>Local error &mdash; the application requested a license check for a package
-that is not installed on the device. </td>
-<td>No </td>
-<td></td>
-<td><em>Do not retry the license check.</em>
-<p style="margin-top:.5em;">Typically caused by a development error.</p>
-</td>
-</tr>
-<tr>
-<td>ERROR_NON_MATCHING_UID</td>
-<td>Local error &mdash; the application requested a license check for a package
-whose UID (package, user ID pair) does not match that of the requesting
-application. </td>
-<td>No </td>
-<td></td>
-<td><em>Do not retry the license check.</em>
-<p style="margin-top:.5em;">Typically caused by a development error.</p>
-</td>
-</tr>
-<tr>
-<td>ERROR_NOT_MARKET_MANAGED</td>
-<td>Server error &mdash; the application (package name) was not recognized by
-Android Market. </td>
-<td>No</td>
-<td></td>
-<td><em>Do not retry the license check.</em>
-<p style="margin-top:.5em;">Can indicate that the application was not published
-through Android Market or that there is an development error in the licensing
-implementation.</p>
-</td>
-</tr>
-
-</table>
-
-<p class="note"><strong>Note:</strong> As documented in <a href="#test-env">
-Setting Up The Testing Environment</a>, the response code can be manually
-overridden for the application developer and any registered test users via the
-Android Market publisher site.
-<br/><br/>
-Additionally, as noted above, applications that are in draft mode (in other
-words, applicaitons that have been uploaded but have <em>never</em> been
-published) will return LICENSED for all users, even if not listed as a test
-user. Since the application has never been offered for download, it is assumed
-that any users running it must have obtained it from an authorized channel for
-testing purposes.</p>
-
-<h2 id="extras">Server Response Extras</h2>
-
-<p>The licensing server includes several settings in certain types of license
-responses, to assist the application and its Policy in managing access to the
-application across the 24-hour refund period and other conditions. Specifically,
-the server provides recommended values for the application's license validity
-period, retry grace period, maximum allowable retry count, and other settings.
-The server appends the settings as key-value pairs in the license response
-"extras" field. </p>
-
-<p>Any Policy implementation can extract the extras settings from the license
-response and use them as needed. The LVL default Policy implementation, <a
-href="#ServerManagedPolicy">ServerManagedPolicy</a>, serves as a working
-implementation and an illustration of how to obtain, store, and use the
-settings. </p>
-
-<p class="table-caption"><strong>Table A-3.</strong> Summary of
-license-management settings supplied by the Android Market server in a license
-response.</p>
-
-<table>
-<tr>
-<th>Extra</th><th>Description</th>
-</tr>
-
-<tr>
-  <td>VT</td>
-  <td>License validity timestamp. Specifies the date/time at which the current
-(cached) license response expires and must be rechecked on the licensing server.
- </td>
-</tr>
-<tr>
-  <td>GT</td>
-  <td>Grace period timestamp. Specifies the end of the period during which a
-Policy may allow access to the application, even though the response status is
-RETRY. <p>The value is managed by the server, however a typical value would be 5
-or more days.</p></td>
-</tr>
-<tr>
-  <td>GR</td>
-  <td>Maximum retries count. Specifies how many consecutive RETRY license checks
-the Policy should allow, before denying the user access to the application.
-<p>The value is managed by the server, however a typical value would be "10" or
-higher.</p></td>
-</tr>
-<tr>
-  <td>UT</td>
-  <td>Update timestamp. Specifies the day/time when the most recent update to
-this application was uploaded and published. <p>The server returns this extra
-only for LICENSED_OLD_KEYS responses, to allow the Policy to determine how much
-time has elapsed since an update was published with new licensing keys before
-denying the user access to the application. </p></td>
-</tr>
-
-</table>
-
-<p>The sections below provide more information about the server-provided
-settings and how to use them. </p>
-
-<h4>License validity period</h4>
-
-<p>The Android Market licensing server sets a license validity period for all
-downloaded applications. The period expresses the interval of time over which an
-application's license status should be considered as unchanging and cacheable by
-a licensing Policy in the application. The licensing server includes the
-validity period in its response to all license checks, appending an
-end-of-validity timestamp to the response as an extra under the key "VT". A
-Policy can extract the VT key value and use it to conditionally allow access to
-the application without rechecking the license, until the validity period
-expires. </p>
-
-<p>The license validity signals to a licensing Policy when it must recheck the
-licensing status with the licensing server. It is <em>not</em> intended to imply
-whether an application is actually licensed for use. That is, when an
-application's license validity period expires, this does not mean that the
-application is no longer licensed for use &mdash; rather, it indicates only that
-the Policy must recheck the licensing status with the server. It follows that,
-as long as the license validity period is not expired, it is acceptable for the
-Policy to cache the initial license status locally and return the cached license
-status instead of sending a new license check to the server.</p>
-
-<p>The licensing server manages the validity period as a means of helping the
-application properly enforce licensing across the refund period offered by
-Android Market for paid applications. It sets the validity period based on
-whether the application was purchased and, if so, how long ago. Specifically,
-the server sets a validity period as follows:</p>
-
-<ul>
-<li>For a paid application, the server sets the initial license validity period
-so that the license response remains valid for as long as the application is
-refundable. A licensing Policy in the application may cache the
-result of the initial license check and does not need to recheck the license
-until the validity period has expired.</li>
-<li>When an application is no longer refundable, the server
-sets a longer validity period &mdash; typically a number of days. </li>
-<li>For a free application, the server sets the validity period to a very high
-value (<code>long.MAX_VALUE</code>). This ensures that, provided the Policy has
-cached the validity timestamp locally, it will not need to recheck the
-license status of the application in the future.</li>
-</ul>
-
-<p>The ServerManagedPolicy implementation uses the extracted timestamp
-(<code>mValidityTimestamp</code>) as a primary condition for determining whether
-to recheck the license status with the server before allowing the user access to
-the application. </p>
-
-<h4>Retry period and maximum retry count</h4>
-
-<p>In some cases, system or network conditions can prevent an application's
-license check from reaching the licensing server, or prevent the server's
-response from reaching the Android Market client application. For example, the
-user might launch an application when there is no cell network or data
-connection available &mdash; such as when on an airplane &mdash; or when the
-network connection is unstable or the cell signal is weak. </p>
-
-<p>When network problems prevent or interrupt a license check, the Android
-Market client notifies the application by returning a "RETRY" response code to
-the Policy's <code>processServerResponse()</code> method. In the case of system
-problems, such as when the application is unable to bind with Android Market's
-ILicensingService implementation, the LicenseChecker library itself calls the
-Policy <code>processServerResonse()</code> method with a "RETRY" response code.
-</p>
-
-<p>In general, the RETRY response code is a signal to the application that an
-error has occurred that has prevented a license check from completing.
-
-<p>The Android Market server helps an application to manage licensing under
-error conditions by setting a retry "grace period" and a recommended maximum
-retries count. The server includes these values in all license check responses,
-appending them as extras under the keys "GT" and "GR". </p>
-
-<p>The application Policy can extract the GT and GR extras and use them to
-conditionally allow access to the application, as follows:</p>
-
-<ul>
-<li>For a license check that results in a RETRY response, the Policy should
-cache the RETRY response code and increment a count of RETRY responses.</li>
-<li>The Policy should allow the user to access the application, provided that
-either the retry grace period is still active or the maximum retries count has
-not been reached.</li>
-</ul>
-
-<p>The ServerManagedPolicy uses the server-supplied GT and GR values as
-described above. The example below shows the conditional handling of the retry
-responses in the <code>allow()</code> method. The count of RETRY responses is
-maintained in the <code>processServerResponse()</code> method, not shown. </p>
-
-
-<pre>    public boolean allowAccess() {
-        long ts = System.currentTimeMillis();
-        if (mLastResponse == LicenseResponse.LICENSED) {
-            // Check if the LICENSED response occurred within the validity timeout.
-            if (ts &lt;= mValidityTimestamp) {
-                // Cached LICENSED response is still valid.
-                return true;
-            }
-        } else if (mLastResponse == LicenseResponse.RETRY &amp;&amp;
-                   ts &lt; mLastResponseTime + MILLIS_PER_MINUTE) {
-            // Only allow access if we are within the retry period or we haven't used up our
-            // max retries.
-            return (ts &lt;= mRetryUntil || mRetryCount &lt;= mMaxRetries);
-        }
-        return false;
-    }</pre>
-
diff --git a/docs/html/guide/publishing/preparing.jd b/docs/html/guide/publishing/preparing.jd
index 83aa5ee..fe56352 100644
--- a/docs/html/guide/publishing/preparing.jd
+++ b/docs/html/guide/publishing/preparing.jd
@@ -22,7 +22,7 @@
     <ol>
       <li><a href="{@docRoot}guide/publishing/publishing_overview.html">Publishing Overview</a></li>
       <li><a href="{@docRoot}guide/publishing/app-signing.html">Signing Your Applications</a></li>
-      <li><a href="{@docRoot}guide/publishing/publishing.html">Publishing on Android Market</a></li>
+      <li><a href="{@docRoot}guide/publishing/publishing.html">Publishing on Google Play</a></li>
     </ol>
   </div>
 </div>
@@ -39,13 +39,13 @@
 tasks serve as a final check, ensuring that your application performs as expected under real-world
 conditions. When you are finished preparing your application for release you have a signed
 <code>.apk</code> file, which you can distribute directly to users or distribute through an
-application marketplace such as Android Market.</p>
+application marketplace such as Google Play.</p>
 
 <p>This document summarizes the main tasks you need to perform to prepare your application for
 release. The tasks that are described in this document apply to all Android applications regardless
-how they are released or distributed to users. If you are releasing your application through Android
-Market, you should also read <a href="{@docRoot}guide/publishing/publishing.html">Publishing on
-Android Market</a> to be sure your release-ready application satisfies all Android Market
+how they are released or distributed to users. If you are releasing your application through Google
+Play, you should also read <a href="{@docRoot}guide/publishing/publishing.html">Publishing on
+Google Play</a> to be sure your release-ready application satisfies all Google Play
 requirements.</p>
 
 <p class="note"><strong>Note:</strong> As a best practice, your application should meet all of your
@@ -89,9 +89,9 @@
 
 <p>To prepare your application for release you typically perform five main tasks (see figure 2).
 Each main task may include one or more smaller tasks depending on how you are releasing your
-application. For example, if you are releasing your application through Android Market you may want
+application. For example, if you are releasing your application through Google Play you may want
 to add special filtering rules to your manifest while you are configuring your application for
-release. Similarly, to meet Android Market publishing guidelines you may have to prepare screenshots
+release. Similarly, to meet Google Play publishing guidelines you may have to prepare screenshots
 and create promotional text while you are gathering materials for release.</p>
 
 <p>You usually perform the tasks listed in figure 2 after you have throroughly debugged and tested
@@ -137,9 +137,9 @@
 href="{@docRoot}guide/practices/ui_guidelines/icon_design_launcher.html">icon guidelines</a>. Your
 application's icon helps users identify your application on a device's Home
 screen and in the Launcher window. It also appears in Manage Applications, My Downloads, and
-elsewhere. In addition, publishing services such as Android Market display your icon to users.</p>
+elsewhere. In addition, publishing services such as Google Play display your icon to users.</p>
 
-<p class="note"><strong>Note:</strong> If you are releasing your application on Android Market, you
+<p class="note"><strong>Note:</strong> If you are releasing your application on Google Play, you
 need to create a high resolution
   version of your icon. See <a
 href="https://www.google.com/support/androidmarket/developer/bin/answer.py?answer=1078870">Graphic
@@ -154,7 +154,7 @@
 <h4>Miscellaneous Materials</h4>
 
 <p>You might also have to prepare promotional and marketing materials to publicize your application.
-For example, if you are releasing your application on Android Market you will need to prepare some
+For example, if you are releasing your application on Google Play you will need to prepare some
 promotional text and you will need to create screenshots of your application. For more
 information, see
 <a href="https://www.google.com/support/androidmarket/developer/bin/answer.py?answer=1078870">
@@ -242,11 +242,11 @@
 </ul>
 
 <p>There are several additional manifest elements that you can set if you are releasing your
-application on Android Market. For example, the <code>android:minSdkVersion</code> and
+application on Google Play. For example, the <code>android:minSdkVersion</code> and
 <code>android:targetSdkVersion</code> attributes, which are located in the <a
 href="{@docRoot}guide/topics/manifest/uses-sdk-element.html"> &lt;uses-sdk&gt;</a> element. For more
-information about these and other Android Market settings, see <a
-href="{@docRoot}/guide//appendix/market-filters.html">Market Filters</a>.</p>
+information about these and other Google Play settings, see <a
+href="{@docRoot}/guide//appendix/market-filters.html">Filters on Google Play</a>.</p>
 
 <h4>Address compatibility issues</h4>
 
@@ -283,15 +283,15 @@
 <p>If your application accesses remote servers or services, make sure you are using the production
 URL or path for the server or service and not a test URL or path.</p>
 
-<h4>Implement Licensing (if you are releasing on Android Market)</h4>
+<h4>Implement Licensing (if you are releasing on Google Play)</h4>
 
-<p>If you are releasing a paid application through Android Market, consider adding support for
-Android Market Licensing. Licensing lets you control access to your application based on whether the
-current user has purchased it. Using Android Market Licensing is optional even if you are
-releasing your app through Android Market.</p>
+<p>If you are releasing a paid application through Google Play, consider adding support for
+Google Play Licensing. Licensing lets you control access to your application based on whether the
+current user has purchased it. Using Google Play Licensing is optional even if you are
+releasing your app through Google Play.</p>
 
-<p>For more information about Android Market Licensing Service and how to use it in your
-application, see <a href="{@docRoot}guide/publishing/licensing.html">Application Licensing</a>.</p>
+<p>For more information about Google Play Licensing Service and how to use it in your
+application, see <a href="{@docRoot}guide/market/licensing.html">Application Licensing</a>.</p>
 
 <h2 id="publishing-build">Building Your Application for Release</h2>
 
@@ -352,7 +352,7 @@
 done testing and you are satisfied that the release version of your application
 behaves correctly, you can release your application to users. For more information, see
 <a href="{@docRoot}guide/publishing/publishing_overview.html#publishing-release">Releasing Your
-Application to Users</a>. If you are publishing your application on Android Market, see
-<a href="{@docRoot}guide/publishing/publishing.html">Publishing on Android Market</a>.</p>
+Application to Users</a>. If you are publishing your application on Google Play, see
+<a href="{@docRoot}guide/publishing/publishing.html">Publishing on Google Play</a>.</p>
 
 
diff --git a/docs/html/guide/publishing/publishing.jd b/docs/html/guide/publishing/publishing.jd
index 49b34d8..b9513ab 100644
--- a/docs/html/guide/publishing/publishing.jd
+++ b/docs/html/guide/publishing/publishing.jd
@@ -1,4 +1,4 @@
-page.title=Publishing on Android Market
+page.title=Publishing on Google Play
 @jd:body
 
 <div id="qv-wrapper">
@@ -7,25 +7,25 @@
 <h2>Quickview</h2>
 
 <ul>
-<li>Learn how to publish and update apps on Android Market.</li>
-<li>Find out how to create links to apps that are published on Android Market.</li>
-<li>Learn about Android Market features.</li>
+<li>Learn how to publish and update apps on Google Play.</li>
+<li>Find out how to create links to apps that are published on Google Play.</li>
+<li>Learn about Google Play features.</li>
 </ul>
 
 
 <h2>In this document</h2>
 
 <ol>
-<li><a href="#overview">About Android Market</a>
-<li><A href="#marketpublish">Publishing Apps on Android Market</a></li>
-<li><a href="#marketupgrade">Publishing Updates on Android Market</a></li>
-<li><a href="#marketLicensing">Using Android Market Licensing Service</a></li>
-<li><a href="#marketinappbilling">Using Android Market In-app Billing</a></li>
-<li><a href="#marketintent">Linking to Your Apps on Android Market</a>
+<li><a href="#overview">About Google Play</a>
+<li><A href="#marketpublish">Publishing Apps on Google Play</a></li>
+<li><a href="#marketupgrade">Publishing Updates on Google Play</a></li>
+<li><a href="#marketLicensing">Using Google Play Licensing Service</a></li>
+<li><a href="#marketinappbilling">Using Google Play In-app Billing</a></li>
+<li><a href="#marketintent">Linking to Your Apps on Google Play</a>
   <ol>
     <li><a href="#OpeningDetails">Opening an app's details page</a></li>
     <li><a href="#PerformingSearch">Performing a search</a></li>
-    <li><a href="#BuildaButton">Build an Android Market button</a></li>
+    <li><a href="#BuildaButton">Build a Google Play button</a></li>
     <li><a href="#UriSummary">Summary of URI formats</a></li>
   </ol>
 </li>
@@ -41,9 +41,9 @@
 <div id="qv-extra">
   <img id="rule" src="{@docRoot}assets/images/grad-rule-qv.png">
   <div id="qv-sub-rule">
-    <img src="{@docRoot}assets/images/icon_market.jpg" style="float:left;margin:0;padding:0 5px;">
-    <h2 style="color:#669999;">Already know about Android Market and want to get started?</h2>
-    <p>Go to <a href="http://market.android.com/publish">Android Market</a>, create a developer
+    <img src="{@docRoot}assets/images/icon_play.png" style="float:left;margin:0;padding:0 5px;">
+    <h2 style="color:#669999;">Already know about Google Play and want to get started?</h2>
+    <p>Go to <a href="http://play.google.com/apps/publish">Google Play</a>, create a developer
 account, and upload your application. For more information about required assets, listing details,
 and publishing options, see <a
 href="http://market.android.com/support/bin/answer.py?answer=113469">Upload
@@ -55,78 +55,78 @@
 </div>
 
 <p>One of the most effective ways to get your application into users' hands is to
-publish it on an application marketplace like Android Market. Publishing on Android Market is a
+publish it on an application marketplace like Google Play. Publishing on Google Play is a
 straightforward process that you can do in just a few simple steps&mdash;register, configure,
 upload, and publish. Registration takes only a few minutes and needs to be done only once.
-The configuration and publishing steps can all be done through the Android Market Developer Console
-after you register as an Android Market developer.</p>
+The configuration and publishing steps can all be done through the Google Play Android Developer Console
+after you register as a Google Play developer.</p>
 
-<p>To start publishing on Android Market, first read this topic and then go to the <a
-href="https://market.android.com/publish/signup">Android Market publisher site</a> and register as
-an Android Market developer.</p>
+<p>To start publishing on Google Play, first read this topic and then go to the <a
+href="https://play.google.com/apps/publish">Google Play Android Developer Console</a> and register as
+a Google Play developer.</p>
 
 
-<h2 id="overview">About Android Market</h2>
+<h2 id="overview">About Google Play</h2>
 
-<p>Android Market is a robust publishing platform that helps you publicize, sell, and distribute
+<p>Google Play is a robust publishing platform that helps you publicize, sell, and distribute
 your Android applications to users around the world. When you release your applications through
-Android Market you have access to a suite of developer tools that let you analyze your sales,
+Google Play you have access to a suite of developer tools that let you analyze your sales,
 identify market trends, and control who your applications are being distributed to. You also have
 access to several revenue-enhancing features, such as <a
 href="{@docRoot}guide/market/billing/index.html">in-app billing</a> and
-<a href="{@docRoot}guide/publishing/licensing.html">application licensing</a>.</p>
+<a href="{@docRoot}guide/market/licensing/index.html">application licensing</a>.</p>
 
-<p>Before you can publish applications on Android Market, you need to <a
-href="http://market.android.com/publish">register</a> as an Android Market developer. During the
+<p>Before you can publish applications on Google Play, you need to <a
+href="http://play.google.com/apps/publish">register</a> as a Google Play developer. During the
 registration process you will need to create a developer profile, pay a registration fee, and agree
-to the <a href="http://www.android.com/us/developer-distribution-agreement.html">Android Market
-Developer Distribution Agreement</a>. After you register you can access the Android Market Developer
+to the <a href="http://www.android.com/us/developer-distribution-agreement.html">Google Play
+Developer Distribution Agreement</a>. After you register you can access the Developer
 Console, where you can upload applications, configure publishing options, and monitor publishing
 data. If you want to sell your applications or use the in-app billing feature, you will also need
 to set up a Google Checkout merchant account. For more information about the registration process,
 see <a href="https://support.google.com/androidmarket/developer/bin/answer.py?hl=en&answer=113468">
 Developer Registration</a>.</p>
 
-<h2 id="marketpublish">Publishing Apps on Android Market</h2>
+<h2 id="marketpublish">Publishing Apps on Google Play</h2>
 
-<p>Publishing your application on Android Market is a simple process that involves three basic
+<p>Publishing your application on Google Play is a simple process that involves three basic
 tasks (see figure 1):</p>
 
 <ul>
   <li>Creating various graphical assets that
-accompany your app on Android Market.</li>
-  <li>Using the Android Market <a
-href="http://market.android.com/publish">Developer Console</a> to configure publishing options,
-specify listing details, and upload your app and graphical assets to Android Market.</li>
+accompany your app on Google Play.</li>
+  <li>Using the Google Play <a
+href="http://play.google.com/apps/publish">Developer Console</a> to configure publishing options,
+specify listing details, and upload your app and graphical assets to Google Play.</li>
   <li>Reviewing your publishing settings and changing the release
 status of your app from Unpublished to Published.</li>
 </ul>
 
 <img src="{@docRoot}images/publishing/publishing_android_market.png"
-     alt="Shows the three steps that are required to publish on Android Market"
+     alt="Shows the three steps that are required to publish on Google Play"
      height="168"
      id="figure1" />
 <p class="img-caption">
-  <strong>Figure 1.</strong> To publish apps on Android Market you must first <a
+  <strong>Figure 1.</strong> To publish apps on Google Play you must first <a
 href="{@docRoot}guide/publishing/preparing.html">prepare your app for release</a> and then perform
 three simple tasks.
 </p>
 
 <p class="caution"><strong>Important:</strong> You must <a
 href="{@docRoot}guide/publishing/preparing.html">prepare your application for release</a> before you
-can publish it on Android Market. When you prepare your application for release you configure it for
+can publish it on Google Play. When you prepare your application for release you configure it for
 release and build it in release mode. Building in release mode signs your application's {@code .apk}
-file with your private release key. You cannot publish an application on Android Market unless it is
+file with your private release key. You cannot publish an application on Google Play unless it is
 signed with your own private release key.</p>
 
 <h3>Preparing promotional materials</h3>
 
-<p>To fully leverage the marketing and publicity capabilities of Android Market, you need to create
-several graphical assets that accompany your app on Android Market, such as screenshots, videos,
+<p>To fully leverage the marketing and publicity capabilities of Google Play, you need to create
+several graphical assets that accompany your app on Google Play, such as screenshots, videos,
 promotional graphics, and promotional text. At a minimum you must provide two screenshots of your
 application and a high resolution application icon. The screenshots are displayed on the details
-page for your application in Android Market, and the high resolution application icon is displayed
-in various locations throughout Android Market. The high resolution icon does not replace the
+page for your application on Google Play, and the high resolution application icon is displayed
+in various locations throughout Google Play. The high resolution icon does not replace the
 launcher icon for your application, rather, it serves as a supplemental icon and should look
 the same as your launcher icon. Promotional video,
 graphics, and text are optional, although we strongly recommended that you prepare these for your
@@ -136,8 +136,8 @@
 
 <h3>Configuring options and uploading assets</h3>
 
-<p>Android Market lets you target your application to a worldwide pool of users and devices. To
-reach these users you can use the Android Market Developer Console to configure various publishing
+<p>Google Play lets you target your application to a worldwide pool of users and devices. To
+reach these users you can use the Developer Console to configure various publishing
 options and listing details for your app. For example, you can choose the <a
 href="http://support.google.com/androidmarket/developer/bin/answer.py?hl=en&answer=138294&topic=
 2365624&ctx=topic">countries</a> you want to reach, the listing languages you want to use, and the
@@ -155,11 +155,11 @@
 app.</p>
 
 <p>When you are finished setting publishing options and listing details, you can upload your assets
-and your application to Android Market. You can also upload your application as a draft
+and your application to Google Play. You can also upload your application as a draft
 (unpublished) application, which lets you do final testing before you publish it for final
 release.</p>
 
-<p>To learn more about Android Market publishing settings, see the following resources:</p>
+<p>To learn more about Google Play publishing settings, see the following resources:</p>
 
 <ul>
   <li><a
@@ -181,20 +181,20 @@
 <p>When you are satisfied that your publishing settings are correctly configured and your uploaded
 application is ready to be released to the public, you can simply click <strong>Publish</strong> in
 the Developer Console to make your app available for download
-around the world. Keep in mind, it can take several hours for your app to appear on Android
-Market after you click <strong>Publish</strong> in the Developer Console.</p>
+around the world. Keep in mind, it can take several hours for your app to appear on Google
+Play after you click <strong>Publish</strong> in the Developer Console.</p>
 
 <h3>Controlling Distribution to Devices</h3>
 
 <p>If your application targets different device configurations, you can control which Android-powered
-devices have access to your application on Android Market by
-using Android Market filters. Filtering compares device configurations that you declare in your
+devices have access to your application on Google Play by
+using Google Play filters. Filtering compares device configurations that you declare in your
 app's manifest file to the configuration defined by a device. For example, if you declare the camera
-filter in your manifest, only those devices that have a camera will see your app on Android
-Market. Filters must be configured in your application's manifest file when you are <a
+filter in your manifest, only those devices that have a camera will see your app on Google
+Play. Filters must be configured in your application's manifest file when you are <a
 href="{@docRoot}guide/publishing/preparing.html">preparing your app for release</a> (that is, before
-you upload your app to Android Market). For more information, see <a
-href="{@docRoot}guide/appendix/market-filters.html">Market Filters</a>.</p>
+you upload your app to Google Play). For more information, see <a
+href="{@docRoot}guide/appendix/market-filters.html">Filters on Google Play</a>.</p>
 
 <p>You can also use the multiple APK feature to distribute different {@code .apk} files under the same
 application listing and the same package name; however, you should use this option only as a last
@@ -205,17 +205,17 @@
 resources make the APK file too big (greater than 50MB) or other technical challenges prevent a
 single APK from working on all devices. Although we encourage you to develop and publish a single
 APK that supports as many device configurations as possible, doing so is sometimes
-not possible. To help you publish your application for as many devices as possible, Android Market
-allows you to publish multiple APKs under the same application listing. Android Market then supplies
+not possible. To help you publish your application for as many devices as possible, Google Play
+allows you to publish multiple APKs under the same application listing. Google Play then supplies
 each APK to the appropriate devices based on configuration support you've declared in the manifest
 file of each APK. To use this feature, you need to build your separate {@code .apk} files when you are <a
 href="{@docRoot}guide/publishing/preparing.html">preparing your app for release</a> (that is, before
-you upload your app to Android Market). For more information, see <a
+you upload your app to Google Play). For more information, see <a
 href="{@docRoot}guide/market/publishing/multiple-apks.html">Multiple APK Support</a>.</p>
 
-<h2 id="marketupgrade">Publishing Updates on Android Market</h2>
+<h2 id="marketupgrade">Publishing Updates on Google Play</h2>
 
-<p>At any time after publishing an application on Android Market, you can upload
+<p>At any time after publishing an application on Google Play, you can upload
 and publish an update to the same application package. When you publish an
 update to an application, users who have already installed the
 application may receive a notification that an update is
@@ -228,49 +228,49 @@
 href="{@docRoot}guide/topics/manifest/manifest-element.html"><code>&lt;manifest&gt;</code></a>
 element of the manifest file. Also, the package name must be the same as the existing version and
 the {@code .apk} file must be signed with the same private key. If the package name and signing
-certificate do <em>not</em> match those of the existing version, Market will
+certificate do <em>not</em> match those of the existing version, Google Play will
 consider it a new application, publish it as such, and will not offer it to existing users as an
 update.</p>
 
-<p>If you plan to publish your application on Android Market, you must make sure
-  that it meets the requirements listed below, which are enforced by the Market
-  server when you upload the application.</p>
+<p>If you plan to publish your application on Google Play, you must make sure
+  that it meets the requirements listed below, which are enforced by Google Play
+  when you upload the application.</p>
 
-<h2 id="marketLicensing">Using Android Market Licensing Service</h2>
+<h2 id="marketLicensing">Using Google Play Licensing Service</h2>
 
-<p>Android Market offers a licensing service that lets you enforce licensing
-policies for paid applications that you publish through Android Market. With
-Android Market Licensing, your applications can query Android Market at runtime
+<p>Google Play offers a licensing service that lets you enforce licensing
+policies for paid applications that you publish through Google Play. With
+Google Play Licensing, your applications can query Google Play at runtime
 to obtain the licensing status for the current user, then allow or disallow
 further use of the application as appropriate. Using the service, you can apply a flexible
 licensing policy on an application-by-application basis&mdash;each
 application can enforce its licensing status in the way most appropriate
 for it. </p>
 
-<p>Any application that you publish through Android Market can use the Android
-Market Licensing Service. The service uses no dedicated framework APIs, so you can
+<p>Any application that you publish through Google Play can use the Google
+Play Licensing Service. The service uses no dedicated framework APIs, so you can
 add licensing to any application that uses a minimum API Level of 3 or
 higher.</p>
 
-<p>For complete information about Android Market Licensing Service and how to
+<p>For complete information about Google Play Licensing Service and how to
 use it in your application, read <a
-href="{@docRoot}guide/publishing/licensing.html">Application Licensing</a>.</p>
+href="{@docRoot}guide/market/licensing/index.html">Application Licensing</a>.</p>
 
-<h2 id="marketinappbilling">Using Android Market In-app Billing</h2>
+<h2 id="marketinappbilling">Using Google Play In-app Billing</h2>
 
-<p><a href="{@docRoot}guide/market/billing/billing_overview.html">Android Market In-app Billing</a>
-is an Android Market service that lets you sell digital content in your applications. You can use
+<p><a href="{@docRoot}guide/market/billing/billing_overview.html">Google Play In-app Billing</a>
+is a Google Play service that lets you sell digital content in your applications. You can use
 the service to sell a wide range of content, including downloadable  content such as media files or
 photos, and virtual content such as game levels or potions.</p>
 
-<p>When you use Android Market's in-app billing service to sell an item, Android Market handles all
+<p>When you use Google Play's in-app billing service to sell an item, Google Play handles all
 billing details so your application never has to directly process any financial transactions.
-Android Market uses the same checkout service that is used for application purchases, so your users
+Google Play uses the same checkout service that is used for application purchases, so your users
 experience a consistent and familiar purchase flow (see figure 1). Also, the transaction fee for
 in-app purchases is the same as the transaction fee for application purchases (30%).</p>
 
-<p>Any application that you publish through Android Market can implement in-app billing. No special
-account or registration is required other than an Android Market publisher account and a Google
+<p>Any application that you publish through Google Play can implement in-app billing. No special
+account or registration is required other than a Google Play publisher account and a Google
 Checkout Merchant account. Also, because the service uses no dedicated framework APIs, you can add
 in-app billing to any application that uses a minimum API level of 4 or higher.</p>
 
@@ -282,58 +282,59 @@
 implement in-app billing. For more information about the in-app billing feature, see the
 <a href="{@docRoot}guide/market/billing/index.html">In-app Billing documentation</a>.</p>
 
-<h2 id="marketintent">Linking to Your Apps on Android Market</h2>
+<h2 id="marketintent">Linking to Your Apps on Google Play</h2>
 
-<p>To help users discover your published applications, you can use two special Android Market URIs
+<p>To help users discover your published applications, you can use two special Google Play URIs
 that direct users to your application's details page or perform a search for all of your published
-applications in Android Market. You can use these URIs to create a button in your application or a
+applications on Google Play. You can use these URIs to create a button in your application or a
 link on a web page that:</p>
 
 <ul>
-  <li>Opens your application's details page in the Android Market application or web site.</li>
-  <li>Searches for all your published applications in the Android Market application or web
+  <li>Opens your application's details page in the Google Play application or web site.</li>
+  <li>Searches for all your published applications in the Google Play application or web
 site.</li>
 </ul>
 
-<p>You can launch the Android Market application or web site in the following ways:</p>
+<p>You can launch the Google Play application or web site in the following ways:</p>
 <ul>
   <li>Initiate an {@link android.content.Intent} from your application that launches the
-Android Market application on the user's device.</li>
-  <li>Provide a link on a web page that opens the Android Market web site (but will also
-open the Android Market application if clicked from a device).</li>
+Google Play application on the user's device.</li>
+  <li>Provide a link on a web page that opens the Google Play web site (but will also
+open the Google Play application if clicked from a device).</li>
 </ul>
 
 <p>In both cases, whether you want to initiate the action from your application or from a web
 page, the URIs are quite similar. The only difference is the URI prefix.</p>
 
-<p>To open the Android Market application from your application, the prefix for the intent's data
+<p>To open the Google Play application from your application, the prefix for the intent's data
 URI is:</p>
 
 <p style="margin-left:2em"><code>market://</code></p>
 
-<p>To open Android Market from your web site, the prefix for the link URI is:</p>
+<p>To open Google Play store from your web site, the prefix for the link URI is:</p>
 
-<p style="margin-left:2em"><code>http://market.android.com/</code></p>
+<p style="margin-left:2em"><code>http://play.google.com/store/</code></p>
 
 <p>The following sections describe how to create a complete URI for each action.</p>
 
-<p class="note"><strong>Note:</strong> If you create a link to open Android Market from your web
-site and the user selects it from an Android-powered device, the device's Market application will
-resolve the link so the user can use the Market application instead of opening the web
-site. As such, you should always use {@code http://market.android.com/} URIs when creating a link on
+<p class="note"><strong>Note:</strong> If you create a link to open Google Play from your web
+site and the user selects it from an Android-powered device, the device's Google Play application will
+resolve the link so the user can use the Google Play application on the device instead of opening the web
+site. As such, you should always use {@code http://play.google.com/store/apps/...} URIs when
+creating a link on
 a web page. When pointing to your apps from within your Android app, use the
-{@code market://} URIs in an intent, so that the Market application always opens.</p>
+{@code market://} URIs in an intent, so that the Google Play application always opens.</p>
 
 
 <h3 id="OpeningDetails">Opening an app's details page</h3>
 
 <p>As described above, you can open the details page for a specific application either on the
-Android Market application or the Android Market web site. The details page allows the user to see
+Google Play application or the Google Play web site. The details page allows the user to see
 the application description, screenshots, reviews and more, and choose to install it.</p>
 
 <p>The format for the URI that opens the details page is:</p>
 
-<p style="margin-left:2em"><code>&lt;URI_prefix&gt;<b>details?id=</b>&lt;package_name&gt;</code></p>
+<p style="margin-left:2em"><code>&lt;URI_prefix&gt;<b>apps/details?id=</b>&lt;package_name&gt;</code></p>
 
 <p>The <code>&lt;package_name&gt;</code> is a placeholder for the target application's
 fully-qualified package name, as declared in the <a
@@ -341,26 +342,28 @@
 package}</a> attribute of the <a href="{@docRoot}guide/topics/manifest/manifest-element.html">{@code
 &lt;manifest&gt;}</a> element.</p>
 
+<p>For example: <code>http://play.google.com/store/apps/details?id=com.example.myapp</code></p>
+
 
 <h4>Opening the app details page from your Android app</h4>
 
-<p>To open the Android Market details page from your application,
+<p>To open the Google Play details page from your application,
 create an intent with the {@link android.content.Intent#ACTION_VIEW} action and include a data URI
 in this format:</p>
 
 <p style="margin-left:2em"><code>market://details?id=&lt;package_name&gt;</code></p>
 
 <p>For example, here's how you can create an intent and open an application's details page in
-Android Market:</p>
+Google Play:</p>
 
 <pre>
 Intent intent = new Intent(Intent.ACTION_VIEW);
-intent.setData(Uri.parse("market://details?id=com.android.example"));
+intent.setData(Uri.parse("market://details?id=com.example.android"));
 startActivity(intent);
 </pre>
 
-<p>This will open the Android Market application on the device to view the {@code
-com.android.example} application.</p>
+<p>This will open the Google Play application on the device to view the {@code
+com.example.android} application.</p>
 
 
 <h4>Opening the app details page from a web site</h4>
@@ -369,32 +372,32 @@
 format:</p>
 
 <p style="margin-left:2em">
-  <code>http://market.android.com/details?id=&lt;package_name&gt;</code>
+  <code>http://play.google.com/store/apps/details?id=&lt;package_name&gt;</code>
 </p>
 
-<p>For example, here's a link that opens an application's details page on Android Market:</p>
+<p>For example, here's a link that opens an application's details page on Google Play:</p>
 
 <pre>
-&lt;a href="http://market.android.com/details?id=com.android.example">App Link&lt;/a>
+&lt;a href="http://play.google.com/store/apps/details?id=com.example.android">App Link&lt;/a>
 </pre>
 
-<p>When clicked from a desktop web browser, this opens the Android Market web site to view the
-{@code com.android.example} application. When clicked from an Android-powered device, users are
-given the option to use either their web browser or the Android Market application to view the
+<p>When clicked from a desktop web browser, this opens the Google Play web site to view the
+{@code com.example.android} application. When clicked from an Android-powered device, users are
+given the option to use either their web browser or the Google Play application to view the
 application.</p>
 
 
 
 <h3 id="PerformingSearch">Performing a search</h3>
 
-<p>To initiate a search in Android Market, the format for the URI is:</p>
+<p>To initiate a search on Google Play, the format for the URI is:</p>
 
 <p style="margin-left:2em">
   <code>&lt;URI_prefix&gt;<b>search?q=</b>&lt;query&gt;</code>
 </p>
 
-<p>The <code>&lt;query&gt;</code> is a placeholder for the search query to execute in Android
-Market. The query can be a raw text string or you can include a parameter that performs a search
+<p>The <code>&lt;query&gt;</code> is a placeholder for the search query to execute in Google
+Play. The query can be a raw text string or you can include a parameter that performs a search
 based on the publisher name:</p>
 
 <ul>
@@ -410,14 +413,14 @@
 
 <h4>Searching from your Android app</h4>
 
-<p>To initiate a search on Android Market from your application, create an intent with the
+<p>To initiate a search on Google Play from your application, create an intent with the
 {@link android.content.Intent#ACTION_VIEW} action and include a data URI in this format:</p>
 
 <p style="margin-left:2em"><code>market://search?q=&lt;query&gt;</code></p>
 
 <p>The query may include the {@code pub:} parameter described above.</p>
 
-<p>For example, here's how you can initiate a search in the Android Market application, based on the
+<p>For example, here's how you can initiate a search in the Google Play application, based on the
 publisher name:</p>
 
 <pre>
@@ -426,46 +429,46 @@
 startActivity(intent);
 </pre>
 
-<p>This opens the Android Market application to perform the search. The search result shows all
+<p>This opens the Google Play application to perform the search. The search result shows all
 applications published by the publisher that are compatible with the current device.</p>
 
 
 <h4>Searching from a web site</h4>
 
-<p>To initiate a search on Android Market from your web site, create a link with a URI in this
+<p>To initiate a search on Google Play from your web site, create a link with a URI in this
 format:</p>
 
 <p style="margin-left:2em">
-  <code>http://market.android.com/search?q=&lt;query&gt;</code>
+  <code>http://play.google.com/store/search?q=&lt;query&gt;</code>
 </p>
 
 <p>The query may include the {@code pub:} parameter described above.</p>
 
-<p>For example, here's a link that initiates a search on Android Market, based on the
+<p>For example, here's a link that initiates a search on Google Play, based on the
 publisher name:</p>
 
 <pre>
-&lt;a href="http://market.android.com/search?q=pub:Your Publisher Name">Search Link&lt;/a>
+&lt;a href="http://play.google.com/store/search?q=pub:Your Publisher Name">Search Link&lt;/a>
 </pre>
 
-<p>When clicked from a desktop web browser, this opens the Android Market web site and performs the
+<p>When clicked from a desktop web browser, this opens the Google Play web site and performs the
 search. When clicked from an Android-powered device, users are given the option to use either their
-web browser or the Android Market application to perform the search.</p>
+web browser or the Google Play application to perform the search.</p>
 
 
 
-<h3 id="BuildaButton">Build an Android Market button</h3>
+<h3 id="BuildaButton">Build a Google Play button</h3>
 
-<p>Use the following form to generate an "Available in Android Market" button that you can use on
-your web site. Input either your application's package name or publisher name and the button will
-take users to Android Market to either view your application's information or view a list of
-your published apps. If users click the button while on an Android-powered device, the Android
-Market application will respond to show users your application(s).</p>
+<p>Use the following form to create a button for your web site that takes users to your application
+on Google Play. Input either your application's package name or your publisher name and the button
+will take users to Google Play to either view your application's information or view a list of your
+published apps. If users click the button while on an Android-powered device, the Google Play
+application will respond to show users your application(s).</p>
 
-<p>This form offers four versions of the official "Available in Android Market" button at
-recommended sizes. If you want to create a different size, you can download an EPS file for
-the button images from the <a href="http://www.android.com/branding.html">Android Brand
-Guidelines</a>.</p>
+<p>This form offers two styles of the official brand badge each at recommended sizes. You can pick
+between either "Get it on Google Play" or "Android app on Google Play." You should not modify the
+badge images in any way. For more usage guidelines,
+see the <a href="http://www.android.com/branding.html">Android Brand Guidelines</a>.</p>
 
 <style type="text/css">
 
@@ -507,33 +510,44 @@
 
 // variables for creating 'try it out' demo button
 var imagePath = "http://www.android.com/images/brand/"
-var linkStart = "<a href=\"http://market.android.com/";
+var linkStart = "<a href=\"http://play.google.com/store/";
 var imageStart = "\">\n"
-        + "  <img src=\"" + imagePath;
-var imageEnd = ".png\"\n"
-        + "       alt=\"Available in Android Market\" />\n</a>";
+        + "  <img alt=\"";
+  // leaves opening for the alt text value
+var imageSrc = "\"\n       src=\"" + imagePath;
+  // leaves opening for the image file name
+var imageEnd = ".png\" />\n</a>";
 
 // variables for creating code snippet
-var linkStartCode = "&lt;a href=\"http://market.android.com/";
+var linkStartCode = "&lt;a href=\"http://play.google.com/store/";
 var imageStartCode = "\"&gt;\n"
-        + "  &lt;img src=\"" + imagePath;
-var imageEndCode = ".png\"\n"
-        + "       alt=\"Available in Android Market\" />\n&lt;/a>";
+        + "  &lt;img alt=\"";
+  // leaves opening for the alt text value
+var imageSrcCode = "\"\n       src=\"" + imagePath;
+  // leaves opening for the image file name
+var imageEndCode = ".png\" />\n&lt;/a>";
 
 /** Generate the HTML snippet and demo based on form values */
 function buildButton(form) {
-  if (form["package"].value != "com.android.example") {
+  var selectedValue = $('form input[type=radio]:checked').val();
+  var altText = selectedValue.indexOf("get_it") != -1 ? "Get it on Google Play" : "Android app on Google Play";
+
+  if (form["package"].value != "com.example.android") {
     $("#preview").show();
-    $("#snippet").show().html(linkStartCode + "details?id=" + form["package"].value
-            + imageStartCode + $('form input[type=radio]:checked').val() + imageEndCode);
-    $("#button-preview").html(linkStart + "details?id=" + form["package"].value
-            + imageStart + $('form input[type=radio]:checked').val() + imageEnd);
+    $("#snippet").show().html(linkStartCode + "apps/details?id=" + form["package"].value
+            + imageStartCode + altText + imageSrcCode
+            + selectedValue + imageEndCode);
+    $("#button-preview").html(linkStart + "apps/details?id=" + form["package"].value
+            + imageStart + altText + imageSrc
+            + selectedValue + imageEnd);
   } else if (form["publisher"].value != "Example, Inc.") {
     $("#preview").show();
     $("#snippet").show().html(linkStartCode + "search?q=pub:" + form["publisher"].value
-            + imageStartCode + $('form input[type=radio]:checked').val() + imageEndCode);
-    $("#button-preview").html(linkStart + "search?q=pub:" + form["publisher"].value + imageStart +
-    $('form input[type=radio]:checked').val() + imageEnd);
+            + imageStartCode + altText + imageSrcCode
+            + selectedValue + imageEndCode);
+    $("#button-preview").html(linkStart + "search?q=pub:" + form["publisher"].value
+            + imageStart + altText + imageSrc
+            + selectedValue + imageEnd);
   } else {
     alert("Please enter your package name or publisher name");
   }
@@ -597,13 +611,13 @@
 <form class="button-form">
   <label class="block" for="package">Package name:</label>
   <input class="text" type="text" id="package" name="package"
-         value="com.android.example"
-         default="com.android.example"
-         onfocus="onInputFocus(this, 'com.android.example')"
-         onblur="onInputBlur(this, 'com.android.example')"
+         value="com.example.android"
+         default="com.example.android"
+         onfocus="onInputFocus(this, 'com.example.android')"
+         onblur="onInputBlur(this, 'com.example.android')"
          onkeyup="return onTextEntered(event, this.parentNode, this)"/>&nbsp;
          <a id="package-clear" style="display:none" href="#"
-            onclick="return clearLabel('package','com.android.example');">clear</a>
+            onclick="return clearLabel('package','com.example.android');">clear</a>
   <p style="clear:both;margin:0">&nbsp;<em>or</em></p>
   <label class="block" style="margin-top:5px" for="publisher">Publisher name:</label>
   <input class="text" type="text" id="publisher" name="publisher"
@@ -617,23 +631,23 @@
          <br/><br/>
 
 <div class="button-row">
-  <input type="radio" name="buttonStyle" value="45_avail_market_logo1" id="ns" checked="checked" />
-    <label for="ns"><img src="http://www.android.com/images/brand/45_avail_market_logo1.png"
-alt="narrow and small logo" /></label>
+  <input type="radio" name="buttonStyle" value="get_it_on_play_logo_small" id="ns" checked="checked" />
+    <label for="ns"><img src="http://www.android.com/images/brand/get_it_on_play_logo_small.png"
+alt="Get it on Google Play (small)" /></label>
     &nbsp;&nbsp;&nbsp;&nbsp;
-  <input type="radio" name="buttonStyle" value="60_avail_market_logo1" id="nm" />
-    <label for="nm"><img src="http://www.android.com/images/brand/60_avail_market_logo1.png"
-alt="narrow and large logo" /></label>
+  <input type="radio" name="buttonStyle" value="get_it_on_play_logo_large" id="nm" />
+    <label for="nm"><img src="http://www.android.com/images/brand/get_it_on_play_logo_large.png"
+alt="Get it on Google Play (large)" /></label>
 </div>
 
 <div class="button-row">
-  <input type="radio" name="buttonStyle" value="45_avail_market_logo2" id="ws" />
-    <label for="ws"><img src="http://www.android.com/images/brand/45_avail_market_logo2.png"
-alt="wide and small logo" /></label>
+  <input type="radio" name="buttonStyle" value="android_app_on_play_logo_small" id="ws" />
+    <label for="ws"><img src="http://www.android.com/images/brand/android_app_on_play_logo_small.png"
+alt="Android app on Google Play (small)" /></label>
     &nbsp;&nbsp;&nbsp;&nbsp;
-  <input type="radio" name="buttonStyle" value="60_avail_market_logo2" id="wm" />
-    <label for="wm"><img src="http://www.android.com/images/brand/60_avail_market_logo2.png"
-alt="wide and large logo" /></label>
+  <input type="radio" name="buttonStyle" value="android_app_on_play_logo_large" id="wm" />
+    <label for="wm"><img src="http://www.android.com/images/brand/android_app_on_play_logo_large.png"
+alt="Android app on Google Play (large)" /></label>
 </div>
 
   <input type="button" onclick="return buildButton(this.parentNode)" value="Build my button"
@@ -643,7 +657,7 @@
 
 <div id="preview" style="display:none">
   <p>Copy and paste this HTML into your web site:</p>
-  <textarea id="snippet" cols="80" rows="4" onclick="this.select()"
+  <textarea id="snippet" cols="100" rows="5" onclick="this.select()"
 style="font-family:monospace;background-color:#efefef;padding:5px;display:none;margin-bottom:1em">
   </textarea >
 
@@ -658,7 +672,7 @@
 
 <h3 id="UriSummary">Summary of URI formats</h3>
 
-<p>The table below provides a summary of the URIs currently supported by the Android Market (both on
+<p>The table below provides a summary of the URIs currently supported by the Google Play (both on
 the web and in the Android application), as discussed in the previous sections.</p>
 
 <table>
@@ -670,19 +684,19 @@
 
 <tr>
 <td>Display the details screen for a specific application</td>
-<td><code>http://market.android.com/details?id=&lt;package_name&gt;</code>
+<td><code>http://play.google.com/store/apps/details?id=&lt;package_name&gt;</code>
 <td><code>market://details?id=&lt;package_name&gt;</code></td>
 </tr>
 
 <tr>
 <td>Search for applications using a general string query.</td>
-<td><code>http://market.android.com/search?q=&lt;query&gt;</code></td>
+<td><code>http://play.google.com/store/search?q=&lt;query&gt;</code></td>
 <td><code>market://search?q=&lt;query&gt;</code></td>
 </tr>
 
 <tr>
 <td>Search for applications by publisher name</td>
-<td><nobr><code>http://market.android.com/search?q=pub:&lt;publisher_name&gt;</code></nobr></td>
+<td><nobr><code>http://play.google.com/store/search?q=pub:&lt;publisher_name&gt;</code></nobr></td>
 <td><nobr><code>market://search?q=pub:&lt;publisher_name&gt;</code></nobr></td>
 </tr>
 
diff --git a/docs/html/guide/publishing/publishing_overview.jd b/docs/html/guide/publishing/publishing_overview.jd
index 79199c5..6fb77e1 100755
--- a/docs/html/guide/publishing/publishing_overview.jd
+++ b/docs/html/guide/publishing/publishing_overview.jd
@@ -14,7 +14,7 @@
     <li><a href="#publishing-prepare">Preparing Your Application for Release</a></li>
     <li><a href="#publishing-release">Releasing Your Application to Users</a>
     <ol>
-      <li><a href="#publishing-market">Releasing on Android Market</a></li>
+      <li><a href="#publishing-market">Releasing on Google Play</a></li>
       <li><a href="#publishing-website">Releasing on your own website</a></li>
       <li><a href="#publishing-email">Releasing through email</a></li>
     </ol>
@@ -23,7 +23,7 @@
   <ol>
     <li><a href="{@docRoot}guide/publishing/preparing.html">Preparing for
     Release</a></li>
-    <li><a href="{@docRoot}guide/publishing/publishing.html">Publishing on Android Market</a></li>
+    <li><a href="{@docRoot}guide/publishing/publishing.html">Publishing on Google Play</a></li>
   </ol>
 </div>
 </div>
@@ -42,7 +42,7 @@
   </li>
 </ul>
 
-<p>Usually, you release your application through an application marketplace, such as Android Market.
+<p>Usually, you release your application through an application marketplace, such as Google Play.
 However, you can also release applications by sending them directly to users or by letting users
 download them from your own website.</p>
 
@@ -73,7 +73,7 @@
     <code>android:versionCode</code> and <code>android:versionName</code> attributes, which are
     located in the
     <a href="{@docRoot}guide/topics/manifest/manifest-element.html">&lt;manifest&gt;</a>
-    element. You may also have to configure several other settings to meet Android Market
+    element. You may also have to configure several other settings to meet Google Play
     requirements or accomodate whatever method you're using to release your application.</p>
   </li>
   <li>Building and signing a release version of your application.
@@ -114,27 +114,27 @@
 <h2 id="publishing-release">Releasing Your Application to Users</h2>
 
 <p>You can release your Android applications several ways. Usually, you release applications
-through an application marketplace, such as Android Market, but you can also release applications
-on your own website or by sending an application directly to a user. Android Market is the
+through an application marketplace, such as Google Play, but you can also release applications
+on your own website or by sending an application directly to a user. Google Play is the
 recommended marketplace for Android applications and is particularly useful if you want to
 distribute your applications to a large global audience. The other two release methods&mdash;server
 distribution and email distribution&mdash;are useful if you are releasing an application to a small
 group of users (for example, a work group in an enterprise environment), or if you do not want to
 make your application available to the general public.</p>
 
-<h3 id="publishing-market">Releasing Your Applications on Android Market</h3>
+<h3 id="publishing-market">Releasing Your Applications on Google Play</h3>
 
-<p>Android Market is a robust publishing platform that helps you publicize, sell, and distribute
+<p>Google Play is a robust publishing platform that helps you publicize, sell, and distribute
 your Android applications to users around the world. When you release your applications through
-Android Market you have access to a suite of developer tools that let you analyze your sales,
+Google Play you have access to a suite of developer tools that let you analyze your sales,
 identify market trends, and control who your applications are being distributed to. You also have
 access to several revenue-enhancing features that are not available anywhere else, such as <a
 href="{@docRoot}guide/market/billing/index.html">in-app billing</a> and <a
-href="{@docRoot}guide/publishing/licensing.html">application licensing</a>. This rich array of tools
-and features, coupled with numerous end-user community features, makes Android Market the premier
+href="{@docRoot}guide/market/licensing.html">application licensing</a>. This rich array of tools
+and features, coupled with numerous end-user community features, makes Google Play the premier
 marketplace for selling and buying Android applications.</p>
 
-<p>Releasing your application on Android Market is a simple process that involves three basic
+<p>Releasing your application on Google Play is a simple process that involves three basic
   steps:</p>
 
 <div class="figure" style="width:275px">
@@ -143,19 +143,19 @@
        to be installed" />
   <p class="img-caption">
     <strong>Figure 2.</strong> The <strong>Unknown sources</strong> setting lets you install
-    applications that are not published on Android Market .
+    applications that are not published on Google Play .
   </p>
 </div>
 
 <ul>
   <li>Preparing promotional materials.
-    <p>To fully leverage the marketing and publicity capabilities of Android Market, you need to
+    <p>To fully leverage the marketing and publicity capabilities of Google Play, you need to
     create promotional materials for your application, such as screenshots, videos, graphics, and
     promotional text.</p>
   </li>
   <li>Configuring options and uploading assets.
-    <p>Android Market lets you target your application to a worldwide pool of users and devices.
-    By configuring various Android Market settings, you can choose the countries you want to
+    <p>Google Play lets you target your application to a worldwide pool of users and devices.
+    By configuring various Google Play settings, you can choose the countries you want to
     reach, the listing languages you want to use, and the price you want to charge in each
     country. You can also configure listing details such as the application type, category, and
     content rating. When you are done configuring options you can upload your promotional materials
@@ -169,21 +169,21 @@
   </li>
 </ul>
 
-<p>For information about Android Market, see <a
-href="{@docRoot}guide/publishing/publishing.html#market">Publishing on Android Market</a>. This
-topic provides an introduction to Android Market features and provides a step-by-step guide for
-distributing your applications on Android Market.</p>
+<p>For information about Google Play, see <a
+href="{@docRoot}guide/publishing/publishing.html#market">Publishing on Google Play</a>. This
+topic provides an introduction to Google Play features and provides a step-by-step guide for
+distributing your applications on Google Play.</p>
 
 <h3 id="publishing-website">Releasing your application on your own website</h3>
 
-<p>If you do not want to release your application on an application marketplace like Android Market,
+<p>If you do not want to release your application on an application marketplace like Google Play,
 you can release your application by making it available for download on your own website or server.
 To do this, you must first prepare your application for release (that is, you must build it for
 release and sign it). Then all you need to do is host the release-ready application on your website
 and provide a download link for the application. When users browse to your website with their
 Android-powered devices and download your application, the Android system will automatically start
 installing the application on the device. However, the installation process will start automatically
-only if the user has configured their device to allow the installation of non-Android Market
+only if the user has configured their device to allow the installation of non-Google Play
 applications.</p>
 
 <div class="figure" style="width:275px">
@@ -197,7 +197,7 @@
 </div>
 
 <p>By default, Android-powered devices allow users to install applications only if the applications
-have been downloaded from Android Market. To allow the installation of applications from other
+have been downloaded from Google Play. To allow the installation of applications from other
 sources, users need to enable the <strong>Unknown sources</strong> setting on their devices, and
 they need to make this configuration change before they download your application to their
 device (see figure 2).</p>
@@ -208,7 +208,7 @@
 <p>Although it is relatively easy to release your application on your own website, it can be
 inefficient and cumbersome. For example, if you want to monetize your application you will
 have to process and track all financial transactions yourself and you will not be able to use
-Android Market's in-app billing feature to sell in-app products. In addition, you will not be
+Google Play's in-app billing feature to sell in-app products. In addition, you will not be
 able to use the licensing feature to help prevent unauthorized installation and use of your
 application.</p>
 
@@ -222,7 +222,7 @@
 button.</p>
 
 <p class="note"><strong>Note:</strong> The <strong>Install Now</strong> button appears only if a
-user has configured their device to allow the installation of non-Android Market applications and
+user has configured their device to allow the installation of non-Google Play applications and
 they open your email with the native Gmail application.</p>
 
 <p>Releasing applications through email is convenient if you are sending your application to
diff --git a/docs/html/guide/publishing/versioning.jd b/docs/html/guide/publishing/versioning.jd
index 79ebf96..da57e3e 100644
--- a/docs/html/guide/publishing/versioning.jd
+++ b/docs/html/guide/publishing/versioning.jd
@@ -25,7 +25,7 @@
 
 <ol>
 <li><a href="{@docRoot}guide/publishing/preparing.html">Preparing to Publish Your Application</a></li>
-<li><a href="{@docRoot}guide/publishing/publishing.html#market">Publishing On Android Market</a></li>
+<li><a href="{@docRoot}guide/publishing/publishing.html#market">Publishing On Google Play</a></li>
 <li><a href="{@docRoot}guide/topics/manifest/manifest-intro.html">The AndroidManifest.xml File</a></li>
 </ol>
 
diff --git a/docs/html/guide/topics/admin/device-admin.jd b/docs/html/guide/topics/admin/device-admin.jd
index 820c3c0..4a325db 100644
--- a/docs/html/guide/topics/admin/device-admin.jd
+++ b/docs/html/guide/topics/admin/device-admin.jd
@@ -75,8 +75,8 @@
 not currently have an automated provisioning solution. Some of the ways a sysadmin might
 distribute the application to users are as follows:
 <ul>
-<li>Android Market.</li>
-<li>Enabling non-market installation.</li>
+<li>Google Play.</li>
+<li>Enabling installation from another store.</li>
 <li>Distributing the application through other means, such as email or websites.</li>
 
 </ul>
diff --git a/docs/html/guide/topics/data/backup.jd b/docs/html/guide/topics/data/backup.jd
index 79dfd88..d91e422 100644
--- a/docs/html/guide/topics/data/backup.jd
+++ b/docs/html/guide/topics/data/backup.jd
@@ -892,8 +892,8 @@
   <li>Install your application on a suitable Android system image
     <ul>
       <li>If using the emulator, create and use an AVD with Android 2.2 (API Level 8).</li>
-      <li>If using a device, the device must be running Android 2.2 or greater and have Android
-Market built in.</li>
+      <li>If using a device, the device must be running Android 2.2 or greater and have Google
+Play built in.</li>
     </ul>
   </li>
   <li>Ensure that backup is enabled
diff --git a/docs/html/guide/topics/fundamentals.jd b/docs/html/guide/topics/fundamentals.jd
index d1a3786..a86d905 100644
--- a/docs/html/guide/topics/fundamentals.jd
+++ b/docs/html/guide/topics/fundamentals.jd
@@ -392,13 +392,13 @@
 that lack features needed by your application, it's important that you clearly define a profile for
 the types of devices your application supports by declaring device and software requirements in your
 manifest file. Most of these declarations are informational only and the system does not read
-them, but external services such as Android Market do read them in order to provide filtering
+them, but external services such as Google Play do read them in order to provide filtering
 for users when they search for applications from their device.</p>
 
 <p>For example, if your application requires a camera and uses APIs introduced in Android 2.1 (<a
 href="{@docRoot}guide/appendix/api-levels.html">API Level</a> 7), you should declare these as
 requirements in your manifest file. That way, devices that do <em>not</em> have a camera and have an
-Android version <em>lower</em> than 2.1 cannot install your application from Android Market.</p>
+Android version <em>lower</em> than 2.1 cannot install your application from Google Play.</p>
 
 <p>However, you can also declare that your application uses the camera, but does not
 <em>require</em> it. In that case, your application must perform a check at runtime to determine
@@ -458,12 +458,12 @@
 </dl>
 
 <p>It's important that you declare all such requirements for your application, because, when you
-distribute your application on Android Market, Market uses these declarations to filter which
+distribute your application on Google Play, the store uses these declarations to filter which
 applications are available on each device. As such, your application should be available only to
 devices that meet all your application requirements.</p>
 
-<p>For more information about how Android Market filters applications based on these (and other)
-requirements, see the <a href="{@docRoot}guide/appendix/market-filters.html">Market Filters</a>
+<p>For more information about how Google Play filters applications based on these (and other)
+requirements, see the <a href="{@docRoot}guide/appendix/market-filters.html">Filters on Google Play</a>
 document.</p>
 
 
diff --git a/docs/html/guide/topics/fundamentals/activities.jd b/docs/html/guide/topics/fundamentals/activities.jd
index 8736aa8..b79136c 100644
--- a/docs/html/guide/topics/fundamentals/activities.jd
+++ b/docs/html/guide/topics/fundamentals/activities.jd
@@ -62,7 +62,7 @@
 activity can then start another activity in order to perform different actions. Each time a new
 activity starts, the previous activity is stopped, but the system preserves the activity
 in a stack (the "back stack"). When a new activity starts, it is pushed onto the back stack and
-takes user focus. The back stack abides to the basic "last in, first out" queue mechanism,
+takes user focus. The back stack abides to the basic "last in, first out" stack mechanism,
 so, when the user is done with the current activity and presses the <em>Back</em> button, it
 is popped from the stack (and destroyed) and the previous activity resumes. (The back stack is
 discussed more in the <a href="{@docRoot}guide/topics/fundamentals/tasks-and-back-stack.html">Tasks
diff --git a/docs/html/guide/topics/fundamentals/fragments.jd b/docs/html/guide/topics/fundamentals/fragments.jd
index 281cb9d..2a22394 100644
--- a/docs/html/guide/topics/fundamentals/fragments.jd
+++ b/docs/html/guide/topics/fundamentals/fragments.jd
@@ -129,7 +129,7 @@
 
 <p>For example&mdash;to continue with the news application example&mdash;the application can embed
 two fragments in <em>Activity A</em>, when running on a tablet-sized device. However, on a
-handset-sized screen, there's not be enough room for both fragments, so <em>Activity A</em> includes
+handset-sized screen, there's not enough room for both fragments, so <em>Activity A</em> includes
 only the fragment for the list of articles, and when the user selects an article, it starts
 <em>Activity B</em>, which includes the second fragment to read the article. Thus, the application
 supports both tablets and handsets by reusing fragments in different combinations, as illustrated in
diff --git a/docs/html/guide/topics/graphics/opengl.jd b/docs/html/guide/topics/graphics/opengl.jd
index 6a2a20f..a786d42 100644
--- a/docs/html/guide/topics/graphics/opengl.jd
+++ b/docs/html/guide/topics/graphics/opengl.jd
@@ -189,7 +189,7 @@
     &lt;uses-feature android:glEsVersion="0x00020000" android:required="true" /&gt;
 </pre>
 
-  <p>Adding this declaration causes the Android Market to restrict your application from being
+  <p>Adding this declaration causes Google Play to restrict your application from being
   installed on devices that do not support OpenGL ES 2.0.</p>
   </li>
   <li><strong>Texture compression requirements</strong> - If your application uses texture
@@ -200,9 +200,9 @@
 
 <p>Declaring texture compression requirements in your manifest hides your application from users
 with devices that do not support at least one of your declared compression types. For more
-information on how Android Market filtering works for texture compressions, see the <a
+information on how Google Play filtering works for texture compressions, see the <a
 href="{@docRoot}guide/topics/manifest/supports-gl-texture-element.html#market-texture-filtering">
-Android Market and texture compression filtering</a> section of the {@code
+Google Play and texture compression filtering</a> section of the {@code
 &lt;supports-gl-texture&gt;} documentation.</p>
   </li>
 </ul>
@@ -470,7 +470,7 @@
 <p class="note"><strong>Note:</strong> Once you decide which texture compression formats your
 application will support, make sure you declare them in your manifest using <a
 href="{@docRoot}guide/topics/manifest/supports-gl-texture-element.html">&lt;supports-gl-texture&gt;
-</a>. Using this declaration enables filtering by external services such as Android Market, so that
+</a>. Using this declaration enables filtering by external services such as Google Play, so that
 your app is installed only on devices that support the formats your app requires. For details, see
 <a
 href="{@docRoot}guide/topics/graphics/opengl.html#manifest">OpenGL manifest declarations</a>.</p>
diff --git a/docs/html/guide/topics/manifest/activity-element.jd b/docs/html/guide/topics/manifest/activity-element.jd
index 8b131c8..9dc124b 100644
--- a/docs/html/guide/topics/manifest/activity-element.jd
+++ b/docs/html/guide/topics/manifest/activity-element.jd
@@ -672,7 +672,7 @@
 
 <p class="note"><strong>Note:</strong> When you declare one of the landscape or portrait values,
 it is considered a hard requirement for the orientation in which the activity runs. As such,
-the value you declare enables filtering by services such as Android Market so your application is
+the value you declare enables filtering by services such as Google Play so your application is
 available only to devices that support the orientation required by your activities. For
 example, if you declare either {@code "landscape"}, {@code "reverseLandscape"}, or
 {@code "sensorLandscape"}, then your application will be available only to devices that support
@@ -681,7 +681,7 @@
 href="{@docRoot}guide/topics/manifest/uses-feature-element.html">{@code &lt;uses-feature&gt;}</a>
 element. For example, <code>&lt;uses-feature
 android:name="android.hardware.screen.portrait"/></code>. This is purely a filtering behavior
-provided by Android Market (and other services that support it) and the platform itself does not
+provided by Google Play (and other services that support it) and the platform itself does not
 control whether your app can be installed when a device supports only certain orientations.</p>
 
 </dd>
diff --git a/docs/html/guide/topics/manifest/compatible-screens-element.jd b/docs/html/guide/topics/manifest/compatible-screens-element.jd
index 5c89869..a27c316 100644
--- a/docs/html/guide/topics/manifest/compatible-screens-element.jd
+++ b/docs/html/guide/topics/manifest/compatible-screens-element.jd
@@ -27,10 +27,10 @@
 
   <p>The Android system <em>does not</em> read the {@code &lt;compatible-screens&gt;} manifest
 element (neither at install-time nor at runtime). This element is informational only and may be used
-by external services (such as Android Market) to better understand the application's compatibility
+by external services (such as Google Play) to better understand the application's compatibility
 with specific screen configurations and enable filtering for users. Any screen configuration that is
 <em>not</em> declared in this element is a screen with which the application is <em>not</em>
-compatible. Thus, external services (such as Android Market) should not provide the application to
+compatible. Thus, external services (such as Google Play) should not provide the application to
 devices with such screens.</p>
 
   <p class="caution"><strong>Caution:</strong> Normally, <strong>you should not use this manifest
@@ -48,14 +48,14 @@
 only for <em>large</em> and <em>xlarge</em> screen devices, the <a
 href="{@docRoot}guide/topics/manifest/supports-screens-element.html">{@code
 &lt;supports-screens&gt;}</a> element allows you to declare that your application does not
-support <em>small</em> and <em>normal</em> screen sizes. External services (such as Android
-Market) will filter your application accordingly. You can also use the <a
+support <em>small</em> and <em>normal</em> screen sizes. External services (such as Google
+Play) will filter your application accordingly. You can also use the <a
 href="{@docRoot}guide/topics/manifest/supports-screens-element.html">{@code
 &lt;supports-screens&gt;}</a> element to declare whether the system should resize your
 application for different screen sizes.</p>
 
-  <p>Also see the <a href="{@docRoot}guide/appendix/market-filters.html">Market Filters</a>
-document for more information about how Android Market filters applications using this and
+  <p>Also see the <a href="{@docRoot}guide/appendix/market-filters.html">Filters on Google Play</a>
+document for more information about how Google Play filters applications using this and
 other manifest elements.</p>
 
 </dd>
@@ -138,5 +138,5 @@
 <dt>see also:</dt>
 <dd><a
 href="{@docRoot}guide/practices/screens_support.html">Supporting Multiple Screens</a></dd>
-<dd><a href="{@docRoot}guide/appendix/market-filters.html">Market Filters</a></dd>
+<dd><a href="{@docRoot}guide/appendix/market-filters.html">Filters on Google Play</a></dd>
 </dl>
diff --git a/docs/html/guide/topics/manifest/manifest-element.jd b/docs/html/guide/topics/manifest/manifest-element.jd
index d737a67..9788945 100644
--- a/docs/html/guide/topics/manifest/manifest-element.jd
+++ b/docs/html/guide/topics/manifest/manifest-element.jd
@@ -150,9 +150,9 @@
 </tr>
 </table>
 
-<p class="caution"><strong>Caution:</strong> If your application uses the Android Market's Copy 
-  Protection feature, it cannot be installed to a device's SD card. However, if you use Android 
-  Market's <a href="{@docRoot}guide/publishing/licensing.html">Application Licensing</a> instead, 
+<p class="caution"><strong>Caution:</strong> If your application uses Google Play's Copy 
+  Protection feature, it cannot be installed to a device's SD card. However, if you use Google 
+  Play's <a href="{@docRoot}guide/market/licensing.html">Application Licensing</a> instead, 
   your application <em>can</em> be installed to internal or external storage, including SD cards.</p>
 
 <p class="note"><strong>Note:</strong> By default, your application will be installed on the
diff --git a/docs/html/guide/topics/manifest/supports-gl-texture-element.jd b/docs/html/guide/topics/manifest/supports-gl-texture-element.jd
index 6c4a05a..ebdd0b1 100644
--- a/docs/html/guide/topics/manifest/supports-gl-texture-element.jd
+++ b/docs/html/guide/topics/manifest/supports-gl-texture-element.jd
@@ -18,20 +18,20 @@
  <div class="sidebox-wrapper">
   <img id="rule" src="{@docRoot}assets/images/grad-rule-qv.png">
   <div id="qv-sub-rule">
-    <img src="{@docRoot}assets/images/icon_market.jpg"
+    <img src="{@docRoot}assets/images/icon_play.png"
     style="float:left;margin:0;padding:0;">
-    <p style="color:#669999;">Android Market and <code
+    <p style="color:#669999;padding-top:1em;">Google Play and <code
     style="color:#669999;">&lt;supports-gl-texture&gt;</code> elements</p>
-    <p style="margin-top:1em;">Android Market filters applications according
+    <p style="margin-top:1em;">Google Play filters applications according
     to the texture compression formats that they support, to ensure that
     they can be installed only on devices that can handle their textures
     properly. Developers can use texture compression filtering
     as a way of targeting specific device types, based on GPU platform.</p>
     
     <p style="margin-top:1em;" class="caution">For important information about how
-    Android Market uses <code>&lt;supports-gl-texture&gt;</code> elements as
-    the basis for filtering, please read <a href="#market-texture-filtering">Android
-    Market and texture compression filtering</a>, below.</p>
+    Google Play uses <code>&lt;supports-gl-texture&gt;</code> elements as
+    the basis for filtering, please read <a href="#market-texture-filtering">Google
+    Play and texture compression filtering</a>, below.</p>
 </div> 
 </div>
 
@@ -57,7 +57,7 @@
 <p>Declared <code>&lt;supports-gl-texture&gt;</code> elements are informational,
 meaning that the Android system itself does not examine the elements at install
 time to ensure matching support on the device. However, other services
-(such as Android Market) or applications can check your application's
+(such as Google Play) or applications can check your application's
 <code>&lt;supports-gl-texture&gt;</code> declarations as part of handling or
 interacting with your application. For this reason, it's very important that
 you declare all of the texture compression formats (from the list below) that
@@ -141,20 +141,20 @@
 <dt>see also:</dt>
 <dd>
   <ul>
-    <li><a href="{@docRoot}guide/appendix/market-filters.html">Android Market Filters</a></li>
+    <li><a href="{@docRoot}guide/appendix/market-filters.html">Filters on Google Play</a></li>
   </ul>
 </dd>
 
-<h2 id="market-texture-filtering">Android Market and texture compression filtering</h2>
+<h2 id="market-texture-filtering">Google Play and texture compression filtering</h2>
 
-<p>Android Market filters the applications that are visible to users, so that
+<p>Google Play filters the applications that are visible to users, so that
 users can see and download only those applications that are compatible with
-their devices. One of the ways Market filters applications is by texture
+their devices. One of the ways it filters applications is by texture
 compression compatibility, giving you control over the availability of your
 application to various devices, based on the capabilities of their GPUs.</p>
 
 <p>To determine an application's texture compression compatibility with a given
-user's device, Android Market compares:</p>
+user's device, Google Play compares:</p>
 
 <ul>
 <li>Texture compression formats that are supported by the application &mdash;
@@ -164,26 +164,26 @@
 a device reports the formats it supports as read-only system properties.</li>
 </ul>
 
-<p>Each time you upload an application to the Android Market Publisher Site,
-Android Market scans the application's manifest file and looks for any
+<p>Each time you upload an application to the Google Play publisher site,
+Google Play scans the application's manifest file and looks for any
 <code>&lt;supports-gl-texture&gt;</code> elements. It extracts the
 format descriptors from the elements and stores them internally as
 metadata associated with the application <code>.apk</code> and the application
 version. </p>
 
-<p>When a user searches or browses for applications on Android Market,
+<p>When a user searches or browses for applications on Google Play,
 the service compares the texture compression formats supported by the application
 with those supported by the user's device. The comparison is based on the format
 descriptor strings and a match must be exact.</p>
 
 <p>If <em>any</em> of an application's supported texture compression formats is
-also supported by the device, Android Market allows the user to see the
+also supported by the device, Google Play allows the user to see the
 application and potentially download it. Otherwise, if none of the application's
-formats is supported by the device, Android Market filters the application so
+formats is supported by the device, Google Play filters the application so
 that it is not available for download. </p>
 
 <p>If an application does not declare any <code>&lt;supports-gl-texture&gt;</code> elements,
-Android Market does not apply any filtering based on GL texture compression format.</p>
+Google Play does not apply any filtering based on GL texture compression format.</p>
 
 </dl>
 
diff --git a/docs/html/guide/topics/manifest/supports-screens-element.jd b/docs/html/guide/topics/manifest/supports-screens-element.jd
index 81d6e27..ae14121 100644
--- a/docs/html/guide/topics/manifest/supports-screens-element.jd
+++ b/docs/html/guide/topics/manifest/supports-screens-element.jd
@@ -80,7 +80,7 @@
      A small screen is defined as one with a smaller aspect ratio than
      the "normal" (traditional HVGA) screen.  An application that does
      not support small screens <em>will not be available</em> for
-     small screen devices from external services (such as Android Market), because there is little
+     small screen devices from external services (such as Google Play), because there is little
 the platform can do to make such an application work on a smaller screen. This is {@code "true"} by
 default.
   </dd>
@@ -156,8 +156,8 @@
 
   <p class="caution"><strong>Caution:</strong> The Android system does not pay attention to this
 attribute, so it does not affect how your application behaves at runtime. Instead, it is used
-to enable filtering for your application on services such as Android Market. However,
-<strong>Android Market currently does not support this attribute for filtering</strong> (on Android
+to enable filtering for your application on services such as Google Play. However,
+<strong>Google Play currently does not support this attribute for filtering</strong> (on Android
 3.2), so you should continue using the other size attributes if your application does not support
 small screens.</p>
 
diff --git a/docs/html/guide/topics/manifest/uses-feature-element.jd b/docs/html/guide/topics/manifest/uses-feature-element.jd
index 9f80638..9175566 100644
--- a/docs/html/guide/topics/manifest/uses-feature-element.jd
+++ b/docs/html/guide/topics/manifest/uses-feature-element.jd
@@ -9,7 +9,7 @@
 
 <h2>In this document</h2>
 <ol>
-  <li><a href="#market-feature-filtering">Android Market and Feature-Based Filtering</a>
+  <li><a href="#market-feature-filtering">Google Play and Feature-Based Filtering</a>
     <ol>
       <li><a href="#declared">Filtering based on explicitly declared features</a></li>
       <li><a href="#implicit">Filtering based on implicit features</a></li>
@@ -45,26 +45,26 @@
  <div class="sidebox-wrapper"> 
   <img id="rule" src="{@docRoot}assets/images/grad-rule-qv.png"> 
   <div id="qv-sub-rule"> 
-    <img src="{@docRoot}assets/images/icon_market.jpg" style="float:left;margin:0;padding:0;"> 
-    <p style="color:#669999;">Android Market and <code style="color:#669999;">&lt;uses-feature&gt;</code> elements</p>
-    <p style="margin-top:1em;">Android Market filters the applications that are visible to users, so
+    <img src="{@docRoot}assets/images/icon_play.png" style="float:left;margin:0;padding:0;"> 
+    <p style="color:#669999;padding-top:1em;">Google Play and <code style="color:#669999;">&lt;uses-feature&gt;</code> elements</p>
+    <p style="margin-top:1em;">Google Play filters the applications that are visible to users, so
 that users can see and download only those applications that are compatible with their
-devices. One of the ways Market filters applications is by feature compatibility.</p>
+devices. One of the ways it filters applications is by feature compatibility.</p>
 
-<p style="margin-top:1em;">To do this, Market checks the
+<p style="margin-top:1em;">To do this, Google Play checks the
 <code>&lt;uses-feature&gt;</code> elements in each application's manifest, to
-establish the app's feature needs. Market then shows or hides the application to
+establish the app's feature needs. Google Play then shows or hides the application to
 each user, based on a comparison with the features available on the user's
 device. </p>
 
 <p style="margin-top:1em;">By specifying the features that your application requires,
-you enable Android Market to present your application only to users whose
+you enable Google Play to present your application only to users whose
 devices meet the application's feature requirements, rather than presenting it
 to all users. </p>
 
 <p style="margin-top:1em;" class="caution">For important information about how
-Android Market uses features as the basis for filtering, please read <a
-href="#market-feature-filtering">Android Market and Feature-Based Filtering</a>,
+Google Play uses features as the basis for filtering, please read <a
+href="#market-feature-filtering">Google Play and Feature-Based Filtering</a>,
 below.</p>
 </div>
 </div>
@@ -106,7 +106,7 @@
 <p>Declared <code>&lt;uses-feature></code> elements are informational only, meaning
 that the Android system itself does not check for matching feature support on
 the device before installing an application. However, other services
-(such as Android Market) or applications may check your application's 
+(such as Google Play) or applications may check your application's 
 <code>&lt;uses-feature></code> declarations as part of handling or interacting
 with your application. For this reason, it's very important that you declare all of
 the features (from the list below) that your application uses. </p>
@@ -207,22 +207,22 @@
     <li>{@link android.content.pm.FeatureInfo}</li>
     <li>{@link android.content.pm.ConfigurationInfo}</li>
     <li><a href="{@docRoot}guide/topics/manifest/uses-permission-element.html"><code>&lt;uses-permission&gt;</code></a></li>
-    <li><a href="{@docRoot}guide/appendix/market-filters.html">Android Market Filters</a></li>
+    <li><a href="{@docRoot}guide/appendix/market-filters.html">Filters on Google Play</a></li>
   </ul>
 </dd>
 
 </dl>
 
 
-<h2 id="market-feature-filtering">Android Market and Feature-Based Filtering</h2>
+<h2 id="market-feature-filtering">Google Play and Feature-Based Filtering</h2>
 
-<p>Android Market filters the applications that are visible to users, so that
+<p>Google Play filters the applications that are visible to users, so that
 users can see and download only those applications that are compatible with
-their devices. One of the ways Market filters applications is by feature
+their devices. One of the ways it filters applications is by feature
 compatibility.</p>
 
 <p>To determine an application's feature compatibility with a given user's
-device, the Android Market service compares:</p>
+device, Google Play compares:</p>
 
 <ul>
 <li>Features required by the application &mdash; an application declares features in
@@ -238,14 +238,14 @@
 the bottom of this document, and in the class documentation for {@link
 android.content.pm.PackageManager}.</p>
 
-<p>When the user launches the Market application, the application queries the
+<p>When the user launches Google Play, the application queries the
 Package Manager for the list of features available on the device by calling
 {@link android.content.pm.PackageManager#getSystemAvailableFeatures()}. The
-Market application then passes the features list up to the Android Market
-service when establishing the session for the user.</p>
+Store application then passes the features list up to Google Play
+when establishing the session for the user.</p>
 
-<p>Each time you upload an application to the Android Market Publisher Site,
-Android Market scans the application's manifest file. It looks for
+<p>Each time you upload an application to the Google Play publisher site,
+Google Play scans the application's manifest file. It looks for
 <code>&lt;uses-feature&gt;</code> elements and evaluates them in combination
 with other elements, in some cases, such as <code>&lt;uses-sdk&gt;</code> and
 <code>&lt;uses-permission&gt;</code> elements. After establishing the
@@ -253,17 +253,17 @@
 metadata associated with the application <code>.apk</code> and the application
 version. </p>
 
-<p>When a user searches or browses for applications using the Android Market
+<p>When a user searches or browses for applications using the Google Play
 application, the service compares the features needed by each application with
 the features available on the user's device. If all of an application's required
-features are present on the device, Android Market allows the user to see the
+features are present on the device, Google Play allows the user to see the
 application and potentially download it. If any required feature is not
-supported by the device, Android Market filters the application so that it is
+supported by the device, Google Play filters the application so that it is
 not visible to the user and not available for download. </p>
 
 <p>Because the features you declare in <code>&lt;uses-feature&gt;</code>
-elements directly affect how Android Market filters your application, it's
-important to understand how Android Market evaluates the application's manifest
+elements directly affect how Google Play filters your application, it's
+important to understand how Google Play evaluates the application's manifest
 and establishes the set of required features. The sections below provide more
 information. </p>
 
@@ -277,35 +277,35 @@
 it (<code>"true"</code>), or whether the application prefers to use the feature
 if available, but is designed to run without it (<code>"false"</code>).</p>
 
-<p>Android Market handles explicitly declared features in this way: </p>
+<p>Google Play handles explicitly declared features in this way: </p>
 
 <ul>
-<li>If a feature is explicitly declared as being required, Android Market adds
+<li>If a feature is explicitly declared as being required, Google Play adds
 the feature to the list of required features for the application. It then
 filters the application from users on devices that do not provide that feature.
 For example:
 <pre>&lt;uses-feature android:name="android.hardware.camera" android:required="true" /&gt;</pre></li>
-<li>If a feature is explicitly declared as <em>not</em> being required, Android
-Market <em>does not</em> add the feature to the list of required features. For
+<li>If a feature is explicitly declared as <em>not</em> being required, Google
+Play <em>does not</em> add the feature to the list of required features. For
 that reason, an explicitly declared non-required feature is never considered when
 filtering the application. Even if the device does not provide the declared
-feature, Android Market will still consider the application compatible with the
+feature, Google Play will still consider the application compatible with the
 device and will show it to the user, unless other filtering rules apply. For
 example:
 <pre>&lt;uses-feature android:name="android.hardware.camera" android:required="false" /&gt;</pre></li>
 <li>If a feature is explicitly declared, but without an
-<code>android:required</code> attribute, Android Market assumes that the feature
+<code>android:required</code> attribute, Google Play assumes that the feature
 is required and sets up filtering on it. </li>
 </ul>
 
 <p>In general, if your application is designed to run on Android 1.6 and earlier
 versions, the <code>android:required</code> attribute is not available in the
-API and Android Market assumes that any and all
+API and Google Play assumes that any and all
 <code>&lt;uses-feature&gt;</code> declarations are required. </p>
 
 <p class="note"><strong>Note:</strong> By declaring a feature explicitly and
 including an <code>android:required="false"</code> attribute, you can
-effectively disable all filtering on Android Market for the specified feature.
+effectively disable all filtering on Google Play for the specified feature.
 </p>
 
 
@@ -317,7 +317,7 @@
 speaking, every application should <em>always</em> declare all features that it
 uses or requires, so the absence of a declaration for a feature used by an
 application should be considered an error. However, as a safeguard for users and
-developers, Android Market looks for implicit features in each application and
+developers, Google Play looks for implicit features in each application and
 sets up filters for those features, just as it would do for an explicitly
 declared feature. </p>
 
@@ -337,25 +337,25 @@
 </li>
 </ul>
 
-<p>To account for the cases above, Android Market attempts to discover an
+<p>To account for the cases above, Google Play attempts to discover an
 application's implied feature requirements by examining <em>other elements</em>
 declared in the manifest file, specifically,
 <code>&lt;uses-permission&gt;</code> elements.</p>
 
-<p>If an application requests hardware-related permissions, Android Market
+<p>If an application requests hardware-related permissions, Google Play
 <em>assumes that the application uses the underlying hardware features and
 therefore requires those features</em>, even though there might be no
 corresponding to <code>&lt;uses-feature&gt;</code> declarations. For such
-permissions, Android Market adds the underlying hardware features to the
+permissions, Google Play adds the underlying hardware features to the
 metadata that it stores for the application and sets up filters for them.</p>
 
 <p>For example, if an application requests the <code>CAMERA</code> permission
 but does not declare a <code>&lt;uses-feature&gt;</code> element for
-<code>android.hardware.camera</code>, Android Market considers that the
+<code>android.hardware.camera</code>, Google Play considers that the
 application requires a camera and should not be shown to users whose devices do
 not offer a camera.</p>
 
-<p>If you don't want Android Market to filter based on a specific implied
+<p>If you don't want Google Play to filter based on a specific implied
 feature, you can disable that behavior. To do so, declare the feature explicitly
 in a <code>&lt;uses-feature&gt;</code> element and include an 
 <code>android:required="false"</code> attribute. For example, to disable
@@ -366,30 +366,30 @@
 
 <p class="caution">It's important to understand that the permissions that you
 request in <code>&lt;uses-permission&gt;</code> elements can directly affect how
-Android Market filters your application. The reference section <a
+Google Play filters your application. The reference section <a
 href="#permissions">Permissions that Imply Feature Requirements</a>,
 below, lists the full set of permissions that imply feature requirements and
 therefore trigger filtering.</p>
 
 <h3 id="bt-permission-handling">Special handling for Bluetooth feature</h3>
 
-<p>Android Market applies slightly different rules than described above, when
+<p>Google Play applies slightly different rules than described above, when
 determining filtering for Bluetooth.</p>
 
 <p>If an application declares a Bluetooth permission in a
 <code>&lt;uses-permission&gt;</code> element, but does not explicitly declare
-the Bluetooth feature in a <code>&lt;uses-feature&gt;</code> element, Android
-Market checks the version(s) of the Android platform on which the application is
+the Bluetooth feature in a <code>&lt;uses-feature&gt;</code> element, Google
+Play checks the version(s) of the Android platform on which the application is
 designed to run, as specified in the <code>&lt;uses-sdk&gt;</code> element. </p>
 
-<p>As shown in the table below, Android Market enables filtering for the
+<p>As shown in the table below, Google Play enables filtering for the
 Bluetooth feature only if the application declares its lowest or targeted
-platform as Android 2.0 (API level 5) or higher. However, note that Android
-market applies the normal rules for filtering when the application explicitly
+platform as Android 2.0 (API level 5) or higher. However, note that Google
+Play applies the normal rules for filtering when the application explicitly
 declares the Bluetooth feature in a <code>&lt;uses-feature&gt;</code> element.
 </p>
 
-<p class="caption"><strong>Table 1.</strong> How Android Market determines the
+<p class="caption"><strong>Table 1.</strong> How Google Play determines the
 Bluetooth feature requirement for an application that requests a Bluetooth
 permission but does not declare the Bluetooth feature in a
 <code>&lt;uses-feature&gt;</code> element.</p>
@@ -403,14 +403,14 @@
 <tr>
 <td><nobr>&lt;=4 (or uses-sdk is not declared)</nobr></td>
 <td>&lt;=4</td>
-<td>Android Market <em>will not</em> filter the application from any devices
+<td>Google Play <em>will not</em> filter the application from any devices
 based on their reported support for the <code>android.hardware.bluetooth</code>
 feature.</td>
 </tr>
 <tr>
 <td>&lt;=4</td>
 <td>&gt;=5</td>
-<td rowspan="2">Android Market filters the application from any devices that
+<td rowspan="2">Google Play filters the application from any devices that
 do not support the <code>android.hardware.bluetooth</code> feature (including
 older releases).</td>
 </tr>
@@ -421,13 +421,13 @@
 </table>
 
 <p>The examples below illustrate the different filtering effects, based on how
-Android Market handles the Bluetooth feature. </p>
+Google Play handles the Bluetooth feature. </p>
 
 <dl>
 <dt>In first example, an application that is designed to run on older API levels
 declares a Bluetooth permission, but does not declare the Bluetooth feature in a
 <code>&lt;uses-feature&gt;</code> element.</dt>
-<dd><em>Result:</em> Android Market does not filter the application from any device.</dd>
+<dd><em>Result:</em> Google Play does not filter the application from any device.</dd>
 </dl>
 
 <pre>&lt;manifest ...>
@@ -439,7 +439,7 @@
 <dl>
 <dt>In the second example, below, the same application also declares a target
 API level of "5". </dt>
-<dd><em>Result:</em> Android Market now assumes that the feature is required and
+<dd><em>Result:</em> Google Play now assumes that the feature is required and
 will filter the application from all devices that do not report Bluetooth support,
 including devices running older versions of the platform. </dd>
 </dl>
@@ -465,7 +465,7 @@
 <dl>
 <dt>Finally, in the case below, the same application adds an
 <code>android:required="false"</code> attribute.</dt>
-<dd><em>Result:</em> Android Market disables filtering based on Bluetooth
+<dd><em>Result:</em> Google Play disables filtering based on Bluetooth
 feature support, for all devices.</dd>
 </dl>
 
@@ -481,10 +481,10 @@
 <h3 id="testing">Testing the features required by your application</h3>
 
 <p>You can use the <code>aapt</code> tool, included in the Android SDK, to
-determine how Android Market will filter your application, based on its declared
+determine how Google Play will filter your application, based on its declared
 features and permissions. To do so, run  <code>aapt</code> with the <code>dump
 badging</code> command. This causes <code>aapt</code> to parse your
-application's manifest and apply the same rules as used by Android Market to
+application's manifest and apply the same rules as used by Google Play to
 determine the features that your application requires. </p>
 
 <p>To use the tool, follow these steps: </p>
@@ -529,7 +529,7 @@
 <h2 id=features-reference>Features Reference</h2>
 
 <p>The tables below provide reference information about hardware and software
-features and the permissions that can imply them on Android Market. </p>
+features and the permissions that can imply them on Google Play. </p>
 
 <h3 id="hw-features">Hardware features</h3>
 
@@ -873,12 +873,12 @@
 the ability to declare that they require the API via the
 <code>&lt;uses-feature&gt;</code> system. </p>
 
-<p>To prevent those apps from being made available unintentionally,  Android
-Market assumes that certain hardware-related permissions indicate that the
+<p>To prevent those apps from being made available unintentionally,  Google
+Play assumes that certain hardware-related permissions indicate that the
 underlying hardware features are required by default. For instance, applications
 that use Bluetooth must request the <code>BLUETOOTH</code> permission in a
-<code>&lt;uses-permission&gt;</code> element &mdash; for legacy apps, Android
-Market assumes that the permission declaration means that the underlying
+<code>&lt;uses-permission&gt;</code> element &mdash; for legacy apps, Google
+Play assumes that the permission declaration means that the underlying
 <code>android.hardware.bluetooth</code> feature is required by the application
 and sets up filtering based on that feature. </p>
 
diff --git a/docs/html/guide/topics/manifest/uses-library-element.jd b/docs/html/guide/topics/manifest/uses-library-element.jd
index d94ad9f..2f8eb50 100644
--- a/docs/html/guide/topics/manifest/uses-library-element.jd
+++ b/docs/html/guide/topics/manifest/uses-library-element.jd
@@ -33,7 +33,7 @@
     </p>
     <p>
         This element also affects the installation of the application on a particular device and
-        the availability of the application in Android Market:
+        the availability of the application on Google Play:
     </p>
     <dl>
         <dt><em>Installation</em></dt>
@@ -42,11 +42,11 @@
             {@code true}, the {@link android.content.pm.PackageManager} framework won't let the user
             install the application unless the library is present on the user's device.
         </dd>
-        <dt><em>Market</em></dt>
+        <dt><em>Google Play</em></dt>
         <dd>
-            Android Market filters applications based on the libraries installed on the
+            Google Play filters applications based on the libraries installed on the
             user's device. For more information about filtering, see the topic
-            <a href="{@docRoot}guide/appendix/market-filters.html">Market Filters</a>.
+            <a href="{@docRoot}guide/appendix/market-filters.html">Filters on Google Play</a>.
         </dd>
     </dl>
     <p>
diff --git a/docs/html/guide/topics/manifest/uses-permission-element.jd b/docs/html/guide/topics/manifest/uses-permission-element.jd
index 967fc5a..6c71fb4 100644
--- a/docs/html/guide/topics/manifest/uses-permission-element.jd
+++ b/docs/html/guide/topics/manifest/uses-permission-element.jd
@@ -8,21 +8,21 @@
  <div class="sidebox-wrapper"> 
   <img id="rule" src="{@docRoot}assets/images/grad-rule-qv.png"> 
   <div id="qv-sub-rule"> 
-    <img src="{@docRoot}assets/images/icon_market.jpg" style="float:left;margin:0;padding:0;"> 
-    <p style="color:#669999;"><code style="color:#669999;">&lt;uses-permission&gt;</code> and filtering on Android Market. </p>
+    <img src="{@docRoot}assets/images/icon_play.png" style="float:left;margin:0;padding:0;"> 
+    <p style="color:#669999;padding-top:1em;"><code style="color:#669999;">&lt;uses-permission&gt;</code> and filtering on Google Play. </p>
 
 <p style="margin-top:1em;">In some cases, the permissions that you request
 through <code>&lt;uses-permission&gt;</code> can affect how
-your application is filtered by Android Market.</p>
+your application is filtered by Google Play.</p>
 
 <p style="margin-top:1em;">If you request a hardware-related permission &mdash;
-<code>CAMERA</code>, for example &mdash; Android Market assumes that your
+<code>CAMERA</code>, for example &mdash; Google Play assumes that your
 application requires the underlying hardware feature and filters the application
 from devices that do not offer it.</p>
 
 <p style="margin-top:1em;">To control filtering, always explicitly declare
 hardware features in <code>&lt;uses-feature&gt;</code> elements, rather than
-relying on Android Market to "discover" the requirements in
+relying on Google Play to "discover" the requirements in
 <code>&lt;uses-permission&gt;</code> elements. Then, if you want to disable
 filtering for a particular feature, you can add a
 <code>android:required="false"</code> attribute to the
diff --git a/docs/html/guide/topics/manifest/uses-sdk-element.jd b/docs/html/guide/topics/manifest/uses-sdk-element.jd
index 99c91f6..8fa39d1 100644
--- a/docs/html/guide/topics/manifest/uses-sdk-element.jd
+++ b/docs/html/guide/topics/manifest/uses-sdk-element.jd
@@ -33,16 +33,16 @@
  <div class="sidebox-wrapper" xstyle="margin-bottom:2em;margin-top:.5em;width:90%;"> 
   <img id="rule" src="{@docRoot}assets/images/grad-rule-qv.png"> 
   <div id="qv-sub-rule"> 
-    <img src="{@docRoot}assets/images/icon_market.jpg" style="float:left;margin:0;padding:0;"> 
-    <p style="color:#669999;">Android Market and &lt;uses-sdk&gt; attributes</p> 
-    <p>Android Market filters the applications that are visible to users, so
+    <img src="{@docRoot}assets/images/icon_play.png" style="float:left;margin:0;padding:0;"> 
+    <p style="color:#669999;padding-top:1em;">Google Play and &lt;uses-sdk&gt; attributes</p> 
+    <p style="padding-top:1em;">Google Play filters the applications that are visible to users, so
 that users can only see and download applications that are compatible with their
-devices. One of the ways Market filters applications is by Android
-version-compatibility. To do this, Market checks the <code>&lt;uses-sdk&gt;</code>
+devices. One of the ways it filters applications is by Android
+version-compatibility. To do this, Google Play checks the <code>&lt;uses-sdk&gt;</code>
 attributes in each application's manifest to establish its version-compatibility
 range, then shows or hides the application based on a comparison with the API
 Level of the user's Android system version. For more information, see <a
-href="{@docRoot}guide/appendix/market-filters.html">Market Filters</a>.</p>
+href="{@docRoot}guide/appendix/market-filters.html">Filters on Google Play</a>.</p>
   </div>
 </div>
 
@@ -114,7 +114,7 @@
   updates, consider the following example: </p>
 
   <p>An application declaring <code>maxSdkVersion="5"</code> in its
-  manifest is published on Android Market. A user whose device is running Android
+  manifest is published on Google Play. A user whose device is running Android
   1.6 (API Level 4) downloads and installs the app. After a few weeks, the user
   receives an over-the-air system update to Android 2.0 (API Level 5). After the
   update is installed, the system checks the application's
@@ -143,7 +143,7 @@
 
   <div class="special">Future versions of Android (beyond Android 2.0.1) will no
 longer check or enforce the <code>maxSdkVersion</code> attribute during
-installation or re-validation. Android Market will continue to use the attribute
+installation or re-validation. Google Play will continue to use the attribute
 as a filter, however, when presenting users with applications available for
 download. </div>
   </dd>
diff --git a/docs/html/guide/topics/media/camera.jd b/docs/html/guide/topics/media/camera.jd
index 4e928b3..7d72491 100644
--- a/docs/html/guide/topics/media/camera.jd
+++ b/docs/html/guide/topics/media/camera.jd
@@ -131,11 +131,11 @@
   <p>For a list of camera features, see the manifest
 <a href="{@docRoot}guide/topics/manifest/uses-feature-element.html#hw-features">Features
 Reference</a>.</p>
-  <p>Adding camera features to your manifest causes Android Market to prevent your application from
+  <p>Adding camera features to your manifest causes Google Play to prevent your application from
 being installed to devices that do not include a camera or do not support the camera features you
-specify. For more information about using feature-based filtering with Android Market, see <a
-href="{@docRoot}guide/topics/manifest/uses-feature-element.html#market-feature-filtering">Android
-Market and Feature-Based Filtering</a>.</p>
+specify. For more information about using feature-based filtering with Google Play, see <a
+href="{@docRoot}guide/topics/manifest/uses-feature-element.html#market-feature-filtering">Google
+Play and Feature-Based Filtering</a>.</p>
   <p>If your application <em>can use</em> a camera or camera feature for proper operation, but does
 not <em>require</em> it, you should specify this in the manifest by including the {@code
 android:required} attribute, and setting it to {@code false}:</p>
@@ -442,7 +442,7 @@
 the first, back-facing camera on a device with more than one camera.</p>
 
 <h3 id="check-camera-features">Checking camera features</h3>
-<p>Once you obtain access to a camera, you can get further information about its capabilties using
+<p>Once you obtain access to a camera, you can get further information about its capabilities using
 the {@link android.hardware.Camera#getParameters() Camera.getParameters()} method and checking the
 returned {@link android.hardware.Camera.Parameters} object for supported capabilities. When using
 API Level 9 or higher, use the {@link android.hardware.Camera#getCameraInfo(int,
@@ -677,8 +677,8 @@
 <pre>
 // Add a listener to the Capture button
 Button captureButton = (Button) findViewById(id.button_capture);
-    captureButton.setOnClickListener(
-        new View.OnClickListener() {
+captureButton.setOnClickListener(
+    new View.OnClickListener() {
         &#64;Override
         public void onClick(View v) {
             // get an image from the camera
@@ -1260,7 +1260,7 @@
 
 <p>If your application requires certain camera features in order to function properly, you can
 require them through additions to your application manifest. When you declare the use of specific
-camera features, such as flash and auto-focus, the Android Market restricts your application from
+camera features, such as flash and auto-focus, Google Play restricts your application from
 being installed on devices which do not support these features. For a list of camera features that
 can be declared in your app manifest, see the manifest
 <a href="{@docRoot}guide/topics/manifest/uses-feature-element.html#hw-features"> Features
diff --git a/docs/html/guide/topics/network/sip.jd b/docs/html/guide/topics/network/sip.jd
index 276adb6..600da78 100644
--- a/docs/html/guide/topics/network/sip.jd
+++ b/docs/html/guide/topics/network/sip.jd
@@ -147,7 +147,7 @@
 </ul>
 
 <p>To control how your application is filtered from devices that do not support
-SIP (for example, in Android Market), add the following to your application's
+SIP (for example, on Google Play), add the following to your application's
 manifest:</p>
 
 <ul>
diff --git a/docs/html/guide/topics/nfc/nfc.jd b/docs/html/guide/topics/nfc/nfc.jd
index 83873c3..834656a 100644
--- a/docs/html/guide/topics/nfc/nfc.jd
+++ b/docs/html/guide/topics/nfc/nfc.jd
@@ -318,8 +318,8 @@
 </pre>
     </li>
 
-    <li>The <code>uses-feature</code> element so that your application shows up in the Android
-Market only for devices that have NFC hardware:
+    <li>The <code>uses-feature</code> element so that your application shows up in Google
+Play only for devices that have NFC hardware:
       <pre>
 &lt;uses-feature android:name="android.hardware.nfc" android:required="true" /&gt;
 </pre>
@@ -660,7 +660,7 @@
 of an application embedded inside an NDEF record. You can add an AAR to any NDEF record of your NDEF message,
 because Android searches the entire NDEF message for AARs. If it finds an AAR, it starts the application based
 on the package name inside the AAR. If the application is not present on the device,
-Android Market is launched to download the application.</p>
+Google Play is launched to download the application.</p>
 
 <p>AARs are useful if you want to prevent other applications from filtering for the same intent and
 potentially handling specific tags that you have deployed. AARs are only supported at the
@@ -678,7 +678,7 @@
   <li>If the Activity that filters for the intent does not match the
 AAR, if multiple Activities can handle the intent, or if no Activity handles the intent, start the
 application specified by the AAR.</li>
-  <li>If no application can start with the AAR, go to the Android Market to download the
+  <li>If no application can start with the AAR, go to Google Play to download the
 application based on the AAR.</li>
 </ol>
 
@@ -897,7 +897,7 @@
 
 <p>Note that this code comments out an AAR, which you can remove. If you enable the AAR, the
 application specified in the AAR always receives the Android Beam message. If the application is not
-present, the Android Market is started to download the application. Therefore, the following intent
+present, Google Play launches to download the application. Therefore, the following intent
 filter is not technically necessary for Android 4.0 devices or later if the AAR is used:
 </p>
 
diff --git a/docs/html/guide/topics/renderscript/graphics.jd b/docs/html/guide/topics/renderscript/graphics.jd
index 1c6d0de..462a990 100644
--- a/docs/html/guide/topics/renderscript/graphics.jd
+++ b/docs/html/guide/topics/renderscript/graphics.jd
@@ -142,7 +142,7 @@
 
       <p class="note"><strong>Note:</strong> The Renderscript runtime makes its best effort to
       refresh the frame at the specified rate. For example, if you are creating a live wallpaper
-      and set the return value to 20, the Renderscript runtime renders the wallpaper at 20fps if it has just
+      and set the return value to 20, the Renderscript runtime renders the wallpaper at 50fps if it has just
       enough or more resources to do so. It renders as fast as it can if not enough resources
       are available.</p>
 
@@ -570,7 +570,7 @@
   vertex 0, 1, and 2 (the vertices are drawn counter-clockwise).</p>
   <pre>
 int float2VtxSize = 2;
-Mesh.TriangleMeshBuilder triangle = new Mesh.TriangleMeshBuilder(renderscriptGL,
+Mesh.TriangleMeshBuilder triangles = new Mesh.TriangleMeshBuilder(renderscriptGL,
 float2VtxSize, Mesh.TriangleMeshBuilder.COLOR);
 triangles.addVertex(300.f, 300.f);
 triangles.addVertex(150.f, 450.f);
diff --git a/docs/html/guide/topics/renderscript/index.jd b/docs/html/guide/topics/renderscript/index.jd
index a0e8876..24b9750 100644
--- a/docs/html/guide/topics/renderscript/index.jd
+++ b/docs/html/guide/topics/renderscript/index.jd
@@ -231,7 +231,8 @@
 
 <p>
 If you want the Renderscript code to send a value back to the Android framework, use the
-<code>rsSendToClient()</code> function.
+<a href="{@docRoot}reference/renderscript/rs__core_8rsh.html"><code>rsSendToClient()</code></a>
+function.
 </p>
 
 <h3 id="var">Variables</h3>
@@ -256,53 +257,6 @@
 }
   </pre>
 
-  <h3 id="pointer">Pointers</h3>
-  <p>Pointers are reflected into the script class itself, located in
-<code>project_root/gen/package/name/ScriptC_renderscript_filename</code>. You
-can declare pointers to a <code>struct</code> or any of the supported Renderscript types, but a
-<code>struct</code> cannot contain pointers or nested arrays. For example, if you declare the
-following pointers to a <code>struct</code> and <code>int32_t</code></p>
-
-<pre>
-typedef struct Point {
-    float2 point;
-} Point_t;
-
-Point_t *touchPoints;
-int32_t *intPointer;
-</pre>
-  <p>then the following code is generated in:</p>
-
-  <pre>
-private ScriptField_Point mExportVar_touchPoints;
-public void bind_touchPoints(ScriptField_Point v) {
-    mExportVar_touchPoints = v;
-    if (v == null) bindAllocation(null, mExportVarIdx_touchPoints);
-    else bindAllocation(v.getAllocation(), mExportVarIdx_touchPoints);
-    }
-
-    public ScriptField_Point get_touchPoints() {
-    return mExportVar_touchPoints;
-    }
-
-    private Allocation mExportVar_intPointer;
-    public void bind_intPointer(Allocation v) {
-    mExportVar_intPointer = v;
-    if (v == null) bindAllocation(null, mExportVarIdx_intPointer);
-    else bindAllocation(v, mExportVarIdx_intPointer);
-    }
-
-    public Allocation get_intPointer() {
-        return mExportVar_intPointer;
-    }
-  </pre>
-
-<p>A <code>get</code> method and a special method named <code>bind_<em>pointer_name</em></code>
-(instead of a <code>set()</code> method) is generated. This method allows you to bind the memory
-that is allocated in the Android VM to the Renderscript runtime (you cannot allocate
-memory in your <code>.rs</code> file). For more information, see <a href="#memory">Working
-with Allocated Memory</a>.
-</p>
 
   <h3 id="struct">Structs</h3>
   <p>Structs are reflected into their own classes, located in
@@ -311,7 +265,8 @@
     specified number of <code>struct</code>s. For example, if you declare the following struct:</p>
 <pre>
 typedef struct Point {
-float2 point;
+    float2 position;
+    float size;
 } Point_t;
 </pre>
 
@@ -478,7 +433,8 @@
       </pre>
 
       <p>If you modify the memory in one memory space and want to push the updates to the rest of
-        the memory spaces, call <code>rsgAllocationSyncAll()</code> in your Renderscript code to
+        the memory spaces, call <a href="{@docRoot}reference/renderscript/rs__graphics_8rsh.html">
+        <code>rsgAllocationSyncAll()</code></a> in your Renderscript code to
         synchronize the memory.</p>
     </li>
 
@@ -511,6 +467,56 @@
 properties that are not yet synchronized.</li>
     </ul>
 
+  <h3 id="pointer">Pointers</h3>
+  <p>Pointers are reflected into the script class itself, located in
+<code>project_root/gen/package/name/ScriptC_renderscript_filename</code>. You
+can declare pointers to a <code>struct</code> or any of the supported Renderscript types, but a
+<code>struct</code> cannot contain pointers or nested arrays. For example, if you declare the
+following pointers to a <code>struct</code> and <code>int32_t</code></p>
+
+<pre>
+typedef struct Point {
+    float2 position;
+    float size;
+} Point_t;
+
+Point_t *touchPoints;
+int32_t *intPointer;
+</pre>
+  <p>then the following code is generated in:</p>
+
+<pre>
+private ScriptField_Point mExportVar_touchPoints;
+public void bind_touchPoints(ScriptField_Point v) {
+    mExportVar_touchPoints = v;
+    if (v == null) bindAllocation(null, mExportVarIdx_touchPoints);
+    else bindAllocation(v.getAllocation(), mExportVarIdx_touchPoints);
+}
+
+public ScriptField_Point get_touchPoints() {
+    return mExportVar_touchPoints;
+}
+
+private Allocation mExportVar_intPointer;
+public void bind_intPointer(Allocation v) {
+    mExportVar_intPointer = v;
+    if (v == null) bindAllocation(null, mExportVarIdx_intPointer);
+    else bindAllocation(v, mExportVarIdx_intPointer);
+}
+
+public Allocation get_intPointer() {
+    return mExportVar_intPointer;
+}
+  </pre>
+
+<p>A <code>get</code> method and a special method named <code>bind_<em>pointer_name</em></code>
+(instead of a <code>set()</code> method) is generated. This method allows you to bind the memory
+that is allocated in the Android VM to the Renderscript runtime (you cannot allocate
+memory in your <code>.rs</code> file). For more information, see <a href="#memory">Working
+with Allocated Memory</a>.
+</p>
+
+
   <h2 id="mem-allocation">Memory Allocation APIs</h2>
 
  <p>Applications that use Renderscript still run in the Android VM. The actual Renderscript code, however, runs natively and
@@ -693,7 +699,8 @@
 that is set from the Android framework is always returned during a call to a <code>get</code>
 method. However, when Android framework code modifies a variable, that change can be communicated to
 the Renderscript runtime automatically or synchronized at a later time. If you need to send data
-from the Renderscript runtime to the Android framework layer, you can use the <code>rsSendToClient()</code> function
+from the Renderscript runtime to the Android framework layer, you can use the
+<a href="{@docRoot}reference/renderscript/rs__core_8rsh.html"><code>rsSendToClient()</code></a> function
 to overcome this limitation.
 </p>
 <p>When working with dynamically allocated memory, any changes at the Renderscript runtime layer are propagated
diff --git a/docs/html/guide/topics/resources/localization.jd b/docs/html/guide/topics/resources/localization.jd
index 9affb15..c2b668d 100755
--- a/docs/html/guide/topics/resources/localization.jd
+++ b/docs/html/guide/topics/resources/localization.jd
@@ -186,7 +186,7 @@
 	and can include other types of resources such as animations. 

 <br>

   <code>&nbsp;&nbsp;&nbsp;&nbsp;res/drawable/</code>(required directory holding at least

-  one graphic file, for the application's icon in the Market)<br>

+  one graphic file, for the application's icon on Google Play)<br>

   <code>&nbsp;&nbsp;&nbsp;&nbsp;res/layout/</code> (required directory holding an XML

   file that defines the default layout)<br>

   <code>&nbsp;&nbsp;&nbsp;&nbsp;res/anim/</code> (required if you have any 

@@ -507,7 +507,7 @@
 

 <h2 id="publishing">Publishing Localized Applications</h2>

 

-<p>The Android Market is

+<p>The Google Play is

   the main application distribution system for Android devices. To publish a 

   localized application, you need to sign your application, version it, and go

 through all the other steps described in <a

@@ -521,7 +521,7 @@
 href="{@docRoot}guide/publishing/app-signing.html#strategies">Signing

 Strategies</a>. </li>

   <li>Give each .apk file a different application name. Currently it is

-impossible to put two applications into the Android Market that have exactly the

+impossible to publish two applications on Google Play that have exactly the

 same name.</li>

 <li>Include a complete set of default resources in each .apk file.</li>

 </ul>

@@ -638,7 +638,7 @@
   <tr>

     <td valign="top" align="center"><img src="../../../images/resources/arrow.png" alt="arrow" width="26"

 border="0"></td>

-    <td>Upload your .apk file or files to Market, selecting the appropriate

+    <td>Upload your .apk file or files to Google Play, selecting the appropriate

 languages as

     you upload. (For more details, see <a

 href="{@docRoot}guide/publishing/publishing.html">Publishing Your

diff --git a/docs/html/guide/topics/sensors/sensors_overview.jd b/docs/html/guide/topics/sensors/sensors_overview.jd
index 3c5e94c..543872c 100644
--- a/docs/html/guide/topics/sensors/sensors_overview.jd
+++ b/docs/html/guide/topics/sensors/sensors_overview.jd
@@ -606,7 +606,7 @@
 that a given sensor is present on a device:</p>
 <ul>
   <li>Detect sensors at runtime and enable or disable application features as appropriate.</li>
-  <li>Use Android Market filters to target devices with specific sensor configurations.</li>
+  <li>Use Google Play filters to target devices with specific sensor configurations.</li>
 </ul>
 
 <p>Each option is discussed in the following sections.</p>
@@ -633,9 +633,9 @@
   }
 </pre>
 
-<h4>Using Android Market filters to target specific sensor configurations</h4>
+<h4>Using Google Play filters to target specific sensor configurations</h4>
 
-<p>If you are publishing your application on Android Market you can use the
+<p>If you are publishing your application on Google Play you can use the
   <a href="{@docRoot}guide//topics/manifest/uses-feature-element.html"><code>&lt;uses-feature&gt;
     </code></a> element in your manifest file to filter your application from devices that do not
 have the appropriate sensor configuration for your application. The
@@ -650,7 +650,7 @@
 </pre>
 
 <p>If you add this element and descriptor to your application's manifest, users will see your
-application on Android Market only if their device has an accelerometer.</p>
+application on Google Play only if their device has an accelerometer.</p>
 
 <p>You should set the descriptor to <code>android:required="true"</code> only if your application
 relies entirely on a specific sensor. If your application uses a sensor for some functionality, but
diff --git a/docs/html/guide/topics/ui/actionbar.jd b/docs/html/guide/topics/ui/actionbar.jd
index e59fa0f..bf7369a 100644
--- a/docs/html/guide/topics/ui/actionbar.jd
+++ b/docs/html/guide/topics/ui/actionbar.jd
@@ -349,7 +349,7 @@
   <li><strong>Frequently used</strong>: It's an action that your users need seven out of ten visits
 or they use it several times in a row.
     <p>Example frequent actions: "New message" in the Messaging app and
-"Search" in Android Market.</p>
+"Search" on Google Play.</p>
   </li>
 
   <li><strong>Important</strong>: It's an action that you need users to easily discover or, if it's
diff --git a/docs/html/guide/topics/usb/adk.jd b/docs/html/guide/topics/usb/adk.jd
index 4d5fbfa..c8949a3 100644
--- a/docs/html/guide/topics/usb/adk.jd
+++ b/docs/html/guide/topics/usb/adk.jd
@@ -97,6 +97,9 @@
       <li><a href="http://www.sparkfun.com/products/10748">
         SparkFun</a></li>
 
+      <li><a href="http://troido.de/de/shoplsmallgbuy-android-stufflsmallg">
+        Troido</a></li>
+
       </ol>
     </div>
   </div>
diff --git a/docs/html/guide/topics/wireless/bluetooth.jd b/docs/html/guide/topics/wireless/bluetooth.jd
index 76da08e..0567799 100644
--- a/docs/html/guide/topics/wireless/bluetooth.jd
+++ b/docs/html/guide/topics/wireless/bluetooth.jd
@@ -249,12 +249,20 @@
 <p>A dialog will appear requesting user permission to enable Bluetooth, as shown
 in Figure 1. If the user responds "Yes," the system will begin to enable Bluetooth
 and focus will return to your application once the process completes (or fails).</p> 
-<p>If enabling Bluetooth succeeds, your Activity will receive the {@link
+
+<p>The {@code REQUEST_ENABLE_BT} constant passed to {@link
+android.app.Activity#startActivityForResult(Intent,int) startActivityForResult()} is a locally
+defined integer (which must be greater than 0), that the system passes back to you in your
+{@link
+android.app.Activity#onActivityResult(int,int,Intent) onActivityResult()} implementation as the
+<code>requestCode</code> parameter.</p>
+
+<p>If enabling Bluetooth succeeds, your activity receives the {@link
 android.app.Activity#RESULT_OK} result code in the {@link
 android.app.Activity#onActivityResult(int,int,Intent) onActivityResult()}
 callback. If Bluetooth was not enabled
-due to an error (or the user responded "No") then the result code will be {@link
-android.app.Activity#RESULT_CANCELED}.</p> 
+due to an error (or the user responded "No") then the result code is {@link
+android.app.Activity#RESULT_CANCELED}.</p>
 </li> 
 </ol> 
  
@@ -431,11 +439,11 @@
  
 <p>A dialog will be displayed, requesting user permission to make the device
 discoverable, as shown in Figure 2. If the user responds "Yes," then the device
-will become discoverable for the specified amount of time. Your Activity will
+will become discoverable for the specified amount of time. Your activity will
 then receive a call to the {@link android.app.Activity#onActivityResult(int,int,Intent)
 onActivityResult())} callback, with the result code equal to the duration that the device
 is discoverable. If the user responded "No" or if an error occurred, the result code will
-be Activity.RESULT_CANCELLED.</p> 
+be {@link android.app.Activity#RESULT_CANCELED}.</p> 
  
 <p class="note"><strong>Note:</strong> If Bluetooth has not been enabled on the device,
 then enabling device discoverability will automatically enable Bluetooth.</p> 
@@ -568,7 +576,7 @@
 </ol> 
  
 <p>The {@link android.bluetooth.BluetoothServerSocket#accept()} call should not
-be executed in the main Activity UI thread because it is a blocking call and
+be executed in the main activity UI thread because it is a blocking call and
 will prevent any other interaction with the application. It usually makes
 sense to do all work with a {@link android.bluetooth.BluetoothServerSocket} or {@link
 android.bluetooth.BluetoothSocket} in a new
@@ -696,7 +704,7 @@
 12 seconds), then it will throw an exception.</p> 
 <p>Because {@link
 android.bluetooth.BluetoothSocket#connect()} is a blocking call, this connection
-procedure should always be performed in a thread separate from the main Activity
+procedure should always be performed in a thread separate from the main activity
 thread.</p> 
 <p class="note">Note: You should always ensure that the device is not performing
 device discovery when you call {@link
@@ -838,7 +846,7 @@
             try {
                 // Read from the InputStream
                 bytes = mmInStream.read(buffer);
-                // Send the obtained bytes to the UI Activity
+                // Send the obtained bytes to the UI activity
                 mHandler.obtainMessage(MESSAGE_READ, bytes, -1, buffer)
                         .sendToTarget();
             } catch (IOException e) {
@@ -847,14 +855,14 @@
         }
     }
  
-    /* Call this from the main Activity to send data to the remote device */
+    /* Call this from the main activity to send data to the remote device */
     public void write(byte[] bytes) {
         try {
             mmOutStream.write(bytes);
         } catch (IOException e) { }
     }
  
-    /* Call this from the main Activity to shutdown the connection */
+    /* Call this from the main activity to shutdown the connection */
     public void cancel() {
         try {
             mmSocket.close();
@@ -866,12 +874,12 @@
 <p>The constructor acquires the necessary streams and once executed, the thread
 will wait for data to come through the InputStream. When {@link
 java.io.InputStream#read(byte[])} returns with
-bytes from the stream, the data is sent to the main Activity using a member
+bytes from the stream, the data is sent to the main activity using a member
 Handler from the parent class. Then it goes back and waits for more bytes from
 the stream.</p> 
  
 <p>Sending outgoing data is as simple as calling the thread's
-<code>write()</code> method from the main Activity and passing in the bytes to
+<code>write()</code> method from the main activity and passing in the bytes to
 be sent. This method then simply calls {@link
 java.io.OutputStream#write(byte[])} to send the data to the remote device.</p> 
  
diff --git a/docs/html/images/home/play_logo.png b/docs/html/images/home/play_logo.png
new file mode 100644
index 0000000..b8e3ebf
--- /dev/null
+++ b/docs/html/images/home/play_logo.png
Binary files differ
diff --git a/docs/html/index.jd b/docs/html/index.jd
index 431a7d2..cfd9ff1 100644
--- a/docs/html/index.jd
+++ b/docs/html/index.jd
@@ -13,14 +13,14 @@
                             <div id="announcement-block">
                             <!-- total max width is 520px -->
                                 <a href="{@docRoot}design/index.html">
-                                  <img src="{@docRoot}images/home/android-design.png"
-alt="Android Design" width="160px" style="padding:10px 33px 5px"/>
+                                  <img src="{@docRoot}images/home/play_logo.png"
+alt="Google Play" width="120px" style="padding:10px 52px"/>
                                 </a>
                                   <div id="announcement" style="width:275px">
-    <p>Introducing <b>Android Design</b>: The place to learn about principles, building blocks, and patterns
-      for creating world-class Android user interfaces. Whether you're a UI professional or a developer
-      playing that role, these docs show you how to make good design decisions, big and small.</p>
-    <p><a href="{@docRoot}design/index.html">Android Design &raquo;</a></p>
+    <p>Introducing <strong>Google Play</strong>: An integrated digital content destination where
+users buy and enjoy all of their favorite content in one place. It's the new destination for
+Android apps!</p>
+    <p><a href="http://android-developers.blogspot.com/2012/03/introducing-google-play.html">Read more &raquo;</a></p>
                                 </div> <!-- end annoucement -->
                             </div> <!-- end annoucement-block -->
                         </div><!-- end topAnnouncement -->
@@ -59,11 +59,11 @@
                                       <td colspan="2"><div class="seperator">&nbsp;</div></td>
                               </tr>
                               <tr>
-                                      <td class="imageCell"><a href="http://market.android.com/publish"><img src="{@docRoot}assets/images/icon_market.jpg" style="padding:0" /></a></td>
+                                      <td class="imageCell"><a href="http://play.google.com/apps/publish"><img src="{@docRoot}assets/images/icon_play.png" style="padding:0" /></a></td>
                                       <td>
                                               <h2 class="green">Publish</h2>
-                                              <p>Android Market is an open service that lets you distribute your apps to handsets.</p>
-                                              <p><a href="http://market.android.com/publish">Learn more &raquo;</a></p>
+                                              <p>Google Play is an open service that lets you distribute your apps to devices.</p>
+                                              <p><a href="http://play.google.com/apps/publish">Learn more &raquo;</a></p>
                                       </td>
                               </tr>
                               <tr>
@@ -182,8 +182,8 @@
       'desc': "<p>Run and debug your Android applications directly on one of these "
  + "devices. Modify and rebuild the Android operating system, and flash it onto "
  + "the phone. The Android Dev Phones are carrier-independent, and available for "
- + "purchase by developers through their Android Market publisher accounts.</p><p> "
- + "<a href='http://market.android.com/publish'>Visit Android Market "
+ + "purchase by developers through their Google Play publisher accounts.</p><p> "
+ + "<a href='http://play.google.com/apps/publish'>Visit Google Play "
  + "to learn more &raquo;</a></p>"
     },
     */
diff --git a/docs/html/intl/ja/community/index.jd b/docs/html/intl/ja/community/index.jd
index 490b23f..9739f0d 100644
--- a/docs/html/intl/ja/community/index.jd
+++ b/docs/html/intl/ja/community/index.jd
@@ -85,7 +85,7 @@
 
 <li><b>Android マーケット ヘルプフォーラム</b> - Android マーケットに関する質問や問題の報告をするための、ウェブベースのディスカッション フォーラムです。
 <ul>
-<li>URL:&nbsp;<a href="http://www.google.com/support/forum/p/Android+Market?hl=ja">http://www.google.com/support/forum/p/Android+Market?hl=ja</a></li>
+<li>URL:&nbsp;<a href="http://support.google.com/googleplay?hl=ja">http://support.google.com/googleplay?hl=ja</a></li>
 </ul>
 </li>
 
diff --git a/docs/html/intl/ja/index.jd b/docs/html/intl/ja/index.jd
index 8096247..fbbd88f 100644
--- a/docs/html/intl/ja/index.jd
+++ b/docs/html/intl/ja/index.jd
@@ -52,11 +52,11 @@
                                       <td colspan="2"><div class="seperator">&nbsp;</div></td>
                               </tr>
                               <tr>
-                                      <td class="imageCell"><a href="http://www.android.com/market.html"><img src="{@docRoot}assets/images/icon_market.jpg" style="padding:0" /></a></td>
+                                      <td class="imageCell"><a href="http://play.google.com/apps/publish"><img src="{@docRoot}assets/images/icon_play.png" style="padding:0" /></a></td>
                                       <td>
                                               <h2 class="green">公開</h2>
                                               <p>Android マーケットは、アプリケーションを携帯端末に配信するためのオープン サービスです。</p>
-                                              <p><a href="http://market.android.com/publish/Home">詳細 &raquo;</a></p>
+                                              <p><a href="http://play.google.com/apps/publish">詳細 &raquo;</a></p>
                                       </td>
                               </tr>
                               <tr>
@@ -148,7 +148,7 @@
       'name':"Dev Phone 1",
       'img':"devphone-large.png",
       'title':"Android Dev Phone 1",
-      'desc': "<p>この携帯電話を使用することで、開発した Android アプリケーションの実行とデバッグを行うことができます。Android オペレーティングシステムを変更してからリビルドし、携帯電話に書き込むことができます。Android Dev Phone 1 は携帯通信会社に依存しておらず、<a href='http://market.android.com/publish'>Android マーケット</a>に登録済みのデベロッパーなら誰でも購入可能です。</p><p><a href='/guide/developing/device.html#dev-phone-1'>Android Dev Phone 1 の詳細&raquo;</a></p>"
+      'desc': "<p>この携帯電話を使用することで、開発した Android アプリケーションの実行とデバッグを行うことができます。Android オペレーティングシステムを変更してからリビルドし、携帯電話に書き込むことができます。Android Dev Phone 1 は携帯通信会社に依存しておらず、<a href='http://play.google.com/apps/publish'>Android マーケット</a>に登録済みのデベロッパーなら誰でも購入可能です。</p><p><a href='/guide/developing/device.html#dev-phone-1'>Android Dev Phone 1 の詳細&raquo;</a></p>"
     }
 
   }
diff --git a/docs/html/intl/ja/resources/community-groups.jd b/docs/html/intl/ja/resources/community-groups.jd
index ecedde1..3fd6601 100644
--- a/docs/html/intl/ja/resources/community-groups.jd
+++ b/docs/html/intl/ja/resources/community-groups.jd
@@ -85,7 +85,7 @@
 
 <li><b>Android マーケット ヘルプフォーラム</b> - Android マーケットに関する質問や問題の報告をするための、ウェブベースのディスカッション フォーラムです。
 <ul>
-<li>URL:&nbsp;<a href="http://www.google.com/support/forum/p/Android+Market?hl=ja">http://www.google.com/support/forum/p/Android+Market?hl=ja</a></li>
+<li>URL:&nbsp;<a href="http://support.google.com/googleplay?hl=ja">http://support.google.com/googleplay?hl=ja</a></li>
 </ul>
 </li>
 
diff --git a/docs/html/resources/articles/can-i-use-this-intent.jd b/docs/html/resources/articles/can-i-use-this-intent.jd
index c527331..7787d31e 100644
--- a/docs/html/resources/articles/can-i-use-this-intent.jd
+++ b/docs/html/resources/articles/can-i-use-this-intent.jd
@@ -68,4 +68,4 @@
 UI accordingly to prevent the user from doing something that won't work. The
 technique described here can also be used at startup time to ask the user
 whether he'd like to install the missing package, you can then simply redirect
-him to the Android Market by using the appropriate URI.</p>
\ No newline at end of file
+him to Google Play by using the appropriate URI.</p>
\ No newline at end of file
diff --git a/docs/html/resources/articles/contacts.jd b/docs/html/resources/articles/contacts.jd
index 8365d29..374587b 100644
--- a/docs/html/resources/articles/contacts.jd
+++ b/docs/html/resources/articles/contacts.jd
@@ -298,10 +298,10 @@
       <li>At launch time, check the version of the SDK. The version of the SDK 
 is available as {@link android.os.Build.VERSION#SDK android.os.Build.VERSION.SDK}.</li>
       <li>If the SDK version is greater or equal to 5 (Android 2.0), show a dialog 
-suggesting to the user that it's time to go to Market and find a new version of 
-the app. You can even provide a link to the new app on Market (see <a 
+suggesting to the user that it's time to go to Google Play and find a new version of 
+the app. You can even provide a link to the new app on Google Play (see <a 
 href="{@docRoot}guide/publishing/publishing.html#marketintent">Using Intents 
-to Launch Market</a>). </li>
+to Launch Google Play</a>). </li>
     </ul>
   <li>Change the new application:</li>
     <ul>
@@ -311,14 +311,14 @@
       <li>Modify that application's AndroidManifest.xml file: </li>
         <ul>
           <li>Give the application a new name and a new package name. Currently 
-Android Market does not allow you to have two applications with the same 
+Google Play does not allow you to have two applications with the same 
 name/package.</li>
           <li>Update (or add) the <code>android:minSdkVersion</code> attribute 
 to the <code>&lt;uses-sdk&gt;</code> element. To use the new Contacts API, 
 you should set the value of the attribute to "5" (or higher, as appropriate).</li>
         </ul>
       </ul>
-    <li>Publish both apps on Market, the old app one as an upgrade and the 
+    <li>Publish both apps on Google Play, the old app one as an upgrade and the 
 other as new. Make sure to explain the difference between the apps in their 
 descriptions.</li>
 </ul>
diff --git a/docs/html/resources/articles/live-wallpapers.jd b/docs/html/resources/articles/live-wallpapers.jd
index bfbbb34..0692a62 100644
--- a/docs/html/resources/articles/live-wallpapers.jd
+++ b/docs/html/resources/articles/live-wallpapers.jd
@@ -76,19 +76,19 @@
 supported only on Android 2.1 (API level 7) and higher versions of the platform.
 To ensure that your application can only be installed on devices that support
 live wallpapers, remember to add the following to the application's manifest
-before publishing to Android Market:</p>
+before publishing to Google Play:</p>
 
 <ul>
 <li><code>&lt;uses-sdk android:minSdkVersion="7" /&gt;</code>, which indicates
-to Android Market and the platform that your application requires Android 2.1 or
+to Google Play and the platform that your application requires Android 2.1 or
 higher. For more information, see the <a href="{@docRoot}guide/appendix/api-levels.html">API
 Levels</a> and the documentation for the
 <a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html"><code>&lt;uses-sdk&gt;</code></a>
 element.</li>
 <li><code>&lt;uses-feature android:name="android.software.live_wallpaper" /&gt;</code>,
-which tells Android Market that your application includes a live wallpaper
-Android Market uses this feature as a filter, when presenting users lists of
-available applications. When you declaring this feature, Android Market
+which tells Google Play that your application includes a live wallpaper
+Google Play uses this feature as a filter, when presenting users lists of
+available applications. When you declaring this feature, Google Play
 displays your application only to users whose devices support live wallpapers,
 while hiding it from other devices on which it would not be able to run. For
 more information, see the documentation for the
@@ -98,5 +98,5 @@
 element.</li>
 </ul>
 
-<p>Many great live wallpapers are already available on Android Market and
+<p>Many great live wallpapers are already available on Google Play and
 we can't wait to see more!</p>
diff --git a/docs/html/resources/articles/speech-input.jd b/docs/html/resources/articles/speech-input.jd
index 0867ff2..2f9cd69 100644
--- a/docs/html/resources/articles/speech-input.jd
+++ b/docs/html/resources/articles/speech-input.jd
@@ -9,7 +9,7 @@
 
 <p>Speech input adds another dimension to staying in touch.
 Google's Voice Search application, which is pre-installed on many Android devices
-and available in Android Market, provides powerful features like "search by voice"
+and available on Google Play, provides powerful features like "search by voice"
 and Voice Actions like "Navigate to." Further
 enhancing the voice experience, Android 2.1 introduces a <a
 href="http://www.youtube.com/watch?v=laOlkD8LmZw">
@@ -21,7 +21,7 @@
 <p> We believe speech can
 fundamentally change the mobile experience. We would like to invite every
 Android application developer to consider integrating speech input capabilities
-via the Android SDK.  One of our favorite apps in the Market that integrates
+via the Android SDK.  One of our favorite apps on Google Play that integrates
 speech input is <a href="http://www.handcent.com/">Handcent SMS</a>, 
 because you can dictate a reply to any SMS with a
 quick tap on the SMS popup window. Here is Speech input integrated into
diff --git a/docs/html/resources/articles/tts.jd b/docs/html/resources/articles/tts.jd
index 7d07a89..929d084 100644
--- a/docs/html/resources/articles/tts.jd
+++ b/docs/html/resources/articles/tts.jd
@@ -43,7 +43,7 @@
 know to install the data that's required for the device to become a
 multi-lingual talking machine! Downloading and installing the data is
 accomplished by firing off the ACTION_INSTALL_TTS_DATA intent, which will take
-the user to Android Market, and will let her/him initiate the download.
+the user to Google Play, and will let her/him initiate the download.
 Installation of the data will happen automatically once the download completes.
 Here is an example of what your implementation of
 <code>onActivityResult()</code> would look like:</p>
diff --git a/docs/html/resources/articles/ui-1.6.jd b/docs/html/resources/articles/ui-1.6.jd
index 09108dd..b3238e3 100644
--- a/docs/html/resources/articles/ui-1.6.jd
+++ b/docs/html/resources/articles/ui-1.6.jd
@@ -129,4 +129,4 @@
 
 <p>The Android team is committed to helping you write applications in the
 easiest and most efficient way possible. We hope you find these improvements
-useful and we're excited to see your applications on Android Market.</p>
+useful and we're excited to see your applications on Google Play.</p>
diff --git a/docs/html/resources/community-groups.jd b/docs/html/resources/community-groups.jd
index 599c4ae..6bd347c 100644
--- a/docs/html/resources/community-groups.jd
+++ b/docs/html/resources/community-groups.jd
@@ -14,7 +14,7 @@
     <li><a href="#UsingEmail">Using email with the mailing lists</a></li>
     <li><a href="#ApplicationDeveloperLists">Application developer mailing lists</a></li>
   </ol></li>
-  <li><a href="#MarketHelp">Android Market Help Forum</a></li>
+  <li><a href="#PlayHelp">Google Play Help Forum</a></li>
   </ol>
 
 </div>
@@ -113,8 +113,8 @@
 </ul>
 
 
-<h2 id="MarketHelp">Android Market Help Forum</h2>
+<h2 id="PlayHelp">Google Play Help Forum</h2>
 
-<p>The <a href="http://www.google.com/support/forum/p/Android+Market">Android Market Help Forum</a> is a web-based discussion forum where you can ask questions or report issues relating to Android Market.</p>
+<p>The <a href="http://support.google.com/googleplay">Google Play Help Forum</a> is a web-based discussion forum where you can ask questions or report issues relating to Google Play.</p>
 
-<p style="margin-left: 2em"><a href="http://www.google.com/support/forum/p/Android+Market">http://www.google.com/support/forum/p/Android+Market</a></p>
+<p style="margin-left: 2em"><a href="http://support.google.com/googleplay">http://support.google.com/googleplay</a></p>
diff --git a/docs/html/resources/dashboard/opengl.jd b/docs/html/resources/dashboard/opengl.jd
index d55ab2b..b1c3234 100644
--- a/docs/html/resources/dashboard/opengl.jd
+++ b/docs/html/resources/dashboard/opengl.jd
@@ -50,14 +50,14 @@
 uses.</p>
 
 <p class="note"><strong>Note:</strong> This data is based on the number
-of Android devices that have accessed Android Market within a 7-day period
+of Android devices that have accessed Google Play within a 7-day period
 ending on the data collection date noted below.</p>
 
 
 <div class="dashboard-panel">
 
 <img alt="" width="400" height="250"
-src="http://chart.googleapis.com/chart?cht=p&chs=400x250&chco=c4df9b,6fad0c&chl=GL%201.1%20only|GL%202.0%20%26%201.1&chd=t%3A10.7,89.3" />
+src="http://chart.googleapis.com/chart?cht=p&chs=400x250&chco=c4df9b,6fad0c&chl=GL%201.1%20only|GL%202.0%20%26%201.1&chd=t%3A10.8,89.2" />
 
 <table>
 <tr>
@@ -66,14 +66,14 @@
 </tr>
 <tr>
 <td>1.1 only</th>
-<td>10.7%</td>
+<td>10.8%</td>
 </tr>
 <tr>
 <td>2.0 &amp; 1.1</th>
-<td>89.3%</td>
+<td>89.2%</td>
 </tr>
 </table>
 
-<p><em>Data collected during a 7-day period ending on February 1, 2012</em></p>
+<p><em>Data collected during a 7-day period ending on March 4, 2012</em></p>
 </div>
 
diff --git a/docs/html/resources/dashboard/platform-versions.jd b/docs/html/resources/dashboard/platform-versions.jd
index 4ea52af..65a5575 100644
--- a/docs/html/resources/dashboard/platform-versions.jd
+++ b/docs/html/resources/dashboard/platform-versions.jd
@@ -47,12 +47,12 @@
 <h3 id="Current">Current Distribution</h3>
 
 <p>The following pie chart and table is based on the number of Android devices that have accessed
-Android Market within a 14-day period ending on the data collection date noted below.</p>
+Google Play within a 14-day period ending on the data collection date noted below.</p>
 
 <div class="dashboard-panel">
 
 <img alt="" height="250" width="470"
-src="http://chart.apis.google.com/chart?&cht=p&chs=460x250&chd=t:0.6,1.0,7.6,27.8,0.5,58.1,0.1,1.4,1.9,0.3,0.7&chl=Android%201.5|Android%201.6|Android%202.1|Android%202.2|Android%202.3|Android%202.3.3|Android%203.0|Android%203.1|Android%203.2|Android%204.0|Android%204.0.3&chco=c4df9b,6fad0c" />
+src="http://chart.apis.google.com/chart?&cht=p&chs=460x250&chd=t:0.4,0.8,6.6,25.2,0.5,61.4,0.1,1.1,2.1,0.4,1.2&chl=Android%201.5|Android%201.6|Android%202.1|Android%202.2|Android%202.3|Android%202.3.3|Android%203.0|Android%203.1|Android%203.2|Android%204.0|Android%204.0.3&chco=c4df9b,6fad0c" />
 
 <table>
 <tr>
@@ -61,25 +61,25 @@
   <th>API Level</th>
   <th>Distribution</th>
 </tr>
-<tr><td><a href="{@docRoot}sdk/android-1.5.html">Android 1.5</a></td><td>Cupcake</td>  <td>3</td><td>0.6%</td></tr>
-<tr><td><a href="{@docRoot}sdk/android-1.6.html">Android 1.6</a></td><td>Donut</td>    <td>4</td><td>1.0%</td></tr>
-<tr><td><a href="{@docRoot}sdk/android-2.1.html">Android 2.1</a></td><td>Eclair</td>   <td>7</td><td>7.6%</td></tr>
-<tr><td><a href="{@docRoot}sdk/android-2.2.html">Android 2.2</a></td><td>Froyo</td>    <td>8</td><td>27.8%</td></tr>
+<tr><td><a href="{@docRoot}sdk/android-1.5.html">Android 1.5</a></td><td>Cupcake</td>  <td>3</td><td>0.4%</td></tr>
+<tr><td><a href="{@docRoot}sdk/android-1.6.html">Android 1.6</a></td><td>Donut</td>    <td>4</td><td>0.8%</td></tr>
+<tr><td><a href="{@docRoot}sdk/android-2.1.html">Android 2.1</a></td><td>Eclair</td>   <td>7</td><td>6.6%</td></tr>
+<tr><td><a href="{@docRoot}sdk/android-2.2.html">Android 2.2</a></td><td>Froyo</td>    <td>8</td><td>25.3%</td></tr>
 <tr><td><a href="{@docRoot}sdk/android-2.3.html">Android 2.3 -<br/>
                              Android 2.3.2</a></td><td rowspan="2">Gingerbread</td>    <td>9</td><td>0.5%</td></tr>
 <tr><td><a href="{@docRoot}sdk/android-2.3.3.html">Android 2.3.3 -<br/>
-      Android 2.3.7</a></td><!-- Gingerbread -->                                       <td>10</td><td>58.1%</td></tr>
+      Android 2.3.7</a></td><!-- Gingerbread -->                                       <td>10</td><td>61.5%</td></tr>
 <tr><td><a href="{@docRoot}sdk/android-3.0.html">Android 3.0</a></td>
                                                    <td rowspan="3">Honeycomb</td>      <td>11</td><td>0.1%</td></tr>
-<tr><td><a href="{@docRoot}sdk/android-3.1.html">Android 3.1</a></td><!-- Honeycomb --><td>12</td><td>1.4%</td></tr>
-<tr><td><a href="{@docRoot}sdk/android-3.2.html">Android 3.2</a></td><!-- Honeycomb --><td>13</td><td>1.9%</td></tr> 
+<tr><td><a href="{@docRoot}sdk/android-3.1.html">Android 3.1</a></td><!-- Honeycomb --><td>12</td><td>1.1%</td></tr>
+<tr><td><a href="{@docRoot}sdk/android-3.2.html">Android 3.2</a></td><!-- Honeycomb --><td>13</td><td>2.1%</td></tr> 
 <tr><td><a href="{@docRoot}sdk/android-4.0.html">Android 4.0 -<br/>
                                                Android 4.0.2</a></td>
-                                                <td rowspan="2">Ice Cream Sandwich</td><td>14</td><td>0.3%</td></tr> 
-<tr><td><a href="{@docRoot}sdk/android-4.0.3.html">Android 4.0.3</a></td><!-- ICS     --><td>15</td><td>0.7%</td></tr> 
+                                                <td rowspan="2">Ice Cream Sandwich</td><td>14</td><td>0.4%</td></tr> 
+<tr><td><a href="{@docRoot}sdk/android-4.0.3.html">Android 4.0.3</a></td><!-- ICS     --><td>15</td><td>1.2%</td></tr> 
 </table>
 
-<p><em>Data collected during a 14-day period ending on February 1, 2012</em></p>
+<p><em>Data collected during a 14-day period ending on March 5, 2012</em></p>
 <!--
 <p style="font-size:.9em">* <em>Other: 0.1% of devices running obsolete versions</em></p>
 -->
@@ -103,14 +103,14 @@
 line for that version meets the y-axis on the right.</p>
 
 <p>Each dataset in the timeline is based on the number of Android devices that accessed
-Android Market within a 14-day period ending on the date indicated on the x-axis.</p>
+Google Play within a 14-day period ending on the date indicated on the x-axis.</p>
 
 <div class="dashboard-panel">
 
 <img alt="" height="250" width="660" style="padding:5px;background:#fff"
-src="http://chart.apis.google.com/chart?&cht=lc&chs=660x250&chxt=x,x,y,r&chxr=0,0,12|1,0,12|2,0,100|3,0,100&chxl=0%3A%7C08/01%7C08/15%7C09/01%7C09/15%7C10/01%7C10/15%7C11/01%7C11/15%7C12/01%7C12/15%7C01/01%7C01/15%7C02/01%7C1%3A%7C2011%7C%7C%7C%7C%7C%7C%7C%7C%7C%7C2012%7C%7C2012%7C2%3A%7C0%25%7C25%25%7C50%25%7C75%25%7C100%25%7C3%3A%7C0%25%7C25%25%7C50%25%7C75%25%7C100%25&chxp=0,0,1,2,3,4,5,6,7,8,9,10,11,12&chxtc=0,5&chd=t:98.2,98.1,97.9,97.9,97.7,97.6,97.5,99.4,99.4,99.2,98.6,98.4,98.5|96.9,96.9,96.9,96.9,96.6,96.6,96.5,98.6,98.6,98.5,98.0,97.8,97.9|94.9,95.0,95.1,95.2,95.1,95.4,95.2,97.2,97.3,97.3,96.9,96.8,96.9|79.6,80.5,81.8,82.7,83.3,84.4,84.6,87.0,87.7,88.1,88.4,88.8,89.2|23.7,26.9,30.6,34.1,37.8,40.8,43.5,48.4,52.4,55.2,57.9,59.7,61.3|0.0,0.0,0.0,0.0,0.0,0.0,0.0,2.0,2.3,2.6,3.2,3.2,3.3|0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0,1.2,1.3,1.7,1.8,1.9&chm=b,c3df9b,0,1,0|b,b6dc7d,1,2,0|tAndroid%202.1,5b831d,2,0,15,,t::-5|b,aadb5e,2,3,0|tAndroid%202.2,496c13,3,0,15,,t::-5|b,9ddb3d,3,4,0|tAndroid%202.3.3,38540b,4,0,15,,t::-5|b,91da1e,4,5,0|b,80c414,5,6,0|B,6fad0c,6,7,0&chg=7,25&chdl=Android%201.5|Android%201.6|Android%202.1|Android%202.2|Android%202.3.3|Android%203.1|Android%203.2&chco=add274,a0d155,94d134,84c323,73ad18,62960f,507d08" />
+src="http://chart.apis.google.com/chart?&cht=lc&chs=660x250&chxt=x,x,y,r&chxr=0,0,12|1,0,12|2,0,100|3,0,100&chxl=0%3A%7C09/01%7C09/15%7C10/01%7C10/15%7C11/01%7C11/15%7C12/01%7C12/15%7C01/01%7C01/15%7C02/01%7C02/15%7C03/01%7C1%3A%7C2011%7C%7C%7C%7C%7C%7C%7C%7C2012%7C%7C%7C%7C2012%7C2%3A%7C0%25%7C25%25%7C50%25%7C75%25%7C100%25%7C3%3A%7C0%25%7C25%25%7C50%25%7C75%25%7C100%25&chxp=0,0,1,2,3,4,5,6,7,8,9,10,11,12&chxtc=0,5&chd=t:97.9,97.9,97.7,97.6,97.5,99.4,99.4,99.2,98.9,98.8,99.2,98.9,98.9|96.9,96.9,96.6,96.6,96.5,98.6,98.6,98.5,98.3,98.2,98.6,98.4,98.4|95.1,95.2,95.1,95.4,95.2,97.2,97.3,97.3,97.2,97.2,97.6,97.5,97.6|81.8,82.7,83.3,84.4,84.6,87.0,87.7,88.1,88.7,89.2,89.9,90.3,90.8|30.6,34.1,37.8,40.8,43.5,48.4,52.4,55.2,58.2,60.1,62.0,63.7,65.2|0.0,0.0,0.0,0.0,0.0,2.0,2.3,2.6,3.5,3.6,4.0,4.1,4.3|0.0,0.0,0.0,0.0,0.0,1.0,1.2,1.3,2.0,2.2,2.6,3.0,3.2|0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.3,0.4,0.7,0.8,1.1&chm=b,c3df9b,0,1,0|b,b8dc82,1,2,0|tAndroid%202.1,608920,2,0,15,,t::-5|b,addb67,2,3,0|tAndroid%202.2,517617,3,0,15,,t::-5|b,a3db4b,3,4,0|tAndroid%202.3.3,426210,4,0,15,,t::-5|b,98dc2e,4,5,0|b,8cd41b,5,6,0|b,7ec113,6,7,0|B,6fad0c,7,8,0&chg=7,25&chdl=Android%201.5|Android%201.6|Android%202.1|Android%202.2|Android%202.3.3|Android%203.1|Android%203.2|Android%204.0.3&chco=add274,a2d15a,97d13e,8bcb28,7dba1e,6ea715,5f920e,507d08" />
 
-<p><em>Last historical dataset collected during a 14-day period ending on February 1, 2012</em></p>
+<p><em>Last historical dataset collected during a 14-day period ending on March 5, 2012</em></p>
 
 
 </div><!-- end dashboard-panel -->
diff --git a/docs/html/resources/dashboard/screens.jd b/docs/html/resources/dashboard/screens.jd
index ae5cdc7..e9c738e 100644
--- a/docs/html/resources/dashboard/screens.jd
+++ b/docs/html/resources/dashboard/screens.jd
@@ -53,14 +53,14 @@
 Screens</a>.</p>
 
 <p class="note"><strong>Note:</strong> This data is based on the number
-of Android devices that have accessed Android Market within a 7-day period
+of Android devices that have accessed Google Play within a 7-day period
 ending on the data collection date noted below.</p>
 
 
 <div class="dashboard-panel">
 
 <img alt="" width="400" height="250"
-src="http://chart.googleapis.com/chart?cht=p&chs=400x250&chco=c4df9b,6fad0c&chl=Xlarge%20/%20mdpi|Large%20/%20ldpi|Large%20/%20mdpi|Normal%20/%20hdpi|Normal%20/%20ldpi|Normal%20/%20mdpi|Normal%20/%20xhdpi|Small%20/%20hdpi|Small%20/%20ldpi&chd=t%3A4.8,0.2,2.9,67.1,0.7,18.4,1.8,2.5,1.6" />
+src="http://chart.googleapis.com/chart?cht=p&chs=400x250&chco=c4df9b,6fad0c&chl=Xlarge%20/%20mdpi|Large%20/%20ldpi|Large%20/%20mdpi|Normal%20/%20hdpi|Normal%20/%20ldpi|Normal%20/%20mdpi|Normal%20/%20xhdpi|Small%20/%20hdpi|Small%20/%20ldpi&chd=t%3A4.9,0.2,2.8,66.4,0.7,18.5,2.5,2.4,1.7" />
 
 <table>
 <tr>
@@ -71,31 +71,31 @@
 <th scope="col">xhdpi</th>
 </tr>
 <tr><th scope="row">small</th> 
-<td>1.6%</td>     <!-- small/ldpi -->
+<td>1.7%</td>     <!-- small/ldpi -->
 <td></td>     <!-- small/mdpi -->
-<td>2.5%</td> <!-- small/hdpi -->
+<td>2.4%</td> <!-- small/hdpi -->
 <td></td>     <!-- small/xhdpi -->
 </tr> 
 <tr><th scope="row">normal</th> 
 <td>0.7%</td>  <!-- normal/ldpi -->
-<td>18.4%</td> <!-- normal/mdpi -->
-<td>67.1%</td> <!-- normal/hdpi -->
-<td>1.8%</td>      <!-- normal/xhdpi -->
+<td>18.5%</td> <!-- normal/mdpi -->
+<td>66.3%</td> <!-- normal/hdpi -->
+<td>2.5%</td>      <!-- normal/xhdpi -->
 </tr> 
 <tr><th scope="row">large</th> 
 <td>0.2%</td>     <!-- large/ldpi -->
-<td>2.9%</td> <!-- large/mdpi -->
+<td>2.8%</td> <!-- large/mdpi -->
 <td></td>     <!-- large/hdpi -->
 <td></td>     <!-- large/xhdpi -->
 </tr> 
 <tr><th scope="row">xlarge</th> 
 <td></td>     <!-- xlarge/ldpi -->
-<td>4.8%</td> <!-- xlarge/mdpi -->
+<td>4.9%</td> <!-- xlarge/mdpi -->
 <td></td>     <!-- xlarge/hdpi -->
 <td></td>     <!-- xlarge/xhdpi -->
 </tr> 
 </table>
 
-<p><em>Data collected during a 7-day period ending on February 1, 2012</em></p>
+<p><em>Data collected during a 7-day period ending on March 4, 2012</em></p>
 </div>
 
diff --git a/docs/html/resources/tutorials/notepad/notepad-ex2.jd b/docs/html/resources/tutorials/notepad/notepad-ex2.jd
index ed06778..1334d7a 100644
--- a/docs/html/resources/tutorials/notepad/notepad-ex2.jd
+++ b/docs/html/resources/tutorials/notepad/notepad-ex2.jd
@@ -87,7 +87,7 @@
     menu callback used for the options menu. Here, we add just one line, which will add a menu item
     to delete a note. Call <code>menu.add()</code> like so:
       <pre>
-public void onCreateContextMenu(Menu menu, View v, ContextMenuInfo menuInfo) {
+public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
     super.onCreateContextMenu(menu, v, menuInfo);
     menu.add(0, DELETE_ID, 0, R.string.menu_delete);
 }</pre>
diff --git a/docs/html/resources/tutorials/views/hello-formstuff.jd b/docs/html/resources/tutorials/views/hello-formstuff.jd
index b9f6c16..1ddd1df 100644
--- a/docs/html/resources/tutorials/views/hello-formstuff.jd
+++ b/docs/html/resources/tutorials/views/hello-formstuff.jd
@@ -91,31 +91,30 @@
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:padding="10dp"
-        android:background="@drawable/android_button" />
+        android:background="@drawable/android_button"
+        android:onClick="onButtonClicked"/>
 </pre>
 	<p>The <code>android:background</code> attribute specifies the drawable resource to use for the
 button background (which, when saved at <code>res/drawable/android.xml</code>, is
 referenced as <code>@drawable/android</code>). This replaces the normal background image
-used for buttons throughout the system. In order for the drawable to change its image based on
-the button state, the image must be applied to the background.</p>
+applied by the system with the drawable created above, which changes its image based on
+the button state.</p>
+    <p>The attribute <code>android:onClick</code> specifies the name of a method in your activity 
+that the system should call when the user clicks the button. You'll create that method next.</p>
 </li>
 
 <li>To make the button do something when pressed, add the following
-code at the end of the {@link android.app.Activity#onCreate(Bundle) onCreate()} method:
+method inside your {@link android.app.Activity} class:
 <pre>
-final Button button = (Button) findViewById(R.id.button);
-button.setOnClickListener(new OnClickListener() {
-    public void onClick(View v) {
-        // Perform action on clicks
-        Toast.makeText(HelloFormStuff.this, "Beep Bop", Toast.LENGTH_SHORT).show();
-    }
-});
+public void onButtonClicked(View v) {
+    // Do something when the button is clicked
+    Toast.makeText(HelloFormStuff.this, "Button clicked", Toast.LENGTH_SHORT).show();
+}
 </pre>
-<p>This captures the {@link android.widget.Button} from the layout, then adds an {@link
-android.view.View.OnClickListener}. The {@link android.view.View.OnClickListener}
-must implement the {@link android.view.View.OnClickListener#onClick(View)} callback method, which
-defines the action to be made when the button is clicked. In this example, a
-{@link android.widget.Toast} message will be displayed.</p>
+<p>When you specify this kind of method, which is used in your layout file with the {@code
+android:onClick} attribute, the method must be <code>public</code>, have a <code>void</code> return
+value, and accept a single {@code android.view.View} parameter. When the system calls this method,
+it passes the {@code android.view.View} that was clicked.</p>
 </li>
 <li>Now run the application.</li>
 </ol>
@@ -183,34 +182,33 @@
     &lt;CheckBox android:id="@+id/checkbox"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:text="check it out" />
+        android:text="check it out"
+        android:onClick="onCheckboxClicked"/>
 </pre>
+    <p>The attribute <code>android:onClick</code> specifies the name of a method in your activity 
+that the system should call when the user clicks the check box. You'll create that method next.</p>
 </li>
-<li>To do something when the state is changed, add the following code
-to the end of the {@link android.app.Activity#onCreate(Bundle) onCreate()} method:
+<li>To do something when the state is changed, add the following method inside your {@link
+android.app.Activity} class:</p>
+
 <pre>
-final CheckBox checkbox = (CheckBox) findViewById(R.id.checkbox);
-checkbox.setOnClickListener(new OnClickListener() {
-    public void onClick(View v) {
-        // Perform action on clicks, depending on whether it's now checked
-        if (((CheckBox) v).isChecked()) {
-            Toast.makeText(HelloFormStuff.this, "Selected", Toast.LENGTH_SHORT).show();
-        } else {
-            Toast.makeText(HelloFormStuff.this, "Not selected", Toast.LENGTH_SHORT).show();
-        }
+public void onCheckboxClicked(View v) {
+    // Perform action on clicks, depending on whether it's now checked
+    if (((CheckBox) v).isChecked()) {
+        Toast.makeText(HelloFormStuff.this, "Selected", Toast.LENGTH_SHORT).show();
+    } else {
+        Toast.makeText(HelloFormStuff.this, "Not selected", Toast.LENGTH_SHORT).show();
     }
-});
+}
 </pre>
-<p>This captures the {@link android.widget.CheckBox} element from the layout, then adds an {@link
-android.view.View.OnClickListener}. The {@link android.view.View.OnClickListener} must implement the
-{@link android.view.View.OnClickListener#onClick(View)} callback method, which
-defines the action to be made when the checkbox is clicked. When clicked, {@link
-android.widget.CompoundButton#isChecked()} is called to check the new state of the check box. If it
-has been checked, then a {@link android.widget.Toast} displays the message "Selected", otherwise it
-displays "Not selected". Note that the {@link android.view.View} object that is passed in the {@link
-android.view.View.OnClickListener#onClick(View)} callback must be cast to a {@link
-android.widget.CheckBox} because the {@link android.widget.CompoundButton#isChecked()} method is
-not defined by the parent {@link android.view.View} class. The {@link android.widget.CheckBox}
+
+<p>When you specify this kind of method, which is used in your layout file with the {@code
+android:onClick}
+attribute, the method must be <code>public</code>, have a <code>void</code> return value, and
+accept a single {@code android.view.View} parameter. When the system calls this method, it
+passes the {@code android.view.View} that was clicked. In this example, the {@code
+android.view.View} is cast to a {@link android.widget.CheckBox} to determine whether the widget
+has been checked or unchecked. The {@link android.widget.CheckBox} widget
 handles its own state changes, so you only need to query the current state.</p>
 </li>
 <li>Run it.</li>
@@ -240,44 +238,44 @@
       &lt;RadioButton android:id="@+id/radio_red"
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"
-          android:text="Red" />
+          android:text="Red"
+          android:onClick="onRadioButtonClicked"/>
       &lt;RadioButton android:id="@+id/radio_blue"
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"
-          android:text="Blue" />
+          android:text="Blue"
+          android:onClick="onRadioButtonClicked"/>
     &lt;/RadioGroup>
 </pre>
 <p>It's important that the {@link android.widget.RadioButton}s are grouped together by the {@link
 android.widget.RadioGroup} element so that no more than one can be selected at a time. This logic
 is automatically handled by the Android system. When one {@link android.widget.RadioButton} within
 a group is selected, all others are automatically deselected.</p>
+    <p>The attribute <code>android:onClick</code> specifies the name of a method in your activity 
+that the system should call when the user clicks the radio button. You'll create that method
+next.</p>
 </li>
 
-<li>To do something when each {@link android.widget.RadioButton} is selected, you need an
-{@link android.view.View.OnClickListener}. In this case, you want the listener to be re-usable, so
-add the following code to create a new member in the <code>HelloFormStuff</code> Activity:
+<li>To do something when each {@link android.widget.RadioButton} is selected, add the following
+method inside your {@link android.app.Activity} class:</p>
+
 <pre>
-private OnClickListener radio_listener = new OnClickListener() {
-    public void onClick(View v) {
-        // Perform action on clicks
-        RadioButton rb = (RadioButton) v;
-        Toast.makeText(HelloFormStuff.this, rb.getText(), Toast.LENGTH_SHORT).show();
-    }
-};
+public void onRadioButtonClicked(View v) {
+    // Perform action on clicks
+    RadioButton rb = (RadioButton) v;
+    Toast.makeText(HelloFormStuff.this, rb.getText(), Toast.LENGTH_SHORT).show();
+}
 </pre>
-<p>First, the {@link android.view.View} that is passed to the {@link
-android.view.View.OnClickListener#onClick(View)} method is cast into a RadioButton. Then a
-{@link android.widget.Toast} message displays the selected radio button's text.</p>
-<li>Now, at the bottom of the {@link android.app.Activity#onCreate(Bundle) onCreate()} method, add
-the following:
-<pre>
-  final RadioButton radio_red = (RadioButton) findViewById(R.id.radio_red);
-  final RadioButton radio_blue = (RadioButton) findViewById(R.id.radio_blue);
-  radio_red.setOnClickListener(radio_listener);
-  radio_blue.setOnClickListener(radio_listener);
-</pre>
-<p>This captures each of the {@link android.widget.RadioButton}s from the layout and adds the
-newly-created {@link android.view.View.OnClickListener} to each.</p>
+
+<p>When you specify this kind of method, which is used in your layout file with the {@code
+android:onClick}
+attribute, the method must be <code>public</code>, have a <code>void</code> return value, and
+accept a single {@code android.view.View} parameter. When the system calls this method, it
+passes the {@code android.view.View} that was clicked.</p>
+<p>Because each {@link android.widget.RadioButton} widget is grouped into a {@link
+android.widget.RadioGroup}, each widget handles its own state changes when a new button is
+selected.</p>
+</li>
 <li>Run the application.</li>
 </ol>
 
@@ -303,31 +301,35 @@
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:textOn="Vibrate on"
-        android:textOff="Vibrate off"/>
+        android:textOff="Vibrate off"
+        android:onClick="onToggleClicked"/>
 </pre>
   <p>The attributes <code>android:textOn</code> and <code>android:textOff</code> specify the text
 for the button when the button has been toggled on or off. The default values are "ON" and
 "OFF".</p>
+    <p>The attribute <code>android:onClick</code> specifies the name of a method in your activity 
+that the system should call when the user clicks the button. You'll create that method next.</p>
 </li>
-<li>To do something when the state is changed, add the following code
-to the end of the {@link android.app.Activity#onCreate(Bundle) onCreate()} method:
+<li>To do something when the user clicks the button, add the following
+method inside your {@link android.app.Activity} class:</p>
+
 <pre>
-final ToggleButton togglebutton = (ToggleButton) findViewById(R.id.togglebutton);
-togglebutton.setOnClickListener(new OnClickListener() {
-    public void onClick(View v) {
-        // Perform action on clicks
-        if (togglebutton.isChecked()) {
-            Toast.makeText(HelloFormStuff.this, "Checked", Toast.LENGTH_SHORT).show();
-        } else {
-            Toast.makeText(HelloFormStuff.this, "Not checked", Toast.LENGTH_SHORT).show();
-        }
+public void onToggleClicked(View v) {
+    // Perform action on clicks
+    if (((ToggleButton) v).isChecked()) {
+        Toast.makeText(HelloFormStuff.this, "Toggle on", Toast.LENGTH_SHORT).show();
+    } else {
+        Toast.makeText(HelloFormStuff.this, "Toggle off", Toast.LENGTH_SHORT).show();
     }
-});
+}
 </pre>
-<p>This captures the {@link android.widget.ToggleButton} element from the layout, then adds an
-{@link android.view.View.OnClickListener}. The {@link android.view.View.OnClickListener} must
-implement the {@link android.view.View.OnClickListener#onClick(View)} callback method, which
-defines the action to perform when the button is clicked. In this example, the callback
+
+<p>When you specify this kind of method, which is used in your layout file with the {@code
+android:onClick}
+attribute, the method must be <code>public</code>, have a <code>void</code> return value, and
+accept a single {@code android.view.View} parameter. When the system calls this method, it
+passes the {@code android.view.View} that was clicked.</p>
+<p>In this example, the callback
 method checks the new state of the button, then shows a {@link android.widget.Toast} message that
 indicates the current state.</p>
 
diff --git a/docs/html/resources/tutorials/views/hello-mapview.jd b/docs/html/resources/tutorials/views/hello-mapview.jd
index ac5e826..7a0bedf 100644
--- a/docs/html/resources/tutorials/views/hello-mapview.jd
+++ b/docs/html/resources/tutorials/views/hello-mapview.jd
@@ -208,7 +208,7 @@
   new class constructor:
 <pre>
 public HelloItemizedOverlay(Drawable defaultMarker, Context context) {
-  super(defaultMarker);
+  super(boundCenterBottom(defaultMarker));
   mContext = context;
 }
 </pre>
diff --git a/docs/html/sdk/android-1.6-highlights.jd b/docs/html/sdk/android-1.6-highlights.jd
index 84766d6..f0a50fb 100644
--- a/docs/html/sdk/android-1.6-highlights.jd
+++ b/docs/html/sdk/android-1.6-highlights.jd
@@ -38,7 +38,7 @@
 
 <ul>
   <li><a href="#UserFeatures">New User Features</a></li>
-  <li><a href="#AndroidMarketUpdates">Android Market Updates</a></li>
+  <li><a href="#GooglePlayUpdates">Google Play Updates</a></li>
   <li><a href="#PlatformTechnologies">New Platform Technologies</a></li>
 </ul>
 
@@ -118,14 +118,14 @@
 
 
 
-<h2 id="AndroidMarketUpdates" style="clear:right">Android Market Updates</h2>
+<h2 id="GooglePlayUpdates" style="clear:right">Google Play Updates</h2>
 
 <div class="screenshot" style="margin-top:-35px">
 <img src="images/market.png" class="screenshot" alt="" /><br/>
-New Android Market UI
+New Google Play UI
 </div>
 
-<p>For devices with Android Market, the latest version improves the overall user experience and makes
+<p>For devices with Google Play, the latest version improves the overall user experience and makes
 it easier for users to discover great apps and games from developers.</p>
 
 <ul>
@@ -157,7 +157,7 @@
 It allows any Android application to "speak" a string of text with an accent that matches the language. 
 The engine supports the following languages: English (American and British accents), French, 
 Italian, German and Spanish. If you're using a T-Mobile G1 or Dream device, you'll need to download the 
-SpeechSynthesis Data Installer from Android Market, which includes the "voices" needed by the 
+SpeechSynthesis Data Installer from Google Play, which includes the "voices" needed by the 
 text-to-speech engine.</p>
 
 
diff --git a/docs/html/sdk/android-2.1.jd b/docs/html/sdk/android-2.1.jd
index 3f28551..1ee833c 100644
--- a/docs/html/sdk/android-2.1.jd
+++ b/docs/html/sdk/android-2.1.jd
@@ -191,7 +191,7 @@
 &lt;uses-feature android:name="android.software.live_wallpaper" />
 </pre>
 
-<p>When you've published your application, Android Market checks for the
+<p>When you've published your application, Google Play checks for the
 presence of this element and uses it as a filter, ensuring that your application
 is not made available to users whose devices do not support Live Wallpapers.
 </p>
diff --git a/docs/html/sdk/android-2.2-highlights.jd b/docs/html/sdk/android-2.2-highlights.jd
index 8bed675..37a20d5 100644
--- a/docs/html/sdk/android-2.2-highlights.jd
+++ b/docs/html/sdk/android-2.2-highlights.jd
@@ -231,7 +231,7 @@
 
 <h3>Android Application Error Reports</h3>
 
-<p>New bug reporting feature for Android Market apps enables developers to receive crash and freeze
+<p>New bug reporting feature for Google Play apps enables developers to receive crash and freeze
 reports from their users. The reports will be available when they log into their publisher
 account.</p>
 
diff --git a/docs/html/sdk/android-2.3.3.jd b/docs/html/sdk/android-2.3.3.jd
index 023e2e4..405c063 100644
--- a/docs/html/sdk/android-2.3.3.jd
+++ b/docs/html/sdk/android-2.3.3.jd
@@ -192,7 +192,7 @@
 declaring <code>&lt;uses-permission
 android:name="android.permission.NFC"&gt;</code> in their manifest files.</p>
 
-<p>Additionally, developers can request filtering on Android Market, such that
+<p>Additionally, developers can request filtering on Google Play, such that
 their applications are not discoverable to users whose devices do not support
 NFC. To request filtering, add
 <code>&lt;uses-feature android:name="android.hardware.nfc"
diff --git a/docs/html/sdk/android-2.3.4.jd b/docs/html/sdk/android-2.3.4.jd
index eeaa69a..4bfdabd 100644
--- a/docs/html/sdk/android-2.3.4.jd
+++ b/docs/html/sdk/android-2.3.4.jd
@@ -197,7 +197,7 @@
 accessories, please see the related <a
 href="{@docRoot}guide/topics/usb/index.html">developer documentation</a>.</p>
 
-<p>Additionally, developers can request filtering on Android Market, such that
+<p>Additionally, developers can request filtering on Google Play, such that
 their applications are not available to users whose devices do not provide the
 appropriate accessory support. To request filtering, add the element below
 to the application manifest:</p>
diff --git a/docs/html/sdk/android-2.3.jd b/docs/html/sdk/android-2.3.jd
index fc4f5aa..b466913 100644
--- a/docs/html/sdk/android-2.3.jd
+++ b/docs/html/sdk/android-2.3.jd
@@ -150,7 +150,7 @@
 android:name="android.permission.INTERNET"&gt;</code> and <code>&lt;uses-permission
 android:name="android.permission.USE_SIP"&gt;</code> in their manifest files.</p>
 
-<p>Additionally, developers can request filtering on Android Market, such that
+<p>Additionally, developers can request filtering on Google Play, such that
 their applications are not discoverable to users whose devices do not include
 the platform’s SIP stack and services. To request filtering, add <code>&lt;uses-feature
 android:name="android.software.sip"
@@ -197,7 +197,7 @@
 declaring <code>&lt;uses-permission
 android:name="android.permission.NFC"&gt;</code> in their manifest files.</p>
 
-<p>Additionally, developers can request filtering on Android Market, such that
+<p>Additionally, developers can request filtering on Google Play, such that
 their applications are not discoverable to users whose devices do not support
 NFC. To request filtering, add
 <code>&lt;uses-feature android:name="android.hardware.nfc"
@@ -219,7 +219,7 @@
 <p>Note that the specific set of hardware sensors available on any given device
 varies at the discretion of the device manufacturer. </p>
 
-<p>Developers can request filtering in Android Market, such that their
+<p>Developers can request filtering on Google Play, such that their
 applications are not discoverable to users whose devices do not offer a
 gyroscope sensor. To do so, add <code>&lt;uses-feature
 android:name="android.hardware.sensor.gyroscope"
@@ -726,7 +726,7 @@
 <p>The platform adds several new hardware features that developers can declare
 in their application manifests as being required by their applications. This
 lets developers control how their application is filtered, when published on
-Android Market. </p>
+Google Play. </p>
 
 <ul>
 <li>{@link android.content.pm.PackageManager#FEATURE_AUDIO_LOW_LATENCY
diff --git a/docs/html/sdk/android-3.0.jd b/docs/html/sdk/android-3.0.jd
index 49fefee..39a234f 100644
--- a/docs/html/sdk/android-3.0.jd
+++ b/docs/html/sdk/android-3.0.jd
@@ -922,7 +922,7 @@
 
 <p>The <a
 href="{@docRoot}guide/topics/manifest/uses-feature-element.html">{@code &lt;uses-feature&gt;}</a> 
-manfest element should be used to inform external entities (such as Android Market) of the set of
+manfest element should be used to inform external entities (such as Google Play) of the set of
 hardware and software features on which your application depends. In this release, Android adds the
 following new constants that applications can declare with this element:</p>
 
diff --git a/docs/html/sdk/android-3.1.jd b/docs/html/sdk/android-3.1.jd
index b9cf969..7ec7e33 100644
--- a/docs/html/sdk/android-3.1.jd
+++ b/docs/html/sdk/android-3.1.jd
@@ -214,7 +214,7 @@
 their manufacturers. In particular, host mode relies on appropriate USB
 controller hardware in the Android-powered device. </p>
 
-<p>Additionally, developers can request filtering on Android Market, such that
+<p>Additionally, developers can request filtering on Google Play, such that
 their applications are not availabe to users whose devices do not provide the
 appropriate USB support. To request filtering, add one or both of the elements
 below to the application manifest, as appropriate: </p>
@@ -908,8 +908,8 @@
 <h3 id="features">New feature constants</h3>
 
 <p>The platform adds new hardware feature constants that developers can declare
-in their application manifests, to inform external entities such as Android
-Market of the application's requirement for new hardware capabilities supported
+in their application manifests, to inform external entities such as Google
+Play of the application's requirement for new hardware capabilities supported
 in this version of the platform. Developers declare these and other feature
 constants in <a
 href="{@docRoot}guide/topics/manifest/uses-feature-element.html">{@code
@@ -926,11 +926,11 @@
 devices.</li>
 </ul>
 
-<p>Android Market filters applications based on features declared in <a
+<p>Google Play filters applications based on features declared in <a
 href="{@docRoot}guide/topics/manifest/uses-feature-element.html">{@code
 &lt;uses-feature&gt;}</a> manifest elements. For more information about
 declaring features in an application manifest, read <a
-href="{@docRoot}guide/appendix/market-filters.html">Android Market
+href="{@docRoot}guide/appendix/market-filters.html">Google Play
 Filters</a>.</p>
 
 
diff --git a/docs/html/sdk/android-3.2.jd b/docs/html/sdk/android-3.2.jd
index aeaf9c8..27df22c 100644
--- a/docs/html/sdk/android-3.2.jd
+++ b/docs/html/sdk/android-3.2.jd
@@ -320,7 +320,7 @@
 from being installed and run.</li>
 </ul>
 
-<p class="note"><strong>Note:</strong> Android Market does not currently filter
+<p class="note"><strong>Note:</strong> Google Play does not currently filter
 apps based on any of the attributes above. Support for filtering will be
 added in a later platform release. Applications that require
 filtering based on screen size can use the existing <code>&lt;supports-screens&gt;</code>
@@ -526,13 +526,13 @@
 <h3 id="features">New feature constants</h3>
 
 <p>The platform adds new hardware feature constants that you can declare
-in their application manifests, to inform external entities such as Android
-Market of required hardware and software capabilities. You declare these
+in their application manifests, to inform external entities such as Google
+Play of required hardware and software capabilities. You declare these
 and other feature constants in <a
 href="{@docRoot}guide/topics/manifest/uses-feature-element.html">{@code
 &lt;uses-feature&gt;}</a> manifest elements.
 
-<p>Android Market filters applications based on their <code>&lt;uses-feature&gt;</code> attributes, to ensure that they are available only to devices on which their requirements are met. </p>
+<p>Google Play filters applications based on their <code>&lt;uses-feature&gt;</code> attributes, to ensure that they are available only to devices on which their requirements are met. </p>
 
 <ul>
 <li>Feature constants for landscape or portrait requirements
diff --git a/docs/html/sdk/android-4.0-highlights.jd b/docs/html/sdk/android-4.0-highlights.jd
index 922bb08..50e9a14 100644
--- a/docs/html/sdk/android-4.0-highlights.jd
+++ b/docs/html/sdk/android-4.0-highlights.jd
@@ -529,7 +529,7 @@
 Just touch one Android-powered phone to another, then tap to send.</p>
 
 <p>For sharing apps, Android Beam pushes a link to the app's details page in
-Android Market. On the other device, the Market app launches and loads the
+Google Play. On the other device, the Google Play client app launches and loads the
 details page, for easy downloading of the app. Individual apps can build on
 Android Beam to add other types of interactions, such as passing game scores,
 initiating a multiplayer game or chat, and more.</p>
@@ -715,7 +715,7 @@
 
 <p>Even if developers do not add custom interactions based on Android Beam they
 can still benefit from it being deeply integrated into Android. By default the
-system shares the app’s Android Market URL, so it’s easy for the user to
+system shares the app’s Google Play URL, so it’s easy for the user to
 download or purchase the app right away.</p>
 
 
diff --git a/docs/html/sdk/android-4.0.jd b/docs/html/sdk/android-4.0.jd
index 2cad86b..e3b13c8 100644
--- a/docs/html/sdk/android-4.0.jd
+++ b/docs/html/sdk/android-4.0.jd
@@ -660,14 +660,14 @@
 application record and multiple applications contain activities that handle the specified intent,
 the system always delivers the message to the activity in your application (based on the matching
 application record). If the target device does not currently have your application installed, the
-system uses the Android application record to launch Android Market and take the user to the
+system uses the Android application record to launch Google Play and take the user to the
 application in order to install it.</p>
 
 <p>If your application doesn’t use NFC APIs to perform NDEF Push messaging, then Android provides a
 default behavior: When your application is in the foreground on one device and Android Beam is
 invoked with another Android-powered device, then the other device receives an NDEF message with an
 Android application record that identifies your application. If the receiving device has the
-application installed, the system launches it; if it’s not installed, Android Market opens and takes
+application installed, the system launches it; if it’s not installed, Google Play opens and takes
 the user to your application in order to install it.</p>
 
 <p>You can read more about Android Beam and other NFC features in the <a
diff --git a/docs/html/sdk/ndk/index.jd b/docs/html/sdk/ndk/index.jd
index 29f0749..a1c59e3 100644
--- a/docs/html/sdk/ndk/index.jd
+++ b/docs/html/sdk/ndk/index.jd
@@ -756,7 +756,7 @@
             <li>Includes improvements to the <code>cpufeatures</code> helper library that improves reporting
             of the CPU type (some devices previously reported ARMv7 CPU when the device really was an ARMv6). We
             recommend developers that use this library to rebuild their applications then
-            upload to Market to benefit from the improvements.</li>
+            upload to Google Play to benefit from the improvements.</li>
 
             <li>Adds an EGL library that lets you create and manage OpenGL ES textures and
               services.</li>
@@ -832,7 +832,7 @@
             <code>.apk</code>.</li>
 
             <li>To ensure that your applications are available to users only if their devices are
-            capable of running them, Android Market now filters applications based on the
+            capable of running them, Google Play now filters applications based on the
             instruction set information included in your application &mdash; no action is needed on
             your part to enable the filtering. Additionally, the Android system itself also checks
             your application at install time and allows the installation to continue only if the
diff --git a/docs/html/sdk/ndk/overview.jd b/docs/html/sdk/ndk/overview.jd
index e969f5d..c98e600 100644
--- a/docs/html/sdk/ndk/overview.jd
+++ b/docs/html/sdk/ndk/overview.jd
@@ -535,7 +535,7 @@
     <li>Additionally, an application using the OpenGL ES APIs should declare a
     <code>&lt;uses-feature&gt;</code> element in its manifest, with an
     <code>android:glEsVersion</code> attribute that specifies the minimum OpenGl ES version
-    required by the application. This ensures that Android Market will show your application only
+    required by the application. This ensures that Google Play will show your application only
     to users whose devices are capable of supporting your application. For example:
       <pre style="margin:1em;">
 &lt;manifest&gt;
diff --git a/docs/html/sdk/oem-usb.jd b/docs/html/sdk/oem-usb.jd
index f98257d..818a0af 100644
--- a/docs/html/sdk/oem-usb.jd
+++ b/docs/html/sdk/oem-usb.jd
@@ -34,7 +34,7 @@
 href="{@docRoot}guide/developing/device.html">Using Hardware Devices</a>.</p>
 
 <p class="note"><strong>Note:</strong> If your device is one of the Android Developer Phones
-(purchased from the Android Market publisher site), a Nexus One, or a Nexus S, then you need
+(ADP), a Nexus One, or a Nexus S, then you need
 the <a href="{@docRoot}sdk/win-usb.html">Google USB Driver</a>, instead of an OEM driver. The Galaxy
 Nexus driver, however, is distributed by <a
 href="http://www.samsung.com/us/support/downloads/verizon-wireless/SCH-I515MSAVZW">Samsung</a>
@@ -211,7 +211,7 @@
 <h2 id="Drivers">OEM Drivers</h2>
 
 <p class="note"><strong>Note:</strong> If your device is one of the Android Developer Phones
-(purchased from the Android Market publisher site), a Nexus One, or a Nexus S, then you need
+(purchased from the Google Play publisher site), a Nexus One, or a Nexus S, then you need
 the <a href="{@docRoot}sdk/win-usb.html">Google USB Driver</a>, instead of an OEM driver. The Galaxy
 Nexus driver, however, is distributed by <a
 href="http://www.samsung.com/us/support/downloads/verizon-wireless/SCH-I515MSAVZW">Samsung</a>
diff --git a/docs/html/sitemap.txt b/docs/html/sitemap.txt
index cfbda2b..958fe56 100644
--- a/docs/html/sitemap.txt
+++ b/docs/html/sitemap.txt
@@ -108,7 +108,7 @@
 http://developer.android.com/guide/topics/testing/contentprovider_testing.html
 http://developer.android.com/guide/topics/testing/service_testing.html
 http://developer.android.com/guide/topics/testing/what_to_test.html
-http://developer.android.com/guide/publishing/licensing.html
+http://developer.android.com/guide/market/licensing/index.html
 http://developer.android.com/guide/market/billing/index.html
 http://developer.android.com/guide/market/billing/billing_about.html
 http://developer.android.com/guide/market/billing/billing_overview.html
diff --git a/docs/html/training/camera/cameradirect.jd b/docs/html/training/camera/cameradirect.jd
index 03ad119..4b6f0d2 100644
--- a/docs/html/training/camera/cameradirect.jd
+++ b/docs/html/training/camera/cameradirect.jd
@@ -35,7 +35,7 @@
 the framework APIs.</p>
 
 <p>Directly controlling a device camera requires a lot more code than requesting pictures or videos
-from existing camera applications. However, if you want to build a specialized camera application or
+from existing camera applications. However, if you want to build a specialized camera application
 or something fully integrated in your app UI, this lesson shows you how.</p>
 
 
@@ -95,7 +95,7 @@
 <p>To get started with displaying a preview, you need preview class. The
 preview requires an implementation of the {@code
 android.view.SurfaceHolder.Callback} interface, which is used to pass image
-data from the camera hardware the application.</p>
+data from the camera hardware to the application.</p>
 
 <pre>
 class Preview extends ViewGroup implements SurfaceHolder.Callback {
@@ -214,7 +214,7 @@
 
 <h2 id="TaskRestartPreview">Restart the Preview</h2>
 
-<p>After a picture is taken, you must to restart the preview before the user
+<p>After a picture is taken, you must restart the preview before the user
 can take another picture. In this example, the restart is done by overloading
 the shutter button.</p>
 
diff --git a/docs/html/training/camera/photobasics.jd b/docs/html/training/camera/photobasics.jd
index e6ab43e..3420918 100644
--- a/docs/html/training/camera/photobasics.jd
+++ b/docs/html/training/camera/photobasics.jd
@@ -55,7 +55,7 @@
 <h2 id="TaskManifest">Request Camera Permission</h2>
 
 <p>If an essential function of your application is taking pictures, then restrict
-its visibility in Android Market to devices that have a camera.  To advertise
+its visibility on Google Play to devices that have a camera.  To advertise
 that your application depends on having a camera, put a <a
 href="{@docRoot}guide/topics/manifest/uses-feature-element.html"> {@code
 &lt;uses-feature&gt;}</a> tag in your manifest file:</p>
@@ -68,7 +68,7 @@
 </pre>
 
 <p>If your application uses, but does not require a camera in order to function, add {@code
-android:required="false"} to the tag. In doing so, Android Market will allow devices without a
+android:required="false"} to the tag. In doing so, Google Play will allow devices without a
 camera to download your application. It's then your responsibility to check for the availability
 of the camera at runtime by calling {@link
 android.content.pm.PackageManager#hasSystemFeature hasSystemFeature(PackageManager.FEATURE_CAMERA)}.
diff --git a/docs/html/training/camera/videobasics.jd b/docs/html/training/camera/videobasics.jd
index a3512b0..5fe1a3a 100644
--- a/docs/html/training/camera/videobasics.jd
+++ b/docs/html/training/camera/videobasics.jd
@@ -62,7 +62,7 @@
 </pre>
 
 <p>If your application uses, but does not require a camera in order to function, add {@code
-android:required="false"} to the tag. In doing so, Android Market will allow devices without a
+android:required="false"} to the tag. In doing so, Google Play will allow devices without a
 camera to download your application. It's then your responsibility to check for the availability
 of the camera at runtime by calling {@link
 android.content.pm.PackageManager#hasSystemFeature hasSystemFeature(PackageManager.FEATURE_CAMERA)}.
@@ -107,7 +107,7 @@
 <p>The Android Camera application returns the video in the {@link android.content.Intent} delivered
 to {@link android.app.Activity#onActivityResult onActivityResult()} as a {@link
 android.net.Uri} pointing to the video location in storage. The following code
-retrieves this image and displays it in a {@link android.widget.VideoView}.</p>
+retrieves this video and displays it in a {@link android.widget.VideoView}.</p>
 
 <pre>
 private void handleCameraVideo(Intent intent) {
diff --git a/docs/html/training/id-auth/custom_auth.jd b/docs/html/training/id-auth/custom_auth.jd
index e2bd778..0509c6e 100644
--- a/docs/html/training/id-auth/custom_auth.jd
+++ b/docs/html/training/id-auth/custom_auth.jd
@@ -181,6 +181,6 @@
 <p>One solution is to place the service in one small, special-purpose APK. When
 an app wishes to use your custom account type, it can check the device to see if
 your custom account service is available. If not, it can direct the user to
-Android Market to download the service. This may seem like a great deal of
+Google Play to download the service. This may seem like a great deal of
 trouble at first, but compared with the alternative of re-entering credentials
 for every app that uses your custom account, it's refreshingly easy.</p>
diff --git a/docs/html/training/multiple-apks/api.jd b/docs/html/training/multiple-apks/api.jd
index d8588d4..8b731bd 100644
--- a/docs/html/training/multiple-apks/api.jd
+++ b/docs/html/training/multiple-apks/api.jd
@@ -44,7 +44,7 @@
 </div>
 
 
-<p>When developing your Android application to take advantage of multiple APKs on Android Market,
+<p>When developing your Android application to take advantage of multiple APKs on Google Play,
 it’s important to adopt some good practices from the get-go, and prevent unnecessary headaches
 further into the development process.  This lesson shows you how to create multiple APKs of your
 app, each covering a slightly different range of API levels.  You will also gain some tools
@@ -198,7 +198,7 @@
 
 
 <h2 id="AdjustManifests">Adjust the Manifests</h2>
-<p>When a user downloads an application which uses multiple APKs through Android Market, the correct
+<p>When a user downloads an application which uses multiple APKs through Google Play, the correct
 APK to use is chosen using two simple rules:</p>
 <ul>
 <li>The manifest has to show that particular APK is eligible</li>
@@ -278,19 +278,20 @@
 </table>
 
 <p>
-Now, let’s further assume that the Red APK has some requirement on it that the other two don’t.  The
-Market Filters page of the Android Developer guide has a whole list of possible culprits.  For the
+Now, let’s further assume that the Red APK has some requirement on it that the other two don’t.  
+<a href="{@docRoot}guide/appendix/market-filters.html">Filters on Google Play</a> page of
+the Android Developer guide has a whole list of possible culprits.  For the
 sake of example, let’s assume that red requires a front-facing camera.  In fact, the entire point of
 the red APK is to combine the front-facing camera with sweet new functionality that was added in API
 11.  But, it turns out, not all devices that support API 11 even HAVE front-facing cameras!  The
 horror!</p>
 
-<p>Fortunately, if a user is browsing Market from one such device, Android Market will look at the
+<p>Fortunately, if a user is browsing Google Play from one such device, Google Play will look at the
 manifest, see that Red lists the front-facing camera as a requirement, and quietly ignore it, having
 determined that Red and that device are not a match made in digital heaven.  It will then see that
 Green is not only forward-compatible with devices with API 11 (since no maxSdkVersion was defined),
 but also doesn’t care whether or not there’s a front-facing camera!  The app can still be downloaded
-from Android Market by the user, because despite the whole front-camera mishap, there was still an
+from Google Play by the user, because despite the whole front-camera mishap, there was still an
 APK that supported that particular API level.</p>
 
 <p>  In order to keep all your APKs on separate "tracks", it’s important to have a good version code
@@ -330,7 +331,7 @@
 </pre>
 
 <h2 id="PreLaunch">Go Over Pre-launch Checklist</h2>
-<p>  Before uploading to Android Market, double-check the following items.  Remember that these are specifically relevant to multiple APKs, and in no way represent a complete checklist for all applications being uploaded to Android Market.</p>
+<p>  Before uploading to Google Play, double-check the following items.  Remember that these are specifically relevant to multiple APKs, and in no way represent a complete checklist for all applications being uploaded to Google Play.</p>
 
 <ul>
 <li>All APKs must have the same package name</li>
@@ -342,7 +343,7 @@
 </ul>
 
 <p>It’s also worth inspecting the compiled APK before pushing to market, to make sure there aren’t
-any surprises that could hide your application in Market.  This is actually quite simple using the
+any surprises that could hide your application on Google Play.  This is actually quite simple using the
 "aapt" tool.  Aapt (the Android Asset Packaging Tool) is part of the build process for creating and
 packaging your Android applications, and is also a very handy tool for inspecting them. </p>
 
@@ -370,10 +371,10 @@
 supports-screens and compatible-screens, and that you don’t have unintended "uses-feature" values
 that were added as a result of permissions you set in the manifest. In the example above, the APK
 won’t be visible to very many devices.</p>
-<p>Why?  By adding the required permission SEND_SMS, the feature requirement of android.hardware.telephony was implicitly added.  Since API 11 is Honeycomb (the version of Android optimized specifically for tablets), and no Honeycomb devices have telephony hardware in them, Market will filter out this APK in all cases, until future devices come along which are higher in API level AND possess telephony hardware.
+<p>Why?  By adding the required permission SEND_SMS, the feature requirement of android.hardware.telephony was implicitly added.  Since API 11 is Honeycomb (the version of Android optimized specifically for tablets), and no Honeycomb devices have telephony hardware in them, Google Play will filter out this APK in all cases, until future devices come along which are higher in API level AND possess telephony hardware.
 </p>
 <p>Fortunately this is easily fixed by adding the following to your manifest:</p>
 <pre>
 &lt;uses-feature android:name="android.hardware.telephony" android:required="false" /&gt;
 </pre>
-<p>Once you’ve completed the pre-launch checklist, upload your APKs to Android Market.  It may take a bit for the application to show up when browsing Android Market, but when it does, perform one last check.  Download the application onto any test devices you may have, to make sure that the APKs are targeting the intended devices.  Congratulations, you’re done!</p>
+<p>Once you’ve completed the pre-launch checklist, upload your APKs to Google Play.  It may take a bit for the application to show up when browsing Google Play, but when it does, perform one last check.  Download the application onto any test devices you may have, to make sure that the APKs are targeting the intended devices.  Congratulations, you’re done!</p>
diff --git a/docs/html/training/multiple-apks/index.jd b/docs/html/training/multiple-apks/index.jd
index f9b2b43..d92c106 100644
--- a/docs/html/training/multiple-apks/index.jd
+++ b/docs/html/training/multiple-apks/index.jd
@@ -16,7 +16,7 @@
 
 <ul>
   <li>Android 1.0 and higher</li>
-  <li>You must have an <a href="http://market.android.com/publish">Android Market</a> publisher
+  <li>You must have an <a href="http://play.google.com/apps/publish">Google Play</a> publisher
 account</li>
 </ul>
 
@@ -30,7 +30,7 @@
 </div>
 </div>
 
-<p>Multiple APK support is a feature in Android Market that allows you to publish multiple APKs
+<p>Multiple APK support is a feature of Google Play that allows you to publish multiple APKs
 under the same application listing.  Each APK is a complete instance of your application, optimized
 to target specific device configurations.  Each APK can target a specific set of GL
 textures, API levels, screen sizes, or some combination thereof.</p>
@@ -39,7 +39,7 @@
 configuration variables.  Each lesson covers basics about how to organize your codebase and target
 the right devices, as well as the smart way to avoid pitfalls such as unnecessary redundancy across
 your codebase, and making mistakes in your manifest that could render an APK invisible to all
-devices in Android Market.  By going through any of these lessons, you'll know how to develop
+devices on Google Play.  By going through any of these lessons, you'll know how to develop
 multiple APKs the smart way, make sure they're targeting the devices you want them to,
 and know how to catch mistakes <em>before</em> your app goes live.</p>
 
diff --git a/docs/html/training/multiple-apks/multiple.jd b/docs/html/training/multiple-apks/multiple.jd
index 26a3a93..0c49705 100644
--- a/docs/html/training/multiple-apks/multiple.jd
+++ b/docs/html/training/multiple-apks/multiple.jd
@@ -40,7 +40,7 @@
 </div>
 </div>
 
-<p>When developing your Android application to take advantage of multiple APKs on Android Market,
+<p>When developing your Android application to take advantage of multiple APKs on Google Play,
 it’s important to adopt some good practices from the get-go, and prevent unnecessary headaches
 further into the development process.  This lesson shows you how to create multiple APKs of your
 app, each covering a different class of screen size.  You will also gain some tools necessary to
@@ -227,7 +227,7 @@
 
 
 <h2 id="AdjustManifests">Adjust the Manifests</h2>
-<p>When a user downloads an application which uses multiple APKs through Android Market, the correct
+<p>When a user downloads an application which uses multiple APKs through Google Play, the correct
 APK to use is chosen using two simple rules:
 
 <ul>
@@ -329,17 +329,17 @@
 Purple &#8805; Red &#8805; Green &#8805; Blue
 </p><p>
 Why allow all the overlap?  Let’s pretend that the Purple APK has some requirement on it that the
-other two don’t.  The <a href="{@docRoot}guide/appendix/market-filters.html">Market Filters page</a>
+other two don’t.  The <a href="{@docRoot}guide/appendix/market-filters.html">Filters on Google Play</a> page
 of the Android Developer guide has a whole list of possible culprits.  For the sake of example,
 let’s assume that Purple requires a front-facing camera.  In fact, the entire point of Purple is to
 use entertaining things with the front-facing camera!  But, it turns out, not all API 11+ devices
 even HAVE front-facing cameras!  The horror!</p>
 
-<p>Fortunately, if a user is browsing Market from one such device, Android Market will look at the
+<p>Fortunately, if a user is browsing Google Play from one such device, Google Play will look at the
 manifest, see that Purple lists the front-facing camera as a requirement, and quietly ignore it,
 having determined that Purple and that device are not a match made in digital heaven.  It will then
 see that Red is not only compatible with xlarge devices, but also doesn’t care whether or not
-there’s a front-facing camera!  The app can still be downloaded from Android Market by the user,
+there’s a front-facing camera!  The app can still be downloaded from Google Play by the user,
 because despite the whole front-camera mishap, there was still an APK that supported that particular
 API level.</p>
 
@@ -420,9 +420,9 @@
 </p>
 
 <h2 id="PreLaunch">Go Over Pre-launch Checklist</h2>
-<p>  Before uploading to Android Market, double-check the following items.  Remember that these are
+<p>  Before uploading to Google Play, double-check the following items.  Remember that these are
 specifically relevant to multiple APKs, and in no way represent a complete checklist for all
-applications being uploaded to Android Market.</p>
+applications being uploaded to Google Play.</p>
 <ul>
 <li>All APKs must have the same package name.</li>
 <li>All APKs must be signed with the same certificate.</li>
@@ -439,7 +439,7 @@
 </ul>
 
 <p>It’s also worth inspecting the compiled APK before pushing to market, to make sure there aren’t
-any surprises that could hide your application in Market.  This is actually quite simple using the
+any surprises that could hide your application on Google Play.  This is actually quite simple using the
 "aapt" tool.  Aapt (the Android Asset Packaging Tool) is part of the build process for creating and
 packaging your Android applications, and is also a very handy tool for inspecting them. </p>
 
@@ -467,11 +467,11 @@
 supports-screens and compatible-screens, and that you don’t have unintended "uses-feature" values
 that were added as a result of permissions you set in the manifest. In the example above, the APK
 will be invisible to most, if not all devices.</p>
-<p>Why?  By adding the required permission SEND_SMS, the feature requirement of android.hardware.telephony was implicitly added.  Since most (if not all) xlarge devices are tablets without telephony hardware in them, Market will filter out this APK in these cases, until future devices come along which are both large enough to report as xlarge screen size, and possess telephony hardware.
+<p>Why?  By adding the required permission SEND_SMS, the feature requirement of android.hardware.telephony was implicitly added.  Since most (if not all) xlarge devices are tablets without telephony hardware in them, Google Play will filter out this APK in these cases, until future devices come along which are both large enough to report as xlarge screen size, and possess telephony hardware.
 </p>
 <p>Fortunately this is easily fixed by adding the following to your manifest:<p>
 <pre>
 &lt;uses-feature android:name="android.hardware.telephony" android:required="false" /&gt;
 </pre>
 
-<p>Once you’ve completed the pre-launch checklist, upload your APKs to Android Market.  It may take a bit for the application to show up when browsing Android Market, but when it does, perform one last check.  Download the application onto any test devices you may have to make sure that the APKs are targeting the intended devices. Congratulations, you’re done!</p>
+<p>Once you’ve completed the pre-launch checklist, upload your APKs to Google Play.  It may take a bit for the application to show up when browsing Google Play, but when it does, perform one last check.  Download the application onto any test devices you may have to make sure that the APKs are targeting the intended devices. Congratulations, you’re done!</p>
diff --git a/docs/html/training/multiple-apks/screensize.jd b/docs/html/training/multiple-apks/screensize.jd
index 0ed972a..cbf17c5 100644
--- a/docs/html/training/multiple-apks/screensize.jd
+++ b/docs/html/training/multiple-apks/screensize.jd
@@ -43,7 +43,7 @@
 </div>
 
 
-<p>When developing your Android application to take advantage of multiple APKs on Android Market,
+<p>When developing your Android application to take advantage of multiple APKs on Google Play,
 it’s important to adopt some good practices from the get-go, and prevent unnecessary headaches
 further into the development process.  This lesson shows you how to create multiple APKs of your
 app, each covering a different class of screen size.  You will also gain some tools necessary to
@@ -178,7 +178,7 @@
 
 
 <h2 id="AdjustManifests">Adjust the Manifests</h2>
-<p>When a user downloads an application which uses multiple APKs through Android Market, the correct
+<p>When a user downloads an application which uses multiple APKs through Google Play, the correct
 APK to use is chosen using two simple rules:</p>
 <ul>
 <li>The manifest has to show that particular APK is eligible</li>
@@ -227,17 +227,17 @@
 </table>
 <p>
 Now, let’s further assume that the Red APK has some requirement on it that the other two don’t.  The
-<a href="{@docRoot}guide/appendix/market-filters.html">Market Filters page</a> of the Android
+<a href="{@docRoot}guide/appendix/market-filters.html">Filters on Google Play</a> page of the Android
 Developer guide has a whole list of possible culprits.  For the sake of example, let’s assume that
 red requires a front-facing camera.  In fact, the entire point of the red APK is to use the extra
 available screen space to do entertaining things with that front-facing camera.  But, it turns out,
 not all xlarge devices even HAVE front-facing cameras!  The horror!</p>
 
-<p>Fortunately, if a user is browsing Market from one such device, Android Market will look at the
+<p>Fortunately, if a user is browsing Google Play from one such device, Google Play will look at the
 manifest, see that Red lists the front-facing camera as a requirement, and quietly ignore it, having
 determined that Red and that device are not a match made in digital heaven.  It will then see that
 Green is not only compatible with xlarge devices, but also doesn’t care whether or not there’s a
-front-facing camera!  The app can still be downloaded from Android Market by the user, because
+front-facing camera!  The app can still be downloaded from Google Play by the user, because
 despite the whole front-camera mishap, there was still an APK that supported that particular screen
 size.</p>
 
@@ -300,9 +300,9 @@
 </p>
 
 <h2 id="PreLaunch">Go Over Pre-launch Checklist</h2>
-<p>  Before uploading to Android Market, double-check the following items.  Remember that these are
+<p>  Before uploading to Google Play, double-check the following items.  Remember that these are
 specifically relevant to multiple APKs, and in no way represent a complete checklist for all
-applications being uploaded to Android Market.</p>
+applications being uploaded to Google Play.</p>
 <ul>
 <li>All APKs must have the same package name</li>
 <li>All APKs must be signed with the same certificate</li>
@@ -317,7 +317,7 @@
 </ul>
 
 <p>It’s also worth inspecting the compiled APK before pushing to market, to make sure there aren’t
-any surprises that could hide your application in Market.  This is actually quite simple using the
+any surprises that could hide your application on Google Play.  This is actually quite simple using the
 "aapt" tool.  Aapt (the Android Asset Packaging Tool) is part of the build process for creating and
 packaging your Android applications, and is also a very handy tool for inspecting them. </p>
 
@@ -345,11 +345,11 @@
 supports-screens and compatible-screens, and that you don’t have unintended "uses-feature" values
 that were added as a result of permissions you set in the manifest. In the example above, the APK
 will be invisible to most, if not all devices.</p>
-<p>Why?  By adding the required permission SEND_SMS, the feature requirement of android.hardware.telephony was implicitly added.  Since most (if not all) xlarge devices are tablets without telephony hardware in them, Market will filter out this APK in these cases, until future devices come along which are both large enough to report as xlarge screen size, and possess telephony hardware.
+<p>Why?  By adding the required permission SEND_SMS, the feature requirement of android.hardware.telephony was implicitly added.  Since most (if not all) xlarge devices are tablets without telephony hardware in them, Google Play will filter out this APK in these cases, until future devices come along which are both large enough to report as xlarge screen size, and possess telephony hardware.
 </p>
 <p>Fortunately this is easily fixed by adding the following to your
 manifest:</p>
 <pre>
 &lt;uses-feature android:name="android.hardware.telephony" android:required="false" /&gt;
 </pre>
-<p>Once you’ve completed the pre-launch checklist, upload your APKs to Android Market.  It may take a bit for the application to show up when browsing Android Market, but when it does, perform one last check.  Download the application onto any test devices you may have to make sure that the APKs are targeting the intended devices. Congratulations, you’re done!</p>
+<p>Once you’ve completed the pre-launch checklist, upload your APKs to Google Play.  It may take a bit for the application to show up when browsing Google Play, but when it does, perform one last check.  Download the application onto any test devices you may have to make sure that the APKs are targeting the intended devices. Congratulations, you’re done!</p>
diff --git a/docs/html/training/multiple-apks/texture.jd b/docs/html/training/multiple-apks/texture.jd
index 2bbe511..0dbee61 100644
--- a/docs/html/training/multiple-apks/texture.jd
+++ b/docs/html/training/multiple-apks/texture.jd
@@ -40,7 +40,7 @@
 </div>
 </div>
 
-<p>When developing your Android application to take advantage of multiple APKs on Android Market, it’s important to adopt some good practices from the get-go, and prevent unnecessary headaches further into the development process.  This lesson shows you how to create multiple APKs of your app, each supporting a different subset of OpenGL texture formats.  You will also gain some tools necessary to make maintaining a multiple APK codebase as painless as possible.</p>
+<p>When developing your Android application to take advantage of multiple APKs on Google Play, it’s important to adopt some good practices from the get-go, and prevent unnecessary headaches further into the development process.  This lesson shows you how to create multiple APKs of your app, each supporting a different subset of OpenGL texture formats.  You will also gain some tools necessary to make maintaining a multiple APK codebase as painless as possible.</p>
 
 
 <h2 id="Confirm">Confirm You Need Multiple APKs</h2>
@@ -158,7 +158,7 @@
 
 
 <h2 id="AdjustManifests">Adjust the Manifests</h2>
-<p>When a user downloads an application which uses multiple APKs through Android Market, the correct
+<p>When a user downloads an application which uses multiple APKs through Google Play, the correct
 APK to use is chosen using some simple rules:</p>
 
 <ul>
@@ -246,9 +246,9 @@
 </pre>
 
 <h2 id="PreLaunch">Go Over Pre-launch Checklist</h2>
-<p>Before uploading to Android Market, double-check the following items.  Remember that these are
+<p>Before uploading to Google Play, double-check the following items.  Remember that these are
 specifically relevant to multiple APKs, and in no way represent a complete checklist for all
-applications being uploaded to Android Market.</p>
+applications being uploaded to Google Play.</p>
 
 <ul>
 <li>All APKs must have the same package name</li>
@@ -262,7 +262,7 @@
 </ul>
 
 <p>It’s also worth inspecting the compiled APK before pushing to market, to make sure there aren’t
-any surprises that could hide your application in Market.  This is actually quite simple using the
+any surprises that could hide your application on Google Play.  This is actually quite simple using the
 "aapt" tool.  Aapt (the Android Asset Packaging Tool) is part of the build process for creating and
 packaging your Android applications, and is also a very handy tool for inspecting them. </p>
 
@@ -290,10 +290,10 @@
 supports-screens and compatible-screens, and that you don’t have unintended "uses-feature" values
 that were added as a result of permissions you set in the manifest. In the example above, the APK
 will be invisible to most, if not all devices.</p>
-<p>Why?  By adding the required permission SEND_SMS, the feature requirement of android.hardware.telephony was implicitly added.  Since most (if not all) xlarge devices are tablets without telephony hardware in them, Market will filter out this APK in these cases, until future devices come along which are both large enough to report as xlarge screen size, and possess telephony hardware.  
+<p>Why?  By adding the required permission SEND_SMS, the feature requirement of android.hardware.telephony was implicitly added.  Since most (if not all) xlarge devices are tablets without telephony hardware in them, Google Play will filter out this APK in these cases, until future devices come along which are both large enough to report as xlarge screen size, and possess telephony hardware.  
 </p>
 <p>Fortunately this is easily fixed by adding the following to your manifest:</p>
 <pre>
 &lt;uses-feature android:name="android.hardware.telephony" android:required="false" /&gt;
 </pre>
-<p>Once you’ve completed the pre-launch checklist, upload your APKs to Android Market.  It may take a bit for the application to show up when browsing Android Market, but when it does, perform one last check.  Download the application onto any test devices you may have to make sure that the APKs are targeting the intended devices. Congratulations, you’re done!</p>
+<p>Once you’ve completed the pre-launch checklist, upload your APKs to Google Play.  It may take a bit for the application to show up when browsing Google Play, but when it does, perform one last check.  Download the application onto any test devices you may have to make sure that the APKs are targeting the intended devices. Congratulations, you’re done!</p>
diff --git a/docs/html/training/sharing/receive.jd b/docs/html/training/sharing/receive.jd
index cc55967..a0a5bc8 100644
--- a/docs/html/training/sharing/receive.jd
+++ b/docs/html/training/sharing/receive.jd
@@ -34,7 +34,7 @@
 from applications. Think about how users interact with your application, and what data types you 
 want to receive from other applications. For example, a social networking application would likely 
 be interested in receiving text content, like an interesting web URL, from another app. The 
-<a href="https://market.android.com/details?id=com.google.android.apps.plus">Google+ Android
+<a href="https://play.google.com/store/details?id=com.google.android.apps.plus">Google+ Android
 application</a> 
 accepts both text <em>and</em> single or multiple images. With this app, a user can easily start a 
 new Google+ post with photos from the Android Gallery app.</p>
diff --git a/drm/java/android/drm/DrmConvertedStatus.java b/drm/java/android/drm/DrmConvertedStatus.java
index cecb135..f6e570a 100755
--- a/drm/java/android/drm/DrmConvertedStatus.java
+++ b/drm/java/android/drm/DrmConvertedStatus.java
@@ -18,36 +18,67 @@
 
 /**
  * An entity class that wraps converted data, conversion status, and the
- * offset for appending the header and body signature to the converted data. An instance of this
- * class is returned by the {@link DrmManagerClient#convertData convertData()} and
- * {@link DrmManagerClient#closeConvertSession closeConvertSession()} methods. The offset is provided only when a
- * conversion session is closed by calling {@link DrmManagerClient#closeConvertSession closeConvertSession()}.
+ * offset for appending the header and body signature to the converted data.
+ * An instance of this class may be created two ways by the drm framework:
+ * a) a call to {@link DrmManagerClient#convertData DrmManagerClient.convertData()} and
+ * b) a call to {@link DrmManagerClient#closeConvertSession DrmManagerClient.closeConvertSession()}.
+ * An valid offset value is provided only from a success call to
+ * {@link DrmManagerClient#closeConvertSession DrmManagerClient.closeConvertSession()}.
  *
  */
 public class DrmConvertedStatus {
-    // Should be in sync with DrmConvertedStatus.cpp
+    // The following status code constants must be in sync with
+    // DrmConvertedStatus.cpp. Please also update isValidStatusCode()
+    // when more status code constants are added.
+    /**
+     * Indicate the conversion status is successful.
+     */
     public static final int STATUS_OK = 1;
+    /**
+     * Indicate a failed conversion status due to input data.
+     */
     public static final int STATUS_INPUTDATA_ERROR = 2;
+    /**
+     * Indicate a general failed conversion status.
+     */
     public static final int STATUS_ERROR = 3;
 
-    /** Status code for the conversion.*/
+    /**
+     * Status code for the conversion. Must be one of the defined status
+     * constants above.
+     */
     public final int statusCode;
-    /** Converted data.*/
+    /**
+     * Converted data. It is optional and thus can be null.
+     */
     public final byte[] convertedData;
-    /** Offset value for the body and header signature.*/
+    /**
+     * Offset value for the body and header signature.
+     */
     public final int offset;
 
     /**
      * Creates a <code>DrmConvertedStatus</code> object with the specified parameters.
      *
-     * @param _statusCode Conversion status.
-     * @param _convertedData Converted data.
-     * @param _offset Offset value for appending the header and body signature.
+     * @param statusCode Conversion status. Must be one of the status code constants
+     * defined above.
+     * @param convertedData Converted data. It can be null.
+     * @param offset Offset value for appending the header and body signature.
      */
-    public DrmConvertedStatus(int _statusCode, byte[] _convertedData, int _offset) {
-        statusCode = _statusCode;
-        convertedData = _convertedData;
-        offset = _offset;
+    public DrmConvertedStatus(int statusCode, byte[] convertedData, int offset) {
+        if (!isValidStatusCode(statusCode)) {
+            throw new IllegalArgumentException("Unsupported status code: " + statusCode);
+        }
+
+        this.statusCode = statusCode;
+        this.convertedData = convertedData;
+        this.offset = offset;
+    }
+
+    private boolean isValidStatusCode(int statusCode) {
+        return statusCode == STATUS_OK ||
+               statusCode == STATUS_INPUTDATA_ERROR ||
+               statusCode == STATUS_ERROR;
     }
 }
 
diff --git a/drm/java/android/drm/DrmInfoStatus.java b/drm/java/android/drm/DrmInfoStatus.java
index 2fe0a78..9a3a7df 100755
--- a/drm/java/android/drm/DrmInfoStatus.java
+++ b/drm/java/android/drm/DrmInfoStatus.java
@@ -17,53 +17,81 @@
 package android.drm;
 
 /**
- * An entity class that wraps the result of communication between a device and an online DRM
- * server. Specifically, when the {@link DrmManagerClient#processDrmInfo processDrmInfo()} method
- * is called, an instance of <code>DrmInfoStatus</code> is returned.
+ * An entity class that wraps the result of communication between a device
+ * and an online DRM server. Specifically, when the
+ * {@link DrmManagerClient#processDrmInfo DrmManagerClient.processDrmInfo()}
+ * method is called, an instance of <code>DrmInfoStatus</code> is returned.
  *<p>
- * This class contains the {@link ProcessedData} object, which can be used to instantiate a
- * {@link DrmRights} object during license acquisition.
+ * This class contains the {@link ProcessedData} object, which can be used
+ * to instantiate a {@link DrmRights} object during license acquisition.
  *
  */
 public class DrmInfoStatus {
-    // Should be in sync with DrmInfoStatus.cpp
+    // The following status code constants must be in sync with DrmInfoStatus.cpp
+    // Please update isValidStatusCode() if more status codes are added.
+    /**
+     * Indicate successful communication.
+     */
     public static final int STATUS_OK = 1;
+
+    /**
+     * Indicate failed communication.
+     */
     public static final int STATUS_ERROR = 2;
 
     /**
-     * The status of the communication.
+     * The status of the communication. Must be one of the defined status
+     * constants above.
      */
     public final int statusCode;
     /**
-     * The type of DRM information processed.
+     * The type of DRM information processed. Must be one of the valid type
+     * constants defined in {@link DrmInfoRequest}.
      */
     public final int infoType;
     /**
-     * The MIME type of the content.
+     * The MIME type of the content. Must not be null or an empty string.
      */
     public final String mimeType;
     /**
-     * The processed data.
+     * The processed data. It is optional and thus could be null. When it
+     * is null, it indicates that a particular call to
+     * {@link DrmManagerClient#processDrmInfo DrmManagerClient.processDrmInfo()}
+     * does not return any additional useful information except for the status code.
      */
     public final ProcessedData data;
 
     /**
      * Creates a <code>DrmInfoStatus</code> object with the specified parameters.
      *
-     * @param _statusCode The status of the communication.
-     * @param _infoType The type of the DRM information processed.
-     * @param _data The processed data.
-     * @param _mimeType The MIME type.
+     * @param statusCode The status of the communication. Must be one of the defined
+     * status constants above.
+     * @param infoType The type of the DRM information processed. Must be a valid
+     * type for {@link DrmInfoRequest}.
+     * @param data The processed data.
+     * @param mimeType The MIME type.
      */
-    public DrmInfoStatus(int _statusCode, int _infoType, ProcessedData _data, String _mimeType) {
-        if (!DrmInfoRequest.isValidType(_infoType)) {
-            throw new IllegalArgumentException("infoType: " + _infoType);
+    public DrmInfoStatus(int statusCode, int infoType, ProcessedData data, String mimeType) {
+        if (!DrmInfoRequest.isValidType(infoType)) {
+            throw new IllegalArgumentException("infoType: " + infoType);
         }
 
-        statusCode = _statusCode;
-        infoType = _infoType;
-        data = _data;
-        mimeType = _mimeType;
+        if (!isValidStatusCode(statusCode)) {
+            throw new IllegalArgumentException("Unsupported status code: " + statusCode);
+        }
+
+        if (mimeType == null || mimeType == "") {
+            throw new IllegalArgumentException("mimeType is null or an empty string");
+        }
+
+        this.statusCode = statusCode;
+        this.infoType = infoType;
+        this.data = data;
+        this.mimeType = mimeType;
+    }
+
+    private boolean isValidStatusCode(int statusCode) {
+        return statusCode == STATUS_OK || statusCode == STATUS_ERROR;
     }
 }
 
diff --git a/drm/java/android/drm/DrmSupportInfo.java b/drm/java/android/drm/DrmSupportInfo.java
index 6484fa7..3694ff4 100755
--- a/drm/java/android/drm/DrmSupportInfo.java
+++ b/drm/java/android/drm/DrmSupportInfo.java
@@ -36,8 +36,16 @@
      * Adds the specified MIME type to the list of MIME types this DRM plug-in supports.
      *
      * @param mimeType MIME type that can be handles by this DRM plug-in.
+     * Must not be null or an empty string.
      */
     public void addMimeType(String mimeType) {
+        if (mimeType == null) {
+            throw new IllegalArgumentException("mimeType is null");
+        }
+        if (mimeType == "") {
+            throw new IllegalArgumentException("mimeType is an empty string");
+        }
+
         mMimeTypeList.add(mimeType);
     }
 
@@ -45,8 +53,14 @@
      * Adds the specified file suffix to the list of file suffixes this DRM plug-in supports.
      *
      * @param fileSuffix File suffix that can be handled by this DRM plug-in.
+     * it could be null but not an empty string. When it is null, it indicates
+     * that some DRM content comes with no file suffix.
      */
     public void addFileSuffix(String fileSuffix) {
+        if (fileSuffix == "") {
+            throw new IllegalArgumentException("fileSuffix is an empty string");
+        }
+
         mFileSuffixList.add(fileSuffix);
     }
 
@@ -73,12 +87,18 @@
     /**
      * Sets a description for the DRM plug-in (agent).
      *
-     * @param description Unique description of plug-in.
+     * @param description Unique description of plug-in. Must not be null
+     * or an empty string.
      */
     public void setDescription(String description) {
-        if (null != description) {
-            mDescription = description;
+        if (description == null) {
+            throw new IllegalArgumentException("description is null");
         }
+        if (description == "") {
+            throw new IllegalArgumentException("description is an empty string");
+        }
+
+        mDescription = description;
     }
 
     /**
@@ -93,7 +113,10 @@
     }
 
     /**
-     * Retrieves the DRM plug-in (agent) description.
+     * Retrieves the DRM plug-in (agent) description. Even if null or an empty
+     * string is not allowed in {@link #setDescription(String)}, if
+     * {@link #setDescription(String)} is not called, description returned
+     * from this method is an empty string.
      *
      * @return The plug-in description.
      */
@@ -111,20 +134,21 @@
     }
 
     /**
-     * Overridden <code>equals</code> implementation.
+     * Overridden <code>equals</code> implementation. Two DrmSupportInfo objects
+     * are considered being equal if they support exactly the same set of mime
+     * types, file suffixes, and has exactly the same description.
      *
      * @param object The object to be compared.
      * @return True if equal; false if not equal.
      */
     public boolean equals(Object object) {
-        boolean result = false;
-
         if (object instanceof DrmSupportInfo) {
-            result = mFileSuffixList.equals(((DrmSupportInfo) object).mFileSuffixList) &&
-                    mMimeTypeList.equals(((DrmSupportInfo) object).mMimeTypeList) &&
-                    mDescription.equals(((DrmSupportInfo) object).mDescription);
+            DrmSupportInfo info = (DrmSupportInfo) object;
+            return mFileSuffixList.equals(info.mFileSuffixList) &&
+                   mMimeTypeList.equals(info.mMimeTypeList) &&
+                   mDescription.equals(info.mDescription);
         }
-        return result;
+        return false;
     }
 
     /**
@@ -132,11 +156,17 @@
      *
      * @param mimeType MIME type.
      * @return True if Mime type is supported; false if MIME type is not supported.
+     * Null or empty string is not a supported mimeType.
      */
     /* package */ boolean isSupportedMimeType(String mimeType) {
         if (null != mimeType && !mimeType.equals("")) {
             for (int i = 0; i < mMimeTypeList.size(); i++) {
                 String completeMimeType = mMimeTypeList.get(i);
+
+                // The reason that equals() is not used is that sometimes,
+                // content distributor might just append something to
+                // the basic MIME type. startsWith() is used to avoid
+                // frequent update of DRM agent.
                 if (completeMimeType.startsWith(mimeType)) {
                     return true;
                 }
diff --git a/drm/jni/android_drm_DrmManagerClient.cpp b/drm/jni/android_drm_DrmManagerClient.cpp
index cf58177..14ec4d6 100644
--- a/drm/jni/android_drm_DrmManagerClient.cpp
+++ b/drm/jni/android_drm_DrmManagerClient.cpp
@@ -57,29 +57,16 @@
 };
 
 String8 Utility::getStringValue(JNIEnv* env, jobject object, const char* fieldName) {
-    String8 dataString("");
-
     /* Look for the instance field with the name fieldName */
     jfieldID fieldID
         = env->GetFieldID(env->GetObjectClass(object), fieldName , "Ljava/lang/String;");
 
     if (NULL != fieldID) {
         jstring valueString = (jstring) env->GetObjectField(object, fieldID);
-
-        if (NULL != valueString && valueString != env->NewStringUTF("")) {
-            char* bytes = const_cast< char* > (env->GetStringUTFChars(valueString, NULL));
-
-            const int length = strlen(bytes) + 1;
-            char *data = new char[length];
-            strncpy(data, bytes, length);
-            dataString = String8(data);
-
-            env->ReleaseStringUTFChars(valueString, bytes);
-            delete [] data; data = NULL;
-        } else {
-            ALOGV("Failed to retrieve the data from the field %s", fieldName);
-        }
+        return Utility::getStringValue(env, valueString);
     }
+
+    String8 dataString("");
     return dataString;
 }
 
@@ -102,24 +89,16 @@
 
 char* Utility::getByteArrayValue(
             JNIEnv* env, jobject object, const char* fieldName, int* dataLength) {
-    char* data = NULL;
+
     *dataLength = 0;
 
     jfieldID fieldID = env->GetFieldID(env->GetObjectClass(object), fieldName , "[B");
 
     if (NULL != fieldID) {
         jbyteArray byteArray = (jbyteArray) env->GetObjectField(object, fieldID);
-        if (NULL != byteArray) {
-            jint length = env->GetArrayLength(byteArray);
-
-            *dataLength = length;
-            if (0 < *dataLength) {
-                data = new char[length];
-                env->GetByteArrayRegion(byteArray, (jint)0, length, (jbyte *) data);
-            }
-        }
+        return Utility::getByteArrayValue(env, byteArray, dataLength);
     }
-    return data;
+    return NULL;
 }
 
 char* Utility::getByteArrayValue(JNIEnv* env, jbyteArray byteArray, int* dataLength) {
@@ -419,7 +398,7 @@
                                 Utility::getStringValue(env, contentPath));
     }
 
-    delete mData; mData = NULL;
+    delete[] mData; mData = NULL;
     ALOGV("saveRights - Exit");
     return result;
 }
@@ -510,7 +489,7 @@
                 processedData, env->NewStringUTF(pDrmInfoStatus->mimeType.string()));
     }
 
-    delete mData; mData = NULL;
+    delete[] mData; mData = NULL;
     delete pDrmInfoStatus; pDrmInfoStatus = NULL;
 
     ALOGV("processDrmInfo - Exit");
@@ -641,55 +620,8 @@
     return convertId;
 }
 
-static jobject android_drm_DrmManagerClient_convertData(
-            JNIEnv* env, jobject thiz, jint uniqueId, jint convertId, jbyteArray inputData) {
-    ALOGV("convertData Enter");
-
-    int dataLength = 0;
-    char* mData = Utility::getByteArrayValue(env, inputData, &dataLength);
-    const DrmBuffer buffer(mData, dataLength);
-
-    DrmConvertedStatus* pDrmConvertedStatus
-            = getDrmManagerClientImpl(env, thiz)->convertData(uniqueId, convertId, &buffer);
-
-    jclass localRef = env->FindClass("android/drm/DrmConvertedStatus");
-
-    jobject drmConvertedStatus = NULL;
-
-    if (NULL != localRef && NULL != pDrmConvertedStatus) {
-        int statusCode = pDrmConvertedStatus->statusCode;
-
-        jbyteArray dataArray = NULL;
-        if (NULL != pDrmConvertedStatus->convertedData) {
-            int length = pDrmConvertedStatus->convertedData->length;
-            dataArray = env->NewByteArray(length);
-            env->SetByteArrayRegion(dataArray, 0, length,
-                            (jbyte*) pDrmConvertedStatus->convertedData->data);
-
-            delete [] pDrmConvertedStatus->convertedData->data;
-            delete pDrmConvertedStatus->convertedData; pDrmConvertedStatus->convertedData = NULL;
-        }
-        jmethodID constructorId = env->GetMethodID(localRef, "<init>", "(I[BI)V");
-        drmConvertedStatus
-            = env->NewObject(localRef, constructorId,
-                             statusCode, dataArray, pDrmConvertedStatus->offset);
-    }
-
-    delete mData; mData = NULL;
-    delete pDrmConvertedStatus; pDrmConvertedStatus = NULL;
-
-    ALOGV("convertData - Exit");
-    return drmConvertedStatus;
-}
-
-static jobject android_drm_DrmManagerClient_closeConvertSession(
-            JNIEnv* env, jobject thiz, int uniqueId, jint convertId) {
-
-    ALOGV("closeConvertSession Enter");
-
-    DrmConvertedStatus* pDrmConvertedStatus
-                = getDrmManagerClientImpl(env, thiz)->closeConvertSession(uniqueId, convertId);
-
+static jobject GetConvertedStatus(JNIEnv* env, DrmConvertedStatus* pDrmConvertedStatus) {
+    ALOGV("GetConvertedStatus - Enter");
     jclass localRef = env->FindClass("android/drm/DrmConvertedStatus");
 
     jobject drmConvertedStatus = NULL;
@@ -715,10 +647,42 @@
 
     delete pDrmConvertedStatus; pDrmConvertedStatus = NULL;
 
-    ALOGV("closeConvertSession - Exit");
+    ALOGV("GetConvertedStatus - Exit");
     return drmConvertedStatus;
 }
 
+static jobject android_drm_DrmManagerClient_convertData(
+            JNIEnv* env, jobject thiz, jint uniqueId, jint convertId, jbyteArray inputData) {
+    ALOGV("convertData Enter");
+
+    int dataLength = 0;
+    char* mData = Utility::getByteArrayValue(env, inputData, &dataLength);
+    const DrmBuffer buffer(mData, dataLength);
+
+    DrmConvertedStatus* pDrmConvertedStatus
+            = getDrmManagerClientImpl(env, thiz)->convertData(uniqueId, convertId, &buffer);
+    jobject status = GetConvertedStatus(env, pDrmConvertedStatus);
+
+    delete[] mData;
+    mData = NULL;
+
+    ALOGV("convertData - Exit");
+    return status;
+}
+
+static jobject android_drm_DrmManagerClient_closeConvertSession(
+            JNIEnv* env, jobject thiz, int uniqueId, jint convertId) {
+
+    ALOGV("closeConvertSession Enter");
+
+    DrmConvertedStatus* pDrmConvertedStatus
+                = getDrmManagerClientImpl(env, thiz)->closeConvertSession(uniqueId, convertId);
+    jobject status = GetConvertedStatus(env, pDrmConvertedStatus);
+
+    ALOGV("closeConvertSession - Exit");
+    return status;
+}
+
 static JNINativeMethod nativeMethods[] = {
 
     {"_initialize", "()I",
diff --git a/graphics/java/android/renderscript/Mesh.java b/graphics/java/android/renderscript/Mesh.java
index b6ca58c3..f641117 100644
--- a/graphics/java/android/renderscript/Mesh.java
+++ b/graphics/java/android/renderscript/Mesh.java
@@ -636,7 +636,7 @@
         }
 
         /**
-        * Sets the texture coordinate for the last added vertex
+        * Sets the texture coordinate for the vertices that are added after this method call.
         *
         * @param s texture coordinate s
         * @param t texture coordinate t
@@ -653,7 +653,7 @@
         }
 
         /**
-        * Sets the normal vector for the last added vertex
+        * Sets the normal vector for the vertices that are added after this method call.
         *
         * @param x normal vector x
         * @param y normal vector y
@@ -672,7 +672,7 @@
         }
 
         /**
-        * Sets the color for the last added vertex
+        * Sets the color for the vertices that are added after this method call.
         *
         * @param r red component
         * @param g green component
diff --git a/include/media/AudioRecord.h b/include/media/AudioRecord.h
index b0c581a..4fbeb38 100644
--- a/include/media/AudioRecord.h
+++ b/include/media/AudioRecord.h
@@ -299,7 +299,7 @@
 
     /* obtains a buffer of "frameCount" frames. The buffer must be
      * filled entirely. If the track is stopped, obtainBuffer() returns
-     * STOPPED instead of NO_ERROR as long as there are buffers availlable,
+     * STOPPED instead of NO_ERROR as long as there are buffers available,
      * at which point NO_MORE_BUFFERS is returned.
      * Buffers will be returned until the pool (buffercount())
      * is exhausted, at which point obtainBuffer() will either block
@@ -317,13 +317,14 @@
 
 
     /* As a convenience we provide a read() interface to the audio buffer.
-     * This is implemented on top of lockBuffer/unlockBuffer.
+     * This is implemented on top of obtainBuffer/releaseBuffer.
      */
             ssize_t     read(void* buffer, size_t size);
 
-    /* Return the amount of input frames lost in the audio driver since the last call of this function.
-     * Audio driver is expected to reset the value to 0 and restart counting upon returning the current value by this function call.
-     * Such loss typically occurs when the user space process is blocked longer than the capacity of audio driver buffers.
+    /* Return the amount of input frames lost in the audio driver since the last call of this
+     * function.  Audio driver is expected to reset the value to 0 and restart counting upon
+     * returning the current value by this function call.  Such loss typically occurs when the
+     * user space process is blocked longer than the capacity of audio driver buffers.
      * Unit: the number of input audio frames
      */
             unsigned int  getInputFramesLost() const;
diff --git a/include/media/AudioSystem.h b/include/media/AudioSystem.h
index 89bc95d..d54ab35 100644
--- a/include/media/AudioSystem.h
+++ b/include/media/AudioSystem.h
@@ -218,8 +218,8 @@
         // IAudioFlingerClient
 
         // indicate a change in the configuration of an output or input: keeps the cached
-        // values for output/input parameters upto date in client process
-        virtual void ioConfigChanged(int event, audio_io_handle_t ioHandle, void *param2);
+        // values for output/input parameters up-to-date in client process
+        virtual void ioConfigChanged(int event, audio_io_handle_t ioHandle, const void *param2);
     };
 
     class AudioPolicyServiceClient: public IBinder::DeathRecipient
diff --git a/include/media/AudioTrack.h b/include/media/AudioTrack.h
index 9f2bd3a..95b9d86 100644
--- a/include/media/AudioTrack.h
+++ b/include/media/AudioTrack.h
@@ -135,8 +135,10 @@
      * format:             Audio format (e.g AUDIO_FORMAT_PCM_16_BIT for signed
      *                     16 bits per sample).
      * channelMask:        Channel mask: see audio_channels_t.
-     * frameCount:         Total size of track PCM buffer in frames. This defines the
-     *                     latency of the track.
+     * frameCount:         Minimum size of track PCM buffer in frames. This defines the
+     *                     latency of the track. The actual size selected by the AudioTrack could be
+     *                     larger if the requested size is not compatible with current audio HAL
+     *                     latency.
      * flags:              Reserved for future use.
      * cbf:                Callback function. If not null, this function is called periodically
      *                     to request new PCM data.
diff --git a/include/media/IAudioFlingerClient.h b/include/media/IAudioFlingerClient.h
index f3b4df1..75a9971 100644
--- a/include/media/IAudioFlingerClient.h
+++ b/include/media/IAudioFlingerClient.h
@@ -33,7 +33,7 @@
     DECLARE_META_INTERFACE(AudioFlingerClient);
 
     // Notifies a change of audio input/output configuration.
-    virtual void ioConfigChanged(int event, audio_io_handle_t ioHandle, void *param2) = 0;
+    virtual void ioConfigChanged(int event, audio_io_handle_t ioHandle, const void *param2) = 0;
 
 };
 
diff --git a/include/media/MediaPlayerInterface.h b/include/media/MediaPlayerInterface.h
index f7491d8..8168dff 100644
--- a/include/media/MediaPlayerInterface.h
+++ b/include/media/MediaPlayerInterface.h
@@ -60,6 +60,8 @@
 #define DEFAULT_AUDIOSINK_BUFFERSIZE 1200
 #define DEFAULT_AUDIOSINK_SAMPLERATE 44100
 
+// when the channel mask isn't known, use the channel count to derive a mask in AudioSink::open()
+#define CHANNEL_MASK_USE_CHANNEL_ORDER 0
 
 // callback mechanism for passing messages to MediaPlayer object
 typedef void (*notify_callback_f)(void* cookie,
@@ -91,7 +93,7 @@
         // If no callback is specified, use the "write" API below to submit
         // audio data.
         virtual status_t    open(
-                uint32_t sampleRate, int channelCount,
+                uint32_t sampleRate, int channelCount, audio_channel_mask_t channelMask,
                 audio_format_t format=AUDIO_FORMAT_PCM_16_BIT,
                 int bufferCount=DEFAULT_AUDIOSINK_BUFFERCOUNT,
                 AudioCallback cb = NULL,
diff --git a/include/media/stagefright/MediaSourceSplitter.h b/include/media/stagefright/MediaSourceSplitter.h
deleted file mode 100644
index 568f4c2..0000000
--- a/include/media/stagefright/MediaSourceSplitter.h
+++ /dev/null
@@ -1,193 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// This class provides a way to split a single media source into multiple sources.
-// The constructor takes in the real mediaSource and createClient() can then be
-// used to create multiple sources served from this real mediaSource.
-//
-// Usage:
-// - Create MediaSourceSplitter by passing in a real mediaSource from which
-// multiple duplicate channels are needed.
-// - Create a client using createClient() and use it as any other mediaSource.
-//
-// Note that multiple clients can be created using createClient() and
-// started/stopped in any order. MediaSourceSplitter stops the real source only
-// when all clients have been stopped.
-//
-// If a new client is created/started after some existing clients have already
-// started, the new client will start getting its read frames from the current
-// time.
-
-#ifndef MEDIA_SOURCE_SPLITTER_H_
-
-#define MEDIA_SOURCE_SPLITTER_H_
-
-#include <media/stagefright/MediaSource.h>
-#include <utils/threads.h>
-#include <utils/Vector.h>
-#include <utils/RefBase.h>
-
-namespace android {
-
-class MediaBuffer;
-class MetaData;
-
-class MediaSourceSplitter : public RefBase {
-public:
-    // Constructor
-    // mediaSource: The real mediaSource. The class keeps a reference to it to
-    // implement the various clients.
-    MediaSourceSplitter(sp<MediaSource> mediaSource);
-
-    ~MediaSourceSplitter();
-
-    // Creates a new client of base type MediaSource. Multiple clients can be
-    // created which get their data through the same real mediaSource. These
-    // clients can then be used like any other MediaSource, all of which provide
-    // data from the same real source.
-    sp<MediaSource> createClient();
-
-private:
-    // Total number of clients created through createClient().
-    int32_t mNumberOfClients;
-
-    // reference to the real MediaSource passed to the constructor.
-    sp<MediaSource> mSource;
-
-    // Stores pointer to the MediaBuffer read from the real MediaSource.
-    // All clients use this to implement the read() call.
-    MediaBuffer *mLastReadMediaBuffer;
-
-    // Status code for read from the real MediaSource. All clients return
-    // this for their read().
-    status_t mLastReadStatus;
-
-    // Boolean telling whether the real MediaSource has started.
-    bool mSourceStarted;
-
-    // List of booleans, one for each client, storing whether the corresponding
-    // client's start() has been called.
-    Vector<bool> mClientsStarted;
-
-    // Stores the number of clients which are currently started.
-    int32_t mNumberOfClientsStarted;
-
-    // Since different clients call read() asynchronously, we need to keep track
-    // of what data is currently read into the mLastReadMediaBuffer.
-    // mCurrentReadBit stores the bit for the current read buffer. This bit
-    // flips each time a new buffer is read from the source.
-    // mClientsDesiredReadBit stores the bit for the next desired read buffer
-    // for each client. This bit flips each time read() is completed for this
-    // client.
-    bool mCurrentReadBit;
-    Vector<bool> mClientsDesiredReadBit;
-
-    // Number of clients whose current read has been completed.
-    int32_t mNumberOfCurrentReads;
-
-    // Boolean telling whether the last read has been completed for all clients.
-    // The variable is reset to false each time buffer is read from the real
-    // source.
-    bool mLastReadCompleted;
-
-    // A global mutex for access to critical sections.
-    Mutex mLock;
-
-    // Condition variable for waiting on read from source to complete.
-    Condition mReadFromSourceCondition;
-
-    // Condition variable for waiting on all client's last read to complete.
-    Condition mAllReadsCompleteCondition;
-
-    // Functions used by Client to implement the MediaSource interface.
-
-    // If the real source has not been started yet by any client, starts it.
-    status_t start(int clientId, MetaData *params);
-
-    // Stops the real source after all clients have called stop().
-    status_t stop(int clientId);
-
-    // returns the real source's getFormat().
-    sp<MetaData> getFormat(int clientId);
-
-    // If the client's desired buffer has already been read into
-    // mLastReadMediaBuffer, points the buffer to that. Otherwise if it is the
-    // master client, reads the buffer from source or else waits for the master
-    // client to read the buffer and uses that.
-    status_t read(int clientId,
-            MediaBuffer **buffer, const MediaSource::ReadOptions *options = NULL);
-
-    // Not implemented right now.
-    status_t pause(int clientId);
-
-    // Function which reads a buffer from the real source into
-    // mLastReadMediaBuffer
-    void readFromSource_lock(const MediaSource::ReadOptions *options);
-
-    // Waits until read from the real source has been completed.
-    // _lock means that the function should be called when the thread has already
-    // obtained the lock for the mutex mLock.
-    void waitForReadFromSource_lock(int32_t clientId);
-
-    // Waits until all clients have read the current buffer in
-    // mLastReadCompleted.
-    void waitForAllClientsLastRead_lock(int32_t clientId);
-
-    // Each client calls this after it completes its read(). Once all clients
-    // have called this for the current buffer, the function calls
-    // mAllReadsCompleteCondition.broadcast() to signal the waiting clients.
-    void signalReadComplete_lock(bool readAborted);
-
-    // Make these constructors private.
-    MediaSourceSplitter();
-    MediaSourceSplitter(const MediaSourceSplitter &);
-    MediaSourceSplitter &operator=(const MediaSourceSplitter &);
-
-    // This class implements the MediaSource interface. Each client stores a
-    // reference to the parent MediaSourceSplitter and uses it to complete the
-    // various calls.
-    class Client : public MediaSource {
-    public:
-        // Constructor stores reference to the parent MediaSourceSplitter and it
-        // client id.
-        Client(sp<MediaSourceSplitter> splitter, int32_t clientId);
-
-        // MediaSource interface
-        virtual status_t start(MetaData *params = NULL);
-
-        virtual status_t stop();
-
-        virtual sp<MetaData> getFormat();
-
-        virtual status_t read(
-                MediaBuffer **buffer, const ReadOptions *options = NULL);
-
-        virtual status_t pause();
-
-    private:
-        // Refernce to the parent MediaSourceSplitter
-        sp<MediaSourceSplitter> mSplitter;
-
-        // Id of this client.
-        int32_t mClientId;
-    };
-
-    friend class Client;
-};
-
-}  // namespace android
-
-#endif  // MEDIA_SOURCE_SPLITTER_H_
diff --git a/include/media/stagefright/MetaData.h b/include/media/stagefright/MetaData.h
index 4cdee17..8b4b8ed 100644
--- a/include/media/stagefright/MetaData.h
+++ b/include/media/stagefright/MetaData.h
@@ -43,6 +43,7 @@
     kKeyStride            = 'strd',  // int32_t
     kKeySliceHeight       = 'slht',  // int32_t
     kKeyChannelCount      = '#chn',  // int32_t
+    kKeyChannelMask       = 'chnm',  // int32_t
     kKeySampleRate        = 'srte',  // int32_t (audio sampling rate Hz)
     kKeyFrameRate         = 'frmR',  // int32_t (video frame rate fps)
     kKeyBitRate           = 'brte',  // int32_t (bps)
diff --git a/libs/binder/IPCThreadState.cpp b/libs/binder/IPCThreadState.cpp
index b578a6c..96cef2c 100644
--- a/libs/binder/IPCThreadState.cpp
+++ b/libs/binder/IPCThreadState.cpp
@@ -20,7 +20,6 @@
 
 #include <binder/Binder.h>
 #include <binder/BpBinder.h>
-#include <cutils/sched_policy.h>
 #include <utils/Debug.h>
 #include <utils/Log.h>
 #include <utils/TextOutput.h>
diff --git a/libs/gui/BufferQueue.cpp b/libs/gui/BufferQueue.cpp
index d761680..cb8abdd 100644
--- a/libs/gui/BufferQueue.cpp
+++ b/libs/gui/BufferQueue.cpp
@@ -56,6 +56,11 @@
 #define ST_LOGW(x, ...) ALOGW("[%s] "x, mConsumerName.string(), ##__VA_ARGS__)
 #define ST_LOGE(x, ...) ALOGE("[%s] "x, mConsumerName.string(), ##__VA_ARGS__)
 
+#define ATRACE_BUFFER_INDEX(index)                                            \
+    char ___traceBuf[1024];                                                   \
+    snprintf(___traceBuf, 1024, "%s: %d", mConsumerName.string(), (index));   \
+    android::ScopedTrace ___bufTracer(ATRACE_TAG, ___traceBuf);
+
 namespace android {
 
 // Get an ID that's unique within this process.
@@ -106,7 +111,7 @@
         // easy, we just have more buffers
         mBufferCount = bufferCount;
         mServerBufferCount = bufferCount;
-        mDequeueCondition.signal();
+        mDequeueCondition.broadcast();
     } else {
         // we're here because we're either
         // - reducing the number of available buffers
@@ -187,7 +192,7 @@
     mClientBufferCount = bufferCount;
     mBufferHasBeenQueued = false;
     mQueue.clear();
-    mDequeueCondition.signal();
+    mDequeueCondition.broadcast();
     return OK;
 }
 
@@ -301,6 +306,7 @@
             if (numberOfBuffersNeedsToChange) {
                 // here we're guaranteed that mQueue is empty
                 freeAllBuffersLocked();
+                // XXX: signal?
                 mBufferCount = mServerBufferCount;
                 if (mBufferCount < minBufferCountNeeded)
                     mBufferCount = minBufferCountNeeded;
@@ -365,18 +371,13 @@
                 }
             }
 
-            // we're in synchronous mode and didn't find a buffer, we need to
-            // wait for some buffers to be consumed
-            tryAgain = mSynchronousMode && (foundSync == INVALID_BUFFER_SLOT);
+            // if no buffer is found, wait for a buffer to be released
+            tryAgain = found == INVALID_BUFFER_SLOT;
             if (tryAgain) {
                 mDequeueCondition.wait(mMutex);
             }
         }
 
-        if (mSynchronousMode && found == INVALID_BUFFER_SLOT) {
-            // foundSync guaranteed to be != INVALID_BUFFER_SLOT
-            found = foundSync;
-        }
 
         if (found == INVALID_BUFFER_SLOT) {
             // This should not happen.
@@ -387,6 +388,8 @@
         const int buf = found;
         *outBuf = found;
 
+        ATRACE_BUFFER_INDEX(buf);
+
         const bool useDefaultSize = !w && !h;
         if (useDefaultSize) {
             // use the default size
@@ -489,7 +492,7 @@
         // - if the client set the number of buffers, we're guaranteed that
         // we have at least 3 (because we don't allow less)
         mSynchronousMode = enabled;
-        mDequeueCondition.signal();
+        mDequeueCondition.broadcast();
     }
     return err;
 }
@@ -497,6 +500,8 @@
 status_t BufferQueue::queueBuffer(int buf, int64_t timestamp,
         uint32_t* outWidth, uint32_t* outHeight, uint32_t* outTransform) {
     ATRACE_CALL();
+    ATRACE_BUFFER_INDEX(buf);
+
     ST_LOGV("queueBuffer: slot=%d time=%lld", buf, timestamp);
 
     sp<FrameAvailableListener> listener;
@@ -555,7 +560,7 @@
         mSlots[buf].mFrameNumber = mFrameCounter;
 
         mBufferHasBeenQueued = true;
-        mDequeueCondition.signal();
+        mDequeueCondition.broadcast();
 
         *outWidth = mDefaultWidth;
         *outHeight = mDefaultHeight;
@@ -592,7 +597,7 @@
     }
     mSlots[buf].mBufferState = BufferSlot::FREE;
     mSlots[buf].mFrameNumber = 0;
-    mDequeueCondition.signal();
+    mDequeueCondition.broadcast();
 }
 
 status_t BufferQueue::setCrop(const Rect& crop) {
@@ -700,7 +705,7 @@
                 mNextCrop.makeInvalid();
                 mNextScalingMode = NATIVE_WINDOW_SCALING_MODE_FREEZE;
                 mNextTransform = 0;
-                mDequeueCondition.signal();
+                mDequeueCondition.broadcast();
             } else {
                 ST_LOGE("disconnect: connected to another api (cur=%d, req=%d)",
                         mConnectedApi, api);
@@ -810,6 +815,7 @@
 }
 
 status_t BufferQueue::acquire(BufferItem *buffer) {
+    ATRACE_CALL();
     Mutex::Autolock _l(mMutex);
     // check if queue is empty
     // In asynchronous mode the list is guaranteed to be one buffer
@@ -818,6 +824,8 @@
         Fifo::iterator front(mQueue.begin());
         int buf = *front;
 
+        ATRACE_BUFFER_INDEX(buf);
+
         if (mSlots[buf].mAcquireCalled) {
             buffer->mGraphicBuffer = NULL;
         }
@@ -828,11 +836,13 @@
         buffer->mTransform = mSlots[buf].mTransform;
         buffer->mScalingMode = mSlots[buf].mScalingMode;
         buffer->mFrameNumber = mSlots[buf].mFrameNumber;
+        buffer->mTimestamp = mSlots[buf].mTimestamp;
         buffer->mBuf = buf;
         mSlots[buf].mAcquireCalled = true;
 
         mSlots[buf].mBufferState = BufferSlot::ACQUIRED;
         mQueue.erase(front);
+        mDequeueCondition.broadcast();
 
         ATRACE_INT(mConsumerName.string(), mQueue.size());
     }
@@ -845,6 +855,9 @@
 
 status_t BufferQueue::releaseBuffer(int buf, EGLDisplay display,
         EGLSyncKHR fence) {
+    ATRACE_CALL();
+    ATRACE_BUFFER_INDEX(buf);
+
     Mutex::Autolock _l(mMutex);
 
     if (buf == INVALID_BUFFER_SLOT) {
@@ -861,7 +874,8 @@
             || mSlots[buf].mBufferState == BufferSlot::ACQUIRED) {
         mSlots[buf].mBufferState = BufferSlot::FREE;
     }
-    mDequeueCondition.signal();
+
+    mDequeueCondition.broadcast();
 
     return OK;
 }
@@ -872,7 +886,7 @@
     // is considered abandoned
     mAbandoned = true;
     freeAllBuffersLocked();
-    mDequeueCondition.signal();
+    mDequeueCondition.broadcast();
     return OK;
 }
 
diff --git a/libs/hwui/Caches.cpp b/libs/hwui/Caches.cpp
index 0ef8469..123695a 100644
--- a/libs/hwui/Caches.cpp
+++ b/libs/hwui/Caches.cpp
@@ -20,6 +20,7 @@
 #include <utils/String8.h>
 
 #include "Caches.h"
+#include "DisplayListRenderer.h"
 #include "Properties.h"
 #include "LayerRenderer.h"
 
@@ -199,6 +200,13 @@
         LayerRenderer::destroyLayer(layer);
     }
     mLayerGarbage.clear();
+
+    count = mDisplayListGarbage.size();
+    for (size_t i = 0; i < count; i++) {
+        DisplayList* displayList = mDisplayListGarbage.itemAt(i);
+        delete displayList;
+    }
+    mDisplayListGarbage.clear();
 }
 
 void Caches::deleteLayerDeferred(Layer* layer) {
@@ -206,6 +214,11 @@
     mLayerGarbage.push(layer);
 }
 
+void Caches::deleteDisplayListDeferred(DisplayList* displayList) {
+    Mutex::Autolock _l(mGarbageLock);
+    mDisplayListGarbage.push(displayList);
+}
+
 void Caches::flush(FlushMode mode) {
     FLUSH_LOGD("Flushing caches (mode %d)", mode);
 
diff --git a/libs/hwui/Caches.h b/libs/hwui/Caches.h
index f8c7bcc..65ff9ad 100644
--- a/libs/hwui/Caches.h
+++ b/libs/hwui/Caches.h
@@ -90,6 +90,8 @@
 // Caches
 ///////////////////////////////////////////////////////////////////////////////
 
+class DisplayList;
+
 class ANDROID_API Caches: public Singleton<Caches> {
     Caches();
 
@@ -141,6 +143,11 @@
      */
     void deleteLayerDeferred(Layer* layer);
 
+    /*
+     * Can be used to delete a display list from a non EGL thread.
+     */
+    void deleteDisplayListDeferred(DisplayList* layer);
+
     /**
      * Binds the VBO used to render simple textured quads.
      */
@@ -269,6 +276,7 @@
 
     mutable Mutex mGarbageLock;
     Vector<Layer*> mLayerGarbage;
+    Vector<DisplayList*> mDisplayListGarbage;
 
     DebugLevel mDebugLevel;
     bool mInitialized;
diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp
index babfd04..d9b0e5a 100644
--- a/libs/hwui/DisplayListRenderer.cpp
+++ b/libs/hwui/DisplayListRenderer.cpp
@@ -101,6 +101,13 @@
     clearResources();
 }
 
+void DisplayList::destroyDisplayListDeferred(DisplayList* displayList) {
+    if (displayList) {
+        DISPLAY_LIST_LOGD("Deferring display list destruction");
+        Caches::getInstance().deleteDisplayListDeferred(displayList);
+    }
+}
+
 void DisplayList::clearResources() {
     sk_free((void*) mReader.base());
 
diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h
index 96b87cc..02f8438 100644
--- a/libs/hwui/DisplayListRenderer.h
+++ b/libs/hwui/DisplayListRenderer.h
@@ -119,16 +119,16 @@
 
     static const char* OP_NAMES[];
 
-    void initFromDisplayListRenderer(const DisplayListRenderer& recorder, bool reusing = false);
-
     ANDROID_API size_t getSize();
+    ANDROID_API static void destroyDisplayListDeferred(DisplayList* displayList);
+    ANDROID_API static void outputLogBuffer(int fd);
+
+    void initFromDisplayListRenderer(const DisplayListRenderer& recorder, bool reusing = false);
 
     bool replay(OpenGLRenderer& renderer, Rect& dirty, int32_t flags, uint32_t level = 0);
 
     void output(OpenGLRenderer& renderer, uint32_t level = 0);
 
-    ANDROID_API static void outputLogBuffer(int fd);
-
     void setRenderable(bool renderable) {
         mIsRenderable = renderable;
     }
diff --git a/libs/hwui/GradientCache.h b/libs/hwui/GradientCache.h
index 7339853..ac34684 100644
--- a/libs/hwui/GradientCache.h
+++ b/libs/hwui/GradientCache.h
@@ -19,6 +19,7 @@
 
 #include <SkShader.h>
 
+#include <utils/Mutex.h>
 #include <utils/Vector.h>
 
 #include "Texture.h"
diff --git a/libs/hwui/Layer.h b/libs/hwui/Layer.h
index ee6ef1a..f243177 100644
--- a/libs/hwui/Layer.h
+++ b/libs/hwui/Layer.h
@@ -37,6 +37,10 @@
 // Layers
 ///////////////////////////////////////////////////////////////////////////////
 
+// Forward declarations
+class OpenGLRenderer;
+class DisplayList;
+
 /**
  * A layer has dimensions and is backed by an OpenGL texture or FBO.
  */
@@ -51,6 +55,9 @@
         texture.width = layerWidth;
         texture.height = layerHeight;
         colorFilter = NULL;
+        deferredUpdateScheduled = false;
+        renderer = NULL;
+        displayList = NULL;
     }
 
     ~Layer() {
@@ -77,6 +84,15 @@
         regionRect.translate(layer.left, layer.top);
     }
 
+    void updateDeferred(OpenGLRenderer* renderer, DisplayList* displayList,
+            int left, int top, int right, int bottom) {
+        this->renderer = renderer;
+        this->displayList = displayList;
+        const Rect r(left, top, right, bottom);
+        dirtyRect.unionWith(r);
+        deferredUpdateScheduled = true;
+    }
+
     inline uint32_t getWidth() {
         return texture.width;
     }
@@ -234,6 +250,14 @@
     uint16_t* meshIndices;
     GLsizei meshElementCount;
 
+    /**
+     * Used for deferred updates.
+     */
+    bool deferredUpdateScheduled;
+    OpenGLRenderer* renderer;
+    DisplayList* displayList;
+    Rect dirtyRect;
+
 private:
     /**
      * Name of the FBO used to render the layer. If the name is 0
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index e3148e8..339ae0a 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -2364,6 +2364,24 @@
         return;
     }
 
+    if (layer->deferredUpdateScheduled && layer->renderer && layer->displayList) {
+        OpenGLRenderer* renderer = layer->renderer;
+        Rect& dirty = layer->dirtyRect;
+
+        interrupt();
+        renderer->setViewport(layer->layer.getWidth(), layer->layer.getHeight());
+        renderer->prepareDirty(dirty.left, dirty.top, dirty.right, dirty.bottom, !layer->isBlend());
+        renderer->drawDisplayList(layer->displayList, layer->getWidth(), layer->getHeight(),
+                dirty, DisplayList::kReplayFlag_ClipChildren);
+        renderer->finish();
+        resume();
+
+        dirty.setEmpty();
+        layer->deferredUpdateScheduled = false;
+        layer->renderer = NULL;
+        layer->displayList = NULL;
+    }
+
     mCaches.activeTexture(0);
 
     int alpha;
diff --git a/libs/hwui/TextureCache.h b/libs/hwui/TextureCache.h
index d879392..10a05e0 100644
--- a/libs/hwui/TextureCache.h
+++ b/libs/hwui/TextureCache.h
@@ -19,6 +19,7 @@
 
 #include <SkBitmap.h>
 
+#include <utils/Mutex.h>
 #include <utils/Vector.h>
 
 #include "Debug.h"
diff --git a/libs/rs/driver/rsdCore.cpp b/libs/rs/driver/rsdCore.cpp
index bf2b62a..403393f 100644
--- a/libs/rs/driver/rsdCore.cpp
+++ b/libs/rs/driver/rsdCore.cpp
@@ -34,7 +34,6 @@
 #include <sys/resource.h>
 #include <sched.h>
 #include <cutils/properties.h>
-#include <cutils/sched_policy.h>
 #include <sys/syscall.h>
 #include <string.h>
 #include <bcc/bcc.h>
diff --git a/libs/rs/driver/rsdGL.cpp b/libs/rs/driver/rsdGL.cpp
index 1b12235..63bf7cc 100644
--- a/libs/rs/driver/rsdGL.cpp
+++ b/libs/rs/driver/rsdGL.cpp
@@ -41,6 +41,8 @@
 #include "rsdVertexArray.h"
 #include "rsdFrameBufferObj.h"
 
+#include <gui/SurfaceTextureClient.h>
+
 using namespace android;
 using namespace android::renderscript;
 
@@ -171,15 +173,12 @@
     }
 }
 
-bool rsdGLInit(const Context *rsc) {
-    RsdHal *dc = (RsdHal *)rsc->mHal.drv;
+void getConfigData(const Context *rsc,
+                   EGLint *configAttribs, size_t configAttribsLen,
+                   uint32_t numSamples) {
+    memset(configAttribs, 0, configAttribsLen*sizeof(*configAttribs));
 
-    dc->gl.egl.numConfigs = -1;
-    EGLint configAttribs[128];
     EGLint *configAttribsPtr = configAttribs;
-    EGLint context_attribs2[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
-
-    memset(configAttribs, 0, sizeof(configAttribs));
 
     configAttribsPtr[0] = EGL_SURFACE_TYPE;
     configAttribsPtr[1] = EGL_WINDOW_BIT;
@@ -219,8 +218,25 @@
         configAttribsPtr += 2;
     }
 
+    if (numSamples > 1) {
+        configAttribsPtr[0] = EGL_SAMPLE_BUFFERS;
+        configAttribsPtr[1] = 1;
+        configAttribsPtr[2] = EGL_SAMPLES;
+        configAttribsPtr[3] = numSamples;
+        configAttribsPtr += 4;
+    }
+
     configAttribsPtr[0] = EGL_NONE;
-    rsAssert(configAttribsPtr < (configAttribs + (sizeof(configAttribs) / sizeof(EGLint))));
+    rsAssert(configAttribsPtr < (configAttribs + configAttribsLen));
+}
+
+bool rsdGLInit(const Context *rsc) {
+    RsdHal *dc = (RsdHal *)rsc->mHal.drv;
+
+    dc->gl.egl.numConfigs = -1;
+
+    EGLint configAttribs[128];
+    EGLint context_attribs2[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
 
     ALOGV("%p initEGL start", rsc);
     rsc->setWatchdogGL("eglGetDisplay", __LINE__, __FILE__);
@@ -235,8 +251,18 @@
 
     EGLint numConfigs = -1, n = 0;
     rsc->setWatchdogGL("eglChooseConfig", __LINE__, __FILE__);
-    ret = eglChooseConfig(dc->gl.egl.display, configAttribs, 0, 0, &numConfigs);
-    checkEglError("eglGetConfigs", ret);
+
+    // Try minding a multisample config that matches the user request
+    uint32_t minSample = rsc->mUserSurfaceConfig.samplesMin;
+    uint32_t prefSample = rsc->mUserSurfaceConfig.samplesPref;
+    for (uint32_t sampleCount = prefSample; sampleCount >= minSample; sampleCount--) {
+        getConfigData(rsc, configAttribs, (sizeof(configAttribs) / sizeof(EGLint)), sampleCount);
+        ret = eglChooseConfig(dc->gl.egl.display, configAttribs, 0, 0, &numConfigs);
+        checkEglError("eglGetConfigs", ret);
+        if (numConfigs > 0) {
+            break;
+        }
+    }
 
     eglSwapInterval(dc->gl.egl.display, 0);
 
@@ -299,14 +325,15 @@
     }
     gGLContextCount++;
 
+    sp<SurfaceTexture> st(new SurfaceTexture(123));
+    sp<SurfaceTextureClient> stc(new SurfaceTextureClient(st));
+    dc->gl.egl.surfaceDefault = eglCreateWindowSurface(dc->gl.egl.display, dc->gl.egl.config,
+                                                       static_cast<ANativeWindow*>(stc.get()),
+                                                       NULL);
 
-    EGLint pbuffer_attribs[] = { EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE };
-    rsc->setWatchdogGL("eglCreatePbufferSurface", __LINE__, __FILE__);
-    dc->gl.egl.surfaceDefault = eglCreatePbufferSurface(dc->gl.egl.display, dc->gl.egl.config,
-                                                        pbuffer_attribs);
-    checkEglError("eglCreatePbufferSurface");
+    checkEglError("eglCreateWindowSurface");
     if (dc->gl.egl.surfaceDefault == EGL_NO_SURFACE) {
-        ALOGE("eglCreatePbufferSurface returned EGL_NO_SURFACE");
+        ALOGE("eglCreateWindowSurface returned EGL_NO_SURFACE");
         rsdGLShutdown(rsc);
         rsc->setWatchdogGL(NULL, 0, NULL);
         return false;
diff --git a/libs/rs/rsContext.cpp b/libs/rs/rsContext.cpp
index 95ac76e..0f3cea7 100644
--- a/libs/rs/rsContext.cpp
+++ b/libs/rs/rsContext.cpp
@@ -26,7 +26,6 @@
 
 #include <cutils/properties.h>
 
-#include <cutils/sched_policy.h>
 #include <sys/syscall.h>
 #include <string.h>
 
@@ -354,17 +353,7 @@
     // This is probably not what we want for something the user is actively
     // looking at.
     mThreadPriority = p;
-#if 0
-    SchedPolicy pol = SP_FOREGROUND;
-    if (p > 0) {
-        pol = SP_BACKGROUND;
-    }
-    if (!set_sched_policy(mNativeThreadId, pol)) {
-        // success; reset the priority as well
-    }
-#else
     setpriority(PRIO_PROCESS, mNativeThreadId, p);
-#endif
     mHal.funcs.setPriority(this, mThreadPriority);
 }
 
diff --git a/libs/ui/GraphicBufferAllocator.cpp b/libs/ui/GraphicBufferAllocator.cpp
index d344737..ff550d9 100644
--- a/libs/ui/GraphicBufferAllocator.cpp
+++ b/libs/ui/GraphicBufferAllocator.cpp
@@ -16,11 +16,13 @@
 */
 
 #define LOG_TAG "GraphicBufferAllocator"
+#define ATRACE_TAG ATRACE_TAG_GRAPHICS
 
 #include <cutils/log.h>
 
 #include <utils/Singleton.h>
 #include <utils/String8.h>
+#include <utils/Trace.h>
 
 #include <ui/GraphicBufferAllocator.h>
 
@@ -91,6 +93,7 @@
 status_t GraphicBufferAllocator::alloc(uint32_t w, uint32_t h, PixelFormat format,
         int usage, buffer_handle_t* handle, int32_t* stride)
 {
+    ATRACE_CALL();
     // make sure to not allocate a N x 0 or 0 x N buffer, since this is
     // allowed from an API stand-point allocate a 1x1 buffer instead.
     if (!w || !h)
@@ -128,6 +131,7 @@
 
 status_t GraphicBufferAllocator::free(buffer_handle_t handle)
 {
+    ATRACE_CALL();
     status_t err;
 
     err = mAllocDev->free(mAllocDev, handle);
diff --git a/libs/ui/GraphicBufferMapper.cpp b/libs/ui/GraphicBufferMapper.cpp
index b173c85..967da98 100644
--- a/libs/ui/GraphicBufferMapper.cpp
+++ b/libs/ui/GraphicBufferMapper.cpp
@@ -15,12 +15,14 @@
  */
 
 #define LOG_TAG "GraphicBufferMapper"
+#define ATRACE_TAG ATRACE_TAG_GRAPHICS
 
 #include <stdint.h>
 #include <errno.h>
 
 #include <utils/Errors.h>
 #include <utils/Log.h>
+#include <utils/Trace.h>
 
 #include <ui/GraphicBufferMapper.h>
 #include <ui/Rect.h>
@@ -46,6 +48,7 @@
 
 status_t GraphicBufferMapper::registerBuffer(buffer_handle_t handle)
 {
+    ATRACE_CALL();
     status_t err;
 
     err = mAllocMod->registerBuffer(mAllocMod, handle);
@@ -57,6 +60,7 @@
 
 status_t GraphicBufferMapper::unregisterBuffer(buffer_handle_t handle)
 {
+    ATRACE_CALL();
     status_t err;
 
     err = mAllocMod->unregisterBuffer(mAllocMod, handle);
@@ -69,6 +73,7 @@
 status_t GraphicBufferMapper::lock(buffer_handle_t handle, 
         int usage, const Rect& bounds, void** vaddr)
 {
+    ATRACE_CALL();
     status_t err;
 
     err = mAllocMod->lock(mAllocMod, handle, usage,
@@ -81,6 +86,7 @@
 
 status_t GraphicBufferMapper::unlock(buffer_handle_t handle)
 {
+    ATRACE_CALL();
     status_t err;
 
     err = mAllocMod->unlock(mAllocMod, handle);
diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java
index 1c7f577..aa60d0a 100644
--- a/media/java/android/media/AudioService.java
+++ b/media/java/android/media/AudioService.java
@@ -2035,20 +2035,11 @@
         }
 
         public void readSettings() {
-            int index = Settings.System.getInt(mContentResolver,
-                            mVolumeIndexSettingName,
-                            AudioManager.DEFAULT_STREAM_VOLUME[mStreamType]);
-
-            mIndex.clear();
-            mIndex.put(AudioSystem.DEVICE_OUT_DEFAULT, index);
-
-            index = Settings.System.getInt(mContentResolver,
-                            mLastAudibleVolumeIndexSettingName,
-                            (index > 0) ? index : AudioManager.DEFAULT_STREAM_VOLUME[mStreamType]);
-            mLastAudibleIndex.clear();
-            mLastAudibleIndex.put(AudioSystem.DEVICE_OUT_DEFAULT, index);
+            boolean checkSilentVolume = (mRingerMode == AudioManager.RINGER_MODE_NORMAL) &&
+                                            isStreamAffectedByRingerMode(mStreamType);
 
             int remainingDevices = AudioSystem.DEVICE_OUT_ALL;
+
             for (int i = 0; remainingDevices != 0; i++) {
                 int device = (1 << i);
                 if ((device & remainingDevices) == 0) {
@@ -2057,17 +2048,58 @@
                 remainingDevices &= ~device;
 
                 // retrieve current volume for device
-                String name = getSettingNameForDevice(false, device);
-                index = Settings.System.getInt(mContentResolver, name, -1);
+                String name = getSettingNameForDevice(false /* lastAudible */, device);
+                // if no volume stored for current stream and device, use default volume if default
+                // device, continue otherwise
+                int defaultIndex = (device == AudioSystem.DEVICE_OUT_DEFAULT) ?
+                                        AudioManager.DEFAULT_STREAM_VOLUME[mStreamType] : -1;
+                int index = Settings.System.getInt(mContentResolver, name, defaultIndex);
                 if (index == -1) {
                     continue;
                 }
-                mIndex.put(device, getValidIndex(10 * index));
 
                 // retrieve last audible volume for device
-                name = getSettingNameForDevice(true, device);
-                index = Settings.System.getInt(mContentResolver, name, -1);
-                mLastAudibleIndex.put(device, getValidIndex(10 * index));
+                name = getSettingNameForDevice(true  /* lastAudible */, device);
+                // use stored last audible index if present, otherwise use current index if not 0
+                // or default index
+                defaultIndex = (index > 0) ?
+                                    index : AudioManager.DEFAULT_STREAM_VOLUME[mStreamType];
+                int lastAudibleIndex = Settings.System.getInt(mContentResolver, name, defaultIndex);
+
+                // a last audible index of 0 is never stored, except on non-voice capable devices
+                // (e.g. tablets) for the music stream type, where the music stream volume can reach
+                // 0 without the device being in silent mode
+                if ((lastAudibleIndex == 0) &&
+                        (mVoiceCapable ||
+                         (STREAM_VOLUME_ALIAS[mStreamType] != AudioSystem.STREAM_MUSIC))) {
+                    lastAudibleIndex = AudioManager.DEFAULT_STREAM_VOLUME[mStreamType];
+                    // Correct the data base
+                    sendMsg(mAudioHandler,
+                            MSG_PERSIST_VOLUME,
+                            SENDMSG_QUEUE,
+                            PERSIST_LAST_AUDIBLE,
+                            device,
+                            this,
+                            PERSIST_DELAY);
+                }
+                mLastAudibleIndex.put(device, getValidIndex(10 * lastAudibleIndex));
+                // the initial index should never be 0 for a stream affected by ringer mode if not
+                // in silent or vibrate mode.
+                // this is permitted on tablets for music stream type.
+                if (checkSilentVolume && (index == 0) &&
+                        (mVoiceCapable ||
+                         (STREAM_VOLUME_ALIAS[mStreamType] != AudioSystem.STREAM_MUSIC))) {
+                    index = lastAudibleIndex;
+                    // Correct the data base
+                    sendMsg(mAudioHandler,
+                            MSG_PERSIST_VOLUME,
+                            SENDMSG_QUEUE,
+                            PERSIST_CURRENT,
+                            device,
+                            this,
+                            PERSIST_DELAY);
+                }
+                mIndex.put(device, getValidIndex(10 * index));
             }
         }
 
diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java
index d354cdb..b5e832c 100644
--- a/media/java/android/media/AudioSystem.java
+++ b/media/java/android/media/AudioSystem.java
@@ -279,6 +279,7 @@
             return DEVICE_OUT_ANLG_DOCK_HEADSET_NAME;
         case DEVICE_OUT_DGTL_DOCK_HEADSET:
             return DEVICE_OUT_DGTL_DOCK_HEADSET_NAME;
+        case DEVICE_IN_DEFAULT:
         default:
             return "";
         }
diff --git a/media/java/android/media/CamcorderProfile.java b/media/java/android/media/CamcorderProfile.java
index e94bddc..511111c 100644
--- a/media/java/android/media/CamcorderProfile.java
+++ b/media/java/android/media/CamcorderProfile.java
@@ -67,6 +67,8 @@
 
     /**
      * Quality level corresponding to the 480p (720 x 480) resolution.
+     * Note that the horizontal resolution for 480p can also be other
+     * values, such as 640 or 704, instead of 720.
      */
     public static final int QUALITY_480P = 4;
 
@@ -76,7 +78,10 @@
     public static final int QUALITY_720P = 5;
 
     /**
-     * Quality level corresponding to the 1080p (1920 x 1088) resolution.
+     * Quality level corresponding to the 1080p (1920 x 1080) resolution.
+     * Note that the vertical resolution for 1080p can also be 1088,
+     * instead of 1080 (used by some vendors to avoid cropping during
+     * video playback).
      */
     public static final int QUALITY_1080P = 6;
 
diff --git a/media/java/android/media/MediaActionSound.java b/media/java/android/media/MediaActionSound.java
new file mode 100644
index 0000000..d0e6910
--- /dev/null
+++ b/media/java/android/media/MediaActionSound.java
@@ -0,0 +1,194 @@
+/*
+ * Copyright (C) 2012 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.media;
+
+import android.media.AudioManager;
+import android.media.SoundPool;
+import android.util.Log;
+
+/**
+ * <p>A class for producing sounds that match those produced by various actions
+ * taken by the media and camera APIs.  </p>
+ *
+ * <p>Use this class to play an appropriate camera operation sound when
+ * implementing a custom still or video recording mechanism (through the Camera
+ * preview callbacks with {@link android.hardware.Camera#setPreviewCallback
+ * Camera.setPreviewCallback}, or through GPU processing with {@link
+ * android.hardware.Camera#setPreviewTexture Camera.setPreviewTexture}, for
+ * example), or when implementing some other camera-like function in your
+ * application.</p>
+ *
+ * <p>There is no need to play sounds when using
+ * {@link android.hardware.Camera#takePicture Camera.takePicture} or
+ * {@link android.media.MediaRecorder} for still images or video, respectively,
+ * as the Android framework will play the appropriate sounds when needed for
+ * these calls.</p>
+ *
+ */
+public class MediaActionSound {
+    private static final int NUM_MEDIA_SOUND_STREAMS = 1;
+
+    private SoundPool mSoundPool;
+    private int[]     mSoundIds;
+    private int       mSoundIdToPlay;
+
+    private static final String[] SOUND_FILES = {
+        "/system/media/audio/ui/camera_click.ogg",
+        "/system/media/audio/ui/camera_focus.ogg",
+        "/system/media/audio/ui/VideoRecord.ogg",
+        "/system/media/audio/ui/VideoRecord.ogg"
+    };
+
+    private static final String TAG = "MediaActionSound";
+    /**
+     * The sound used by
+     * {@link android.hardware.Camera#takePicture Camera.takePicture} to
+     * indicate still image capture.
+     * @see #play
+     */
+    public static final int SHUTTER_CLICK         = 0;
+
+    /**
+     * A sound to indicate that focusing has completed. Because deciding
+     * when this occurs is application-dependent, this sound is not used by
+     * any methods in the media or camera APIs.
+     * @see #play
+     */
+    public static final int FOCUS_COMPLETE        = 1;
+
+    /**
+     * The sound used by
+     * {@link android.media.MediaRecorder#start MediaRecorder.start()} to
+     * indicate the start of video recording.
+     * @see #play
+     */
+    public static final int START_VIDEO_RECORDING = 2;
+
+    /**
+     * The sound used by
+     * {@link android.media.MediaRecorder#stop MediaRecorder.stop()} to
+     * indicate the end of video recording.
+     * @see #play
+     */
+    public static final int STOP_VIDEO_RECORDING  = 3;
+
+    private static final int SOUND_NOT_LOADED = -1;
+
+    /**
+     * Construct a new MediaActionSound instance. Only a single instance is
+     * needed for playing any platform media action sound; you do not need a
+     * separate instance for each sound type.
+     */
+    public MediaActionSound() {
+        mSoundPool = new SoundPool(NUM_MEDIA_SOUND_STREAMS,
+                AudioManager.STREAM_SYSTEM_ENFORCED, 0);
+        mSoundPool.setOnLoadCompleteListener(mLoadCompleteListener);
+        mSoundIds = new int[SOUND_FILES.length];
+        for (int i = 0; i < mSoundIds.length; i++) {
+            mSoundIds[i] = SOUND_NOT_LOADED;
+        }
+        mSoundIdToPlay = SOUND_NOT_LOADED;
+    }
+
+    /**
+     * Preload a predefined platform sound to minimize latency when the sound is
+     * played later by {@link #play}.
+     * @param soundName The type of sound to preload, selected from
+     *         SHUTTER_CLICK, FOCUS_COMPLETE, START_VIDEO_RECORDING, or
+     *         STOP_VIDEO_RECORDING.
+     * @see #play
+     * @see #SHUTTER_CLICK
+     * @see #FOCUS_COMPLETE
+     * @see #START_VIDEO_RECORDING
+     * @see #STOP_VIDEO_RECORDING
+     */
+    public synchronized void load(int soundName) {
+        if (soundName < 0 || soundName >= SOUND_FILES.length) {
+            throw new RuntimeException("Unknown sound requested: " + soundName);
+        }
+        if (mSoundIds[soundName] == SOUND_NOT_LOADED) {
+            mSoundIds[soundName] =
+                    mSoundPool.load(SOUND_FILES[soundName], 1);
+        }
+    }
+
+    /**
+     * <p>Play one of the predefined platform sounds for media actions.</p>
+     *
+     * <p>Use this method to play a platform-specific sound for various media
+     * actions. The sound playback is done asynchronously, with the same
+     * behavior and content as the sounds played by
+     * {@link android.hardware.Camera#takePicture Camera.takePicture},
+     * {@link android.media.MediaRecorder#start MediaRecorder.start}, and
+     * {@link android.media.MediaRecorder#stop MediaRecorder.stop}.</p>
+     *
+     * <p>Using this method makes it easy to match the default device sounds
+     * when recording or capturing data through the preview callbacks, or when
+     * implementing custom camera-like features in your
+     * application.</p>
+     *
+     * <p>If the sound has not been loaded by {@link #load} before calling play,
+     * play will load the sound at the cost of some additional latency before
+     * sound playback begins. </p>
+     *
+     * @param soundName The type of sound to play, selected from
+     *         SHUTTER_CLICK, FOCUS_COMPLETE, START_VIDEO_RECORDING, or
+     *         STOP_VIDEO_RECORDING.
+     * @see android.hardware.Camera#takePicture
+     * @see android.media.MediaRecorder
+     * @see #SHUTTER_CLICK
+     * @see #FOCUS_COMPLETE
+     * @see #START_VIDEO_RECORDING
+     * @see #STOP_VIDEO_RECORDING
+     */
+    public synchronized void play(int soundName) {
+        if (soundName < 0 || soundName >= SOUND_FILES.length) {
+            throw new RuntimeException("Unknown sound requested: " + soundName);
+        }
+        if (mSoundIds[soundName] == SOUND_NOT_LOADED) {
+            mSoundIdToPlay =
+                    mSoundPool.load(SOUND_FILES[soundName], 1);
+            mSoundIds[soundName] = mSoundIdToPlay;
+        } else {
+            mSoundPool.play(mSoundIds[soundName], 1.0f, 1.0f, 0, 0, 1.0f);
+        }
+    }
+
+    private SoundPool.OnLoadCompleteListener mLoadCompleteListener =
+            new SoundPool.OnLoadCompleteListener() {
+        public void onLoadComplete(SoundPool soundPool,
+                int sampleId, int status) {
+            if (status == 0) {
+                if (mSoundIdToPlay == sampleId) {
+                    soundPool.play(sampleId, 1.0f, 1.0f, 0, 0, 1.0f);
+                    mSoundIdToPlay = SOUND_NOT_LOADED;
+                }
+            } else {
+                Log.e(TAG, "Unable to load sound for playback (status: " +
+                        status + ")");
+            }
+        }
+    };
+
+    /**
+     * Free up all audio resources used by this MediaActionSound instance
+     */
+    public void release() {
+        mSoundPool.release();
+        mSoundPool = null;
+    }
+}
diff --git a/media/libeffects/data/audio_effects.conf b/media/libeffects/data/audio_effects.conf
index b8fa487..ce25bc8 100644
--- a/media/libeffects/data/audio_effects.conf
+++ b/media/libeffects/data/audio_effects.conf
@@ -50,11 +50,11 @@
   }
   volume {
     library bundle
-    uuid 119341a0-8469-11df-81f9- 0002a5d5c51b
+    uuid 119341a0-8469-11df-81f9-0002a5d5c51b
   }
   reverb_env_aux {
     library reverb
-    uuid 4a387fc0-8ab3-11df-8bad- 0002a5d5c51b
+    uuid 4a387fc0-8ab3-11df-8bad-0002a5d5c51b
   }
   reverb_env_ins {
     library reverb
diff --git a/media/libeffects/downmix/Android.mk b/media/libeffects/downmix/Android.mk
new file mode 100644
index 0000000..0348e1e
--- /dev/null
+++ b/media/libeffects/downmix/Android.mk
@@ -0,0 +1,28 @@
+LOCAL_PATH:= $(call my-dir)
+
+# Multichannel downmix effect library
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+	EffectDownmix.c
+
+LOCAL_SHARED_LIBRARIES := \
+	libcutils
+
+LOCAL_MODULE:= libdownmix
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/soundfx
+
+ifeq ($(TARGET_OS)-$(TARGET_SIMULATOR),linux-true)
+LOCAL_LDLIBS += -ldl
+endif
+
+LOCAL_C_INCLUDES := \
+	system/media/audio_effects/include \
+	system/media/audio_utils/include
+
+LOCAL_PRELINK_MODULE := false
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/media/libeffects/downmix/EffectDownmix.c b/media/libeffects/downmix/EffectDownmix.c
new file mode 100644
index 0000000..a325172
--- /dev/null
+++ b/media/libeffects/downmix/EffectDownmix.c
@@ -0,0 +1,889 @@
+/*
+ * Copyright (C) 2012 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 "EffectDownmix"
+#define LOG_NDEBUG 0
+#include <cutils/log.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdbool.h>
+#include "EffectDownmix.h"
+
+#define MINUS_3_DB_IN_Q19_12 2896 // -3dB = 0.707 * 2^12 = 2896
+
+// effect_handle_t interface implementation for downmix effect
+const struct effect_interface_s gDownmixInterface = {
+        Downmix_Process,
+        Downmix_Command,
+        Downmix_GetDescriptor,
+        NULL /* no process_reverse function, no reference stream needed */
+};
+
+audio_effect_library_t AUDIO_EFFECT_LIBRARY_INFO_SYM = {
+    tag : AUDIO_EFFECT_LIBRARY_TAG,
+    version : EFFECT_LIBRARY_API_VERSION,
+    name : "Downmix Library",
+    implementor : "The Android Open Source Project",
+    query_num_effects : DownmixLib_QueryNumberEffects,
+    query_effect : DownmixLib_QueryEffect,
+    create_effect : DownmixLib_Create,
+    release_effect : DownmixLib_Release,
+    get_descriptor : DownmixLib_GetDescriptor,
+};
+
+
+// AOSP insert downmix UUID: 93f04452-e4fe-41cc-91f9-e475b6d1d69f
+static const effect_descriptor_t gDownmixDescriptor = {
+        EFFECT_UIID_DOWNMIX__, //type
+        {0x93f04452, 0xe4fe, 0x41cc, 0x91f9, {0xe4, 0x75, 0xb6, 0xd1, 0xd6, 0x9f}}, // uuid
+        EFFECT_CONTROL_API_VERSION,
+        EFFECT_FLAG_TYPE_INSERT | EFFECT_FLAG_INSERT_FIRST,
+        0, //FIXME what value should be reported? // cpu load
+        0, //FIXME what value should be reported? // memory usage
+        "Multichannel Downmix To Stereo", // human readable effect name
+        "The Android Open Source Project" // human readable effect implementor name
+};
+
+// gDescriptors contains pointers to all defined effect descriptor in this library
+static const effect_descriptor_t * const gDescriptors[] = {
+        &gDownmixDescriptor
+};
+
+// number of effects in this library
+const int kNbEffects = sizeof(gDescriptors) / sizeof(const effect_descriptor_t *);
+
+
+/*----------------------------------------------------------------------------
+ * Effect API implementation
+ *--------------------------------------------------------------------------*/
+
+/*--- Effect Library Interface Implementation ---*/
+
+int32_t DownmixLib_QueryNumberEffects(uint32_t *pNumEffects) {
+    ALOGV("DownmixLib_QueryNumberEffects()");
+    *pNumEffects = kNbEffects;
+    return 0;
+}
+
+int32_t DownmixLib_QueryEffect(uint32_t index, effect_descriptor_t *pDescriptor) {
+    ALOGV("DownmixLib_QueryEffect() index=%d", index);
+    if (pDescriptor == NULL) {
+        return -EINVAL;
+    }
+    if (index >= (uint32_t)kNbEffects) {
+        return -EINVAL;
+    }
+    memcpy(pDescriptor, gDescriptors[index], sizeof(effect_descriptor_t));
+    return 0;
+}
+
+
+int32_t DownmixLib_Create(const effect_uuid_t *uuid,
+        int32_t sessionId,
+        int32_t ioId,
+        effect_handle_t *pHandle) {
+    int ret;
+    int i;
+    downmix_module_t *module;
+    const effect_descriptor_t *desc;
+
+    ALOGV("DownmixLib_Create()");
+
+    if (pHandle == NULL || uuid == NULL) {
+        return -EINVAL;
+    }
+
+    for (i = 0 ; i < kNbEffects ; i++) {
+        desc = gDescriptors[i];
+        if (memcmp(uuid, &desc->uuid, sizeof(effect_uuid_t)) == 0) {
+            break;
+        }
+    }
+
+    if (i == kNbEffects) {
+        return -ENOENT;
+    }
+
+    module = malloc(sizeof(downmix_module_t));
+
+    module->itfe = &gDownmixInterface;
+
+    module->context.state = DOWNMIX_STATE_UNINITIALIZED;
+
+    ret = Downmix_Init(module);
+    if (ret < 0) {
+        ALOGW("DownmixLib_Create() init failed");
+        free(module);
+        return ret;
+    }
+
+    *pHandle = (effect_handle_t) module;
+
+    ALOGV("DownmixLib_Create() %p , size %d", module, sizeof(downmix_module_t));
+
+    return 0;
+}
+
+
+int32_t DownmixLib_Release(effect_handle_t handle) {
+    downmix_module_t *pDwmModule = (downmix_module_t *)handle;
+
+    ALOGV("DownmixLib_Release() %p", handle);
+    if (handle == NULL) {
+        return -EINVAL;
+    }
+
+    pDwmModule->context.state = DOWNMIX_STATE_UNINITIALIZED;
+
+    free(pDwmModule);
+    return 0;
+}
+
+
+int32_t DownmixLib_GetDescriptor(const effect_uuid_t *uuid, effect_descriptor_t *pDescriptor) {
+    ALOGV("DownmixLib_GetDescriptor()");
+    int i;
+
+    if (pDescriptor == NULL || uuid == NULL){
+        ALOGE("DownmixLib_Create() called with NULL pointer");
+        return -EINVAL;
+    }
+    ALOGV("DownmixLib_GetDescriptor() nb effects=%d", kNbEffects);
+    for (i = 0; i < kNbEffects; i++) {
+        ALOGV("DownmixLib_GetDescriptor() i=%d", i);
+        if (memcmp(uuid, &gDescriptors[i]->uuid, sizeof(effect_uuid_t)) == 0) {
+            memcpy(pDescriptor, gDescriptors[i], sizeof(effect_descriptor_t));
+            ALOGV("EffectGetDescriptor - UUID matched downmix type %d, UUID = %x",
+                 i, gDescriptors[i]->uuid.timeLow);
+            return 0;
+        }
+    }
+
+    return -EINVAL;
+}
+
+
+/*--- Effect Control Interface Implementation ---*/
+
+static int Downmix_Process(effect_handle_t self,
+        audio_buffer_t *inBuffer, audio_buffer_t *outBuffer) {
+
+    downmix_object_t *pDownmixer;
+    int16_t *pSrc, *pDst;
+    downmix_module_t *pDwmModule = (downmix_module_t *)self;
+
+    if (pDwmModule == NULL) {
+        return -EINVAL;
+    }
+
+    if (inBuffer == NULL || inBuffer->raw == NULL ||
+        outBuffer == NULL || outBuffer->raw == NULL ||
+        inBuffer->frameCount != outBuffer->frameCount) {
+        return -EINVAL;
+    }
+
+    pDownmixer = (downmix_object_t*) &pDwmModule->context;
+
+    if (pDownmixer->state == DOWNMIX_STATE_UNINITIALIZED) {
+        ALOGE("Downmix_Process error: trying to use an uninitialized downmixer");
+        return -EINVAL;
+    } else if (pDownmixer->state == DOWNMIX_STATE_INITIALIZED) {
+        ALOGE("Downmix_Process error: trying to use a non-configured downmixer");
+        return -ENODATA;
+    }
+
+    pSrc = inBuffer->s16;
+    pDst = outBuffer->s16;
+    size_t numFrames = outBuffer->frameCount;
+
+    const bool accumulate =
+            (pDwmModule->config.outputCfg.accessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE);
+
+    switch(pDownmixer->type) {
+
+      case DOWNMIX_TYPE_STRIP:
+          if (accumulate) {
+              while (numFrames) {
+                  pDst[0] = clamp16(pDst[0] + pSrc[0]);
+                  pDst[1] = clamp16(pDst[1] + pSrc[1]);
+                  pSrc += pDownmixer->input_channel_count;
+                  pDst += 2;
+                  numFrames--;
+              }
+          } else {
+              while (numFrames) {
+                  pDst[0] = pSrc[0];
+                  pDst[1] = pSrc[1];
+                  pSrc += pDownmixer->input_channel_count;
+                  pDst += 2;
+                  numFrames--;
+              }
+          }
+          break;
+
+      case DOWNMIX_TYPE_FOLD:
+        // optimize for the common formats
+        switch(pDwmModule->config.inputCfg.channels) {
+        case AUDIO_CHANNEL_OUT_QUAD:
+            Downmix_foldFromQuad(pSrc, pDst, numFrames, accumulate);
+            break;
+        case AUDIO_CHANNEL_OUT_SURROUND:
+            Downmix_foldFromSurround(pSrc, pDst, numFrames, accumulate);
+            break;
+        case AUDIO_CHANNEL_OUT_5POINT1:
+            Downmix_foldFrom5Point1(pSrc, pDst, numFrames, accumulate);
+            break;
+        case AUDIO_CHANNEL_OUT_7POINT1:
+            Downmix_foldFrom7Point1(pSrc, pDst, numFrames, accumulate);
+            break;
+        default:
+            // FIXME implement generic downmix
+            ALOGE("Multichannel configurations other than quad, 4.0, 5.1 and 7.1 are not supported");
+            break;
+        }
+        break;
+
+      default:
+        return -EINVAL;
+    }
+
+    return 0;
+}
+
+
+static int Downmix_Command(effect_handle_t self, uint32_t cmdCode, uint32_t cmdSize,
+        void *pCmdData, uint32_t *replySize, void *pReplyData) {
+
+    downmix_module_t *pDwmModule = (downmix_module_t *) self;
+    downmix_object_t *pDownmixer;
+    int retsize;
+
+    if (pDwmModule == NULL || pDwmModule->context.state == DOWNMIX_STATE_UNINITIALIZED) {
+        return -EINVAL;
+    }
+
+    pDownmixer = (downmix_object_t*) &pDwmModule->context;
+
+    ALOGV("Downmix_Command command %d cmdSize %d",cmdCode, cmdSize);
+
+    switch (cmdCode) {
+    case EFFECT_CMD_INIT:
+        if (pReplyData == NULL || *replySize != sizeof(int)) {
+            return -EINVAL;
+        }
+        *(int *) pReplyData = Downmix_Init(pDwmModule);
+        break;
+
+    case EFFECT_CMD_SET_CONFIG:
+        if (pCmdData == NULL || cmdSize != sizeof(effect_config_t)
+                || pReplyData == NULL || *replySize != sizeof(int)) {
+            return -EINVAL;
+        }
+        *(int *) pReplyData = Downmix_Configure(pDwmModule,
+                (effect_config_t *)pCmdData, false);
+        break;
+
+    case EFFECT_CMD_RESET:
+        Downmix_Reset(pDownmixer, false);
+        break;
+
+    case EFFECT_CMD_GET_PARAM:
+        ALOGV("Downmix_Command EFFECT_CMD_GET_PARAM pCmdData %p, *replySize %d, pReplyData: %p",
+                pCmdData, *replySize, pReplyData);
+        if (pCmdData == NULL || cmdSize < (int)(sizeof(effect_param_t) + sizeof(int32_t)) ||
+                pReplyData == NULL ||
+                *replySize < (int) sizeof(effect_param_t) + 2 * sizeof(int32_t)) {
+            return -EINVAL;
+        }
+        effect_param_t *rep = (effect_param_t *) pReplyData;
+        memcpy(pReplyData, pCmdData, sizeof(effect_param_t) + sizeof(int32_t));
+        ALOGV("Downmix_Command EFFECT_CMD_GET_PARAM param %d, replySize %d",
+                *(int32_t *)rep->data, rep->vsize);
+        rep->status = Downmix_getParameter(pDownmixer, *(int32_t *)rep->data, &rep->vsize,
+                rep->data + sizeof(int32_t));
+        *replySize = sizeof(effect_param_t) + sizeof(int32_t) + rep->vsize;
+        break;
+
+    case EFFECT_CMD_SET_PARAM:
+        ALOGV("Downmix_Command EFFECT_CMD_SET_PARAM cmdSize %d pCmdData %p, *replySize %d, " \
+                "pReplyData %p", cmdSize, pCmdData, *replySize, pReplyData);
+        if (pCmdData == NULL || (cmdSize < (int)(sizeof(effect_param_t) + sizeof(int32_t)))
+                || pReplyData == NULL || *replySize != (int)sizeof(int32_t)) {
+            return -EINVAL;
+        }
+        effect_param_t *cmd = (effect_param_t *) pCmdData;
+        *(int *)pReplyData = Downmix_setParameter(pDownmixer, *(int32_t *)cmd->data,
+                cmd->vsize, cmd->data + sizeof(int32_t));
+        break;
+
+    case EFFECT_CMD_SET_PARAM_DEFERRED:
+        //FIXME implement
+        ALOGW("Downmix_Command command EFFECT_CMD_SET_PARAM_DEFERRED not supported, FIXME");
+        break;
+
+    case EFFECT_CMD_SET_PARAM_COMMIT:
+        //FIXME implement
+        ALOGW("Downmix_Command command EFFECT_CMD_SET_PARAM_COMMIT not supported, FIXME");
+        break;
+
+    case EFFECT_CMD_ENABLE:
+        if (pReplyData == NULL || *replySize != sizeof(int)) {
+            return -EINVAL;
+        }
+        if (pDownmixer->state != DOWNMIX_STATE_INITIALIZED) {
+            return -ENOSYS;
+        }
+        pDownmixer->state = DOWNMIX_STATE_ACTIVE;
+        ALOGV("EFFECT_CMD_ENABLE() OK");
+        *(int *)pReplyData = 0;
+        break;
+
+    case EFFECT_CMD_DISABLE:
+        if (pReplyData == NULL || *replySize != sizeof(int)) {
+            return -EINVAL;
+        }
+        if (pDownmixer->state != DOWNMIX_STATE_ACTIVE) {
+            return -ENOSYS;
+        }
+        pDownmixer->state = DOWNMIX_STATE_INITIALIZED;
+        ALOGV("EFFECT_CMD_DISABLE() OK");
+        *(int *)pReplyData = 0;
+        break;
+
+    case EFFECT_CMD_SET_DEVICE:
+        if (pCmdData == NULL || cmdSize != (int)sizeof(uint32_t)) {
+            return -EINVAL;
+        }
+        // FIXME change type if playing on headset vs speaker
+        ALOGV("Downmix_Command EFFECT_CMD_SET_DEVICE: 0x%08x", *(uint32_t *)pCmdData);
+        break;
+
+    case EFFECT_CMD_SET_VOLUME: {
+        // audio output is always stereo => 2 channel volumes
+        if (pCmdData == NULL || cmdSize != (int)sizeof(uint32_t) * 2) {
+            return -EINVAL;
+        }
+        // FIXME change volume
+        ALOGW("Downmix_Command command EFFECT_CMD_SET_VOLUME not supported, FIXME");
+        float left = (float)(*(uint32_t *)pCmdData) / (1 << 24);
+        float right = (float)(*((uint32_t *)pCmdData + 1)) / (1 << 24);
+        ALOGV("Downmix_Command EFFECT_CMD_SET_VOLUME: left %f, right %f ", left, right);
+        break;
+    }
+
+    case EFFECT_CMD_SET_AUDIO_MODE:
+        if (pCmdData == NULL || cmdSize != (int)sizeof(uint32_t)) {
+            return -EINVAL;
+        }
+        ALOGV("Downmix_Command EFFECT_CMD_SET_AUDIO_MODE: %d", *(uint32_t *)pCmdData);
+        break;
+
+    case EFFECT_CMD_SET_CONFIG_REVERSE:
+    case EFFECT_CMD_SET_INPUT_DEVICE:
+        // these commands are ignored by a downmix effect
+        break;
+
+    default:
+        ALOGW("Downmix_Command invalid command %d",cmdCode);
+        return -EINVAL;
+    }
+
+    return 0;
+}
+
+
+int Downmix_GetDescriptor(effect_handle_t self, effect_descriptor_t *pDescriptor)
+{
+    downmix_module_t *pDwnmxModule = (downmix_module_t *) self;
+
+    if (pDwnmxModule == NULL ||
+            pDwnmxModule->context.state == DOWNMIX_STATE_UNINITIALIZED) {
+        return -EINVAL;
+    }
+
+    memcpy(pDescriptor, &gDownmixDescriptor, sizeof(effect_descriptor_t));
+
+    return 0;
+}
+
+
+/*----------------------------------------------------------------------------
+ * Downmix internal functions
+ *--------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+ * Downmix_Init()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Initialize downmix context and apply default parameters
+ *
+ * Inputs:
+ *  pDwmModule    pointer to downmix effect module
+ *
+ * Outputs:
+ *
+ * Returns:
+ *  0             indicates success
+ *
+ * Side Effects:
+ *  updates:
+ *           pDwmModule->context.type
+ *           pDwmModule->context.apply_volume_correction
+ *           pDwmModule->config.inputCfg
+ *           pDwmModule->config.outputCfg
+ *           pDwmModule->config.inputCfg.samplingRate
+ *           pDwmModule->config.outputCfg.samplingRate
+ *           pDwmModule->context.state
+ *  doesn't set:
+ *           pDwmModule->itfe
+ *
+ *----------------------------------------------------------------------------
+ */
+
+int Downmix_Init(downmix_module_t *pDwmModule) {
+
+    ALOGV("Downmix_Init module %p", pDwmModule);
+    int ret = 0;
+
+    memset(&pDwmModule->context, 0, sizeof(downmix_object_t));
+
+    pDwmModule->config.inputCfg.accessMode = EFFECT_BUFFER_ACCESS_READ;
+    pDwmModule->config.inputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
+    pDwmModule->config.inputCfg.channels = AUDIO_CHANNEL_OUT_7POINT1;
+    pDwmModule->config.inputCfg.bufferProvider.getBuffer = NULL;
+    pDwmModule->config.inputCfg.bufferProvider.releaseBuffer = NULL;
+    pDwmModule->config.inputCfg.bufferProvider.cookie = NULL;
+    pDwmModule->config.inputCfg.mask = EFFECT_CONFIG_ALL;
+
+    pDwmModule->config.inputCfg.samplingRate = 44100;
+    pDwmModule->config.outputCfg.samplingRate = pDwmModule->config.inputCfg.samplingRate;
+
+    // set a default value for the access mode, but should be overwritten by caller
+    pDwmModule->config.outputCfg.accessMode = EFFECT_BUFFER_ACCESS_ACCUMULATE;
+    pDwmModule->config.outputCfg.format = AUDIO_FORMAT_PCM_16_BIT;
+    pDwmModule->config.outputCfg.channels = AUDIO_CHANNEL_OUT_STEREO;
+    pDwmModule->config.outputCfg.bufferProvider.getBuffer = NULL;
+    pDwmModule->config.outputCfg.bufferProvider.releaseBuffer = NULL;
+    pDwmModule->config.outputCfg.bufferProvider.cookie = NULL;
+    pDwmModule->config.outputCfg.mask = EFFECT_CONFIG_ALL;
+
+    ret = Downmix_Configure(pDwmModule, &pDwmModule->config, true);
+    if (ret != 0) {
+        ALOGV("Downmix_Init error %d on module %p", ret, pDwmModule);
+    } else {
+        pDwmModule->context.state = DOWNMIX_STATE_INITIALIZED;
+    }
+
+    return ret;
+}
+
+
+/*----------------------------------------------------------------------------
+ * Downmix_Configure()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ *  Set input and output audio configuration.
+ *
+ * Inputs:
+ *  pDwmModule  pointer to downmix effect module
+ *  pConfig     pointer to effect_config_t structure containing input
+ *                  and output audio parameters configuration
+ *  init        true if called from init function
+ *
+ * Outputs:
+ *
+ * Returns:
+ *  0           indicates success
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+ */
+
+int Downmix_Configure(downmix_module_t *pDwmModule, effect_config_t *pConfig, bool init) {
+
+    downmix_object_t *pDownmixer = &pDwmModule->context;
+
+    // Check configuration compatibility with build options, and effect capabilities
+    if (pConfig->inputCfg.samplingRate != pConfig->outputCfg.samplingRate
+        || pConfig->outputCfg.channels != DOWNMIX_OUTPUT_CHANNELS
+        || pConfig->inputCfg.format != AUDIO_FORMAT_PCM_16_BIT
+        || pConfig->outputCfg.format != AUDIO_FORMAT_PCM_16_BIT) {
+        ALOGE("Downmix_Configure error: invalid config");
+        return -EINVAL;
+    }
+
+    memcpy(&pDwmModule->config, pConfig, sizeof(effect_config_t));
+
+    if (init) {
+        pDownmixer->type = DOWNMIX_TYPE_FOLD;
+        pDownmixer->apply_volume_correction = false;
+        pDownmixer->input_channel_count = 8; // matches default input of AUDIO_CHANNEL_OUT_7POINT1
+    } else {
+        // when configuring the effect, do not allow a blank channel mask
+        if (pConfig->inputCfg.channels == 0) {
+            ALOGE("Downmix_Configure error: input channel mask can't be 0");
+            return -EINVAL;
+        }
+        pDownmixer->input_channel_count = popcount(pConfig->inputCfg.channels);
+    }
+
+    Downmix_Reset(pDownmixer, init);
+
+    return 0;
+}
+
+
+/*----------------------------------------------------------------------------
+ * Downmix_Reset()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ *  Reset internal states.
+ *
+ * Inputs:
+ *  pDownmixer   pointer to downmix context
+ *  init         true if called from init function
+ *
+ * Outputs:
+*
+ * Returns:
+ *  0            indicates success
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+ */
+
+int Downmix_Reset(downmix_object_t *pDownmixer, bool init) {
+    // nothing to do here
+    return 0;
+}
+
+
+/*----------------------------------------------------------------------------
+ * Downmix_setParameter()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Set a Downmix parameter
+ *
+ * Inputs:
+ *  pDownmixer    handle to instance data
+ *  param         parameter
+ *  pValue        pointer to parameter value
+ *  size          value size
+ *
+ * Outputs:
+ *
+ * Returns:
+ *  0             indicates success
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+ */
+int Downmix_setParameter(downmix_object_t *pDownmixer, int32_t param, size_t size, void *pValue) {
+
+    int16_t value16;
+    ALOGV("Downmix_setParameter, context %p, param %d, value16 %d, value32 %d",
+            pDownmixer, param, *(int16_t *)pValue, *(int32_t *)pValue);
+
+    switch (param) {
+
+      case DOWNMIX_PARAM_TYPE:
+        if (size != sizeof(downmix_type_t)) {
+            ALOGE("Downmix_setParameter(DOWNMIX_PARAM_TYPE) invalid size %d, should be %d",
+                    size, sizeof(downmix_type_t));
+            return -EINVAL;
+        }
+        value16 = *(int16_t *)pValue;
+        ALOGV("set DOWNMIX_PARAM_TYPE, type %d", value16);
+        if (!((value16 > DOWNMIX_TYPE_INVALID) && (value16 < DOWNMIX_TYPE_LAST))) {
+            ALOGE("Downmix_setParameter invalid DOWNMIX_PARAM_TYPE value %d", value16);
+            return -EINVAL;
+        } else {
+            pDownmixer->type = (downmix_type_t) value16;
+        break;
+
+      default:
+        ALOGE("Downmix_setParameter unknown parameter %d", param);
+        return -EINVAL;
+    }
+}
+
+    return 0;
+} /* end Downmix_setParameter */
+
+
+/*----------------------------------------------------------------------------
+ * Downmix_getParameter()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * Get a Downmix parameter
+ *
+ * Inputs:
+ *  pDownmixer    handle to instance data
+ *  param         parameter
+ *  pValue        pointer to variable to hold retrieved value
+ *  pSize         pointer to value size: maximum size as input
+ *
+ * Outputs:
+ *  *pValue updated with parameter value
+ *  *pSize updated with actual value size
+ *
+ * Returns:
+ *  0             indicates success
+ *
+ * Side Effects:
+ *
+ *----------------------------------------------------------------------------
+ */
+int Downmix_getParameter(downmix_object_t *pDownmixer, int32_t param, size_t *pSize, void *pValue) {
+    int16_t *pValue16;
+
+    switch (param) {
+
+    case DOWNMIX_PARAM_TYPE:
+      if (*pSize < sizeof(int16_t)) {
+          ALOGE("Downmix_getParameter invalid parameter size %d for DOWNMIX_PARAM_TYPE", *pSize);
+          return -EINVAL;
+      }
+      pValue16 = (int16_t *)pValue;
+      *pValue16 = (int16_t) pDownmixer->type;
+      *pSize = sizeof(int16_t);
+      ALOGV("Downmix_getParameter DOWNMIX_PARAM_TYPE is %d", *pValue16);
+      break;
+
+    default:
+      ALOGE("Downmix_getParameter unknown parameter %d", param);
+      return -EINVAL;
+    }
+
+    return 0;
+} /* end Downmix_getParameter */
+
+
+/*----------------------------------------------------------------------------
+ * Downmix_foldFromQuad()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * downmix a quad signal to stereo
+ *
+ * Inputs:
+ *  pSrc       quad audio samples to downmix
+ *  numFrames  the number of quad frames to downmix
+ *
+ * Outputs:
+ *  pDst       downmixed stereo audio samples
+ *
+ *----------------------------------------------------------------------------
+ */
+void Downmix_foldFromQuad(int16_t *pSrc, int16_t*pDst, size_t numFrames, bool accumulate) {
+    // sample at index 0 is FL
+    // sample at index 1 is FR
+    // sample at index 2 is RL
+    // sample at index 3 is RR
+    if (accumulate) {
+        while (numFrames) {
+            // FL + RL
+            pDst[0] = clamp16(pDst[0] + pSrc[0] + pSrc[2]);
+            // FR + RR
+            pDst[1] = clamp16(pDst[1] + pSrc[1] + pSrc[3]);
+            pSrc += 4;
+            pDst += 2;
+            numFrames--;
+        }
+    } else { // same code as above but without adding and clamping pDst[i] to itself
+        while (numFrames) {
+            // FL + RL
+            pDst[0] = clamp16(pSrc[0] + pSrc[2]);
+            // FR + RR
+            pDst[1] = clamp16(pSrc[1] + pSrc[3]);
+            pSrc += 4;
+            pDst += 2;
+            numFrames--;
+        }
+    }
+}
+
+
+/*----------------------------------------------------------------------------
+ * Downmix_foldFromSurround()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * downmix a "surround sound" (mono rear) signal to stereo
+ *
+ * Inputs:
+ *  pSrc       surround signal to downmix
+ *  numFrames  the number of surround frames to downmix
+ *
+ * Outputs:
+ *  pDst       downmixed stereo audio samples
+ *
+ *----------------------------------------------------------------------------
+ */
+void Downmix_foldFromSurround(int16_t *pSrc, int16_t*pDst, size_t numFrames, bool accumulate) {
+    int32_t lt, rt, centerPlusRearContrib; // samples in Q19.12 format
+    // sample at index 0 is FL
+    // sample at index 1 is FR
+    // sample at index 2 is FC
+    // sample at index 3 is RC
+    if (accumulate) {
+        while (numFrames) {
+            // centerPlusRearContrib = FC(-3dB) + RC(-3dB)
+            centerPlusRearContrib = (pSrc[2] * MINUS_3_DB_IN_Q19_12) + (pSrc[3] * MINUS_3_DB_IN_Q19_12);
+            // FL + centerPlusRearContrib
+            lt = (pSrc[0] << 12) + centerPlusRearContrib;
+            // FR + centerPlusRearContrib
+            rt = (pSrc[1] << 12) + centerPlusRearContrib;
+            pDst[0] = clamp16(pDst[0] + (lt >> 12));
+            pDst[1] = clamp16(pDst[1] + (rt >> 12));
+            pSrc += 4;
+            pDst += 2;
+            numFrames--;
+        }
+    } else { // same code as above but without adding and clamping pDst[i] to itself
+        while (numFrames) {
+            // centerPlusRearContrib = FC(-3dB) + RC(-3dB)
+            centerPlusRearContrib = (pSrc[2] * MINUS_3_DB_IN_Q19_12) + (pSrc[3] * MINUS_3_DB_IN_Q19_12);
+            // FL + centerPlusRearContrib
+            lt = (pSrc[0] << 12) + centerPlusRearContrib;
+            // FR + centerPlusRearContrib
+            rt = (pSrc[1] << 12) + centerPlusRearContrib;
+            pDst[0] = clamp16(lt >> 12);
+            pDst[1] = clamp16(rt >> 12);
+            pSrc += 4;
+            pDst += 2;
+            numFrames--;
+        }
+    }
+}
+
+
+/*----------------------------------------------------------------------------
+ * Downmix_foldFrom5Point1()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * downmix a 5.1 signal to stereo
+ *
+ * Inputs:
+ *  pSrc       5.1 audio samples to downmix
+ *  numFrames  the number of 5.1 frames to downmix
+ *
+ * Outputs:
+ *  pDst       downmixed stereo audio samples
+ *
+ *----------------------------------------------------------------------------
+ */
+void Downmix_foldFrom5Point1(int16_t *pSrc, int16_t*pDst, size_t numFrames, bool accumulate) {
+    int32_t lt, rt, centerPlusLfeContrib; // samples in Q19.12 format
+    // sample at index 0 is FL
+    // sample at index 1 is FR
+    // sample at index 2 is FC
+    // sample at index 3 is LFE
+    // sample at index 4 is RL
+    // sample at index 5 is RR
+    if (accumulate) {
+        while (numFrames) {
+            // centerPlusLfeContrib = FC(-3dB) + LFE(-3dB)
+            centerPlusLfeContrib = (pSrc[2] * MINUS_3_DB_IN_Q19_12)
+                    + (pSrc[3] * MINUS_3_DB_IN_Q19_12);
+            // FL + centerPlusLfeContrib + RL
+            lt = (pSrc[0] << 12) + centerPlusLfeContrib + (pSrc[4] << 12);
+            // FR + centerPlusLfeContrib + RR
+            rt = (pSrc[1] << 12) + centerPlusLfeContrib + (pSrc[5] << 12);
+            pDst[0] = clamp16(pDst[0] + (lt >> 12));
+            pDst[1] = clamp16(pDst[1] + (rt >> 12));
+            pSrc += 6;
+            pDst += 2;
+            numFrames--;
+        }
+    } else { // same code as above but without adding and clamping pDst[i] to itself
+        while (numFrames) {
+            // centerPlusLfeContrib = FC(-3dB) + LFE(-3dB)
+            centerPlusLfeContrib = (pSrc[2] * MINUS_3_DB_IN_Q19_12)
+                    + (pSrc[3] * MINUS_3_DB_IN_Q19_12);
+            // FL + centerPlusLfeContrib + RL
+            lt = (pSrc[0] << 12) + centerPlusLfeContrib + (pSrc[4] << 12);
+            // FR + centerPlusLfeContrib + RR
+            rt = (pSrc[1] << 12) + centerPlusLfeContrib + (pSrc[5] << 12);
+            pDst[0] = clamp16(lt >> 12);
+            pDst[1] = clamp16(rt >> 12);
+            pSrc += 6;
+            pDst += 2;
+            numFrames--;
+        }
+    }
+}
+
+
+/*----------------------------------------------------------------------------
+ * Downmix_foldFrom7Point1()
+ *----------------------------------------------------------------------------
+ * Purpose:
+ * downmix a 7.1 signal to stereo
+ *
+ * Inputs:
+ *  pSrc       7.1 audio samples to downmix
+ *  numFrames  the number of 7.1 frames to downmix
+ *
+ * Outputs:
+ *  pDst       downmixed stereo audio samples
+ *
+ *----------------------------------------------------------------------------
+ */
+void Downmix_foldFrom7Point1(int16_t *pSrc, int16_t*pDst, size_t numFrames, bool accumulate) {
+    int32_t lt, rt, centerPlusLfeContrib; // samples in Q19.12 format
+    // sample at index 0 is FL
+    // sample at index 1 is FR
+    // sample at index 2 is FC
+    // sample at index 3 is LFE
+    // sample at index 4 is RL
+    // sample at index 5 is RR
+    // sample at index 6 is SL
+    // sample at index 7 is SR
+    if (accumulate) {
+        while (numFrames) {
+            // centerPlusLfeContrib = FC(-3dB) + LFE(-3dB)
+            centerPlusLfeContrib = (pSrc[2] * MINUS_3_DB_IN_Q19_12)
+                    + (pSrc[3] * MINUS_3_DB_IN_Q19_12);
+            // FL + centerPlusLfeContrib + SL + RL
+            lt = (pSrc[0] << 12) + centerPlusLfeContrib + (pSrc[6] << 12) + (pSrc[4] << 12);
+            // FR + centerPlusLfeContrib + SR + RR
+            rt = (pSrc[1] << 12) + centerPlusLfeContrib + (pSrc[7] << 12) + (pSrc[5] << 12);
+            pDst[0] = clamp16(lt >> 12);
+            pDst[1] = clamp16(rt >> 12);
+            pSrc += 8;
+            pDst += 2;
+            numFrames--;
+    }
+    } else { // same code as above but without adding and clamping pDst[i] to itself
+        while (numFrames) {
+            // centerPlusLfeContrib = FC(-3dB) + LFE(-3dB)
+            centerPlusLfeContrib = (pSrc[2] * MINUS_3_DB_IN_Q19_12)
+                    + (pSrc[3] * MINUS_3_DB_IN_Q19_12);
+            // FL + centerPlusLfeContrib + SL + RL
+            lt = (pSrc[0] << 12) + centerPlusLfeContrib + (pSrc[6] << 12) + (pSrc[4] << 12);
+            // FR + centerPlusLfeContrib + SR + RR
+            rt = (pSrc[1] << 12) + centerPlusLfeContrib + (pSrc[7] << 12) + (pSrc[5] << 12);
+            pDst[0] = clamp16(pDst[0] + (lt >> 12));
+            pDst[1] = clamp16(pDst[1] + (rt >> 12));
+            pSrc += 8;
+            pDst += 2;
+            numFrames--;
+        }
+    }
+}
+
diff --git a/media/libeffects/downmix/EffectDownmix.h b/media/libeffects/downmix/EffectDownmix.h
new file mode 100644
index 0000000..4176b5a
--- /dev/null
+++ b/media/libeffects/downmix/EffectDownmix.h
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_EFFECTDOWNMIX_H_
+#define ANDROID_EFFECTDOWNMIX_H_
+
+#include <audio_effects/effect_downmix.h>
+#include <audio_utils/primitives.h>
+#include <system/audio.h>
+
+/*------------------------------------
+ * definitions
+ *------------------------------------
+*/
+
+#define DOWNMIX_OUTPUT_CHANNELS AUDIO_CHANNEL_OUT_STEREO
+
+typedef enum {
+    DOWNMIX_STATE_UNINITIALIZED,
+    DOWNMIX_STATE_INITIALIZED,
+    DOWNMIX_STATE_ACTIVE,
+} downmix_state_t;
+
+/* parameters for each downmixer */
+typedef struct {
+    downmix_state_t state;
+    downmix_type_t type;
+    bool apply_volume_correction;
+    uint8_t input_channel_count;
+} downmix_object_t;
+
+
+typedef struct downmix_module_s {
+    const struct effect_interface_s *itfe;
+    effect_config_t config;
+    downmix_object_t context;
+} downmix_module_t;
+
+
+/*------------------------------------
+ * Effect API
+ *------------------------------------
+*/
+int32_t DownmixLib_QueryNumberEffects(uint32_t *pNumEffects);
+int32_t DownmixLib_QueryEffect(uint32_t index,
+        effect_descriptor_t *pDescriptor);
+int32_t DownmixLib_Create(const effect_uuid_t *uuid,
+        int32_t sessionId,
+        int32_t ioId,
+        effect_handle_t *pHandle);
+int32_t DownmixLib_Release(effect_handle_t handle);
+int32_t DownmixLib_GetDescriptor(const effect_uuid_t *uuid,
+        effect_descriptor_t *pDescriptor);
+
+static int Downmix_Process(effect_handle_t self,
+        audio_buffer_t *inBuffer,
+        audio_buffer_t *outBuffer);
+static int Downmix_Command(effect_handle_t self,
+        uint32_t cmdCode,
+        uint32_t cmdSize,
+        void *pCmdData,
+        uint32_t *replySize,
+        void *pReplyData);
+static int Downmix_GetDescriptor(effect_handle_t self,
+        effect_descriptor_t *pDescriptor);
+
+
+/*------------------------------------
+ * internal functions
+ *------------------------------------
+*/
+int Downmix_Init(downmix_module_t *pDwmModule);
+int Downmix_Configure(downmix_module_t *pDwmModule, effect_config_t *pConfig, bool init);
+int Downmix_Reset(downmix_object_t *pDownmixer, bool init);
+int Downmix_setParameter(downmix_object_t *pDownmixer, int32_t param, size_t size, void *pValue);
+int Downmix_getParameter(downmix_object_t *pDownmixer, int32_t param, size_t *pSize, void *pValue);
+
+void Downmix_foldFromQuad(int16_t *pSrc, int16_t*pDst, size_t numFrames, bool accumulate);
+void Downmix_foldFromSurround(int16_t *pSrc, int16_t*pDst, size_t numFrames, bool accumulate);
+void Downmix_foldFrom5Point1(int16_t *pSrc, int16_t*pDst, size_t numFrames, bool accumulate);
+void Downmix_foldFrom7Point1(int16_t *pSrc, int16_t*pDst, size_t numFrames, bool accumulate);
+
+#endif /*ANDROID_EFFECTDOWNMIX_H_*/
diff --git a/media/libmedia/AudioSystem.cpp b/media/libmedia/AudioSystem.cpp
index ec4c044..e0b186a 100644
--- a/media/libmedia/AudioSystem.cpp
+++ b/media/libmedia/AudioSystem.cpp
@@ -405,9 +405,9 @@
 }
 
 void AudioSystem::AudioFlingerClient::ioConfigChanged(int event, audio_io_handle_t ioHandle,
-        void *param2) {
+        const void *param2) {
     ALOGV("ioConfigChanged() event %d", event);
-    OutputDescriptor *desc;
+    const OutputDescriptor *desc;
     audio_stream_type_t stream;
 
     if (ioHandle == 0) return;
@@ -417,7 +417,7 @@
     switch (event) {
     case STREAM_CONFIG_CHANGED:
         if (param2 == NULL) break;
-        stream = *(audio_stream_type_t *)param2;
+        stream = *(const audio_stream_type_t *)param2;
         ALOGV("ioConfigChanged() STREAM_CONFIG_CHANGED stream %d, output %d", stream, ioHandle);
         if (gStreamOutputMap.indexOfKey(stream) >= 0) {
             gStreamOutputMap.replaceValueFor(stream, ioHandle);
@@ -429,7 +429,7 @@
             break;
         }
         if (param2 == NULL) break;
-        desc = (OutputDescriptor *)param2;
+        desc = (const OutputDescriptor *)param2;
 
         OutputDescriptor *outputDesc =  new OutputDescriptor(*desc);
         gOutputs.add(ioHandle, outputDesc);
@@ -458,7 +458,7 @@
             break;
         }
         if (param2 == NULL) break;
-        desc = (OutputDescriptor *)param2;
+        desc = (const OutputDescriptor *)param2;
 
         ALOGV("ioConfigChanged() new config for output %d samplingRate %d, format %d channels %d frameCount %d latency %d",
                 ioHandle, desc->samplingRate, desc->format,
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp
index 4890f05..a1c99e5 100644
--- a/media/libmedia/AudioTrack.cpp
+++ b/media/libmedia/AudioTrack.cpp
@@ -784,12 +784,9 @@
                 mNotificationFramesAct = frameCount/2;
             }
             if (frameCount < minFrameCount) {
-                if (enforceFrameCount) {
-                    ALOGE("Invalid buffer size: minFrameCount %d, frameCount %d", minFrameCount, frameCount);
-                    return BAD_VALUE;
-                } else {
-                    frameCount = minFrameCount;
-                }
+                ALOGW_IF(enforceFrameCount, "Minimum buffer size corrected from %d to %d",
+                         frameCount, minFrameCount);
+                frameCount = minFrameCount;
             }
         } else {
             // Ensure that buffer alignment matches channelCount
diff --git a/media/libmedia/IAudioFlingerClient.cpp b/media/libmedia/IAudioFlingerClient.cpp
index ce28b33..1db39a3 100644
--- a/media/libmedia/IAudioFlingerClient.cpp
+++ b/media/libmedia/IAudioFlingerClient.cpp
@@ -39,18 +39,18 @@
     {
     }
 
-    void ioConfigChanged(int event, audio_io_handle_t ioHandle, void *param2)
+    void ioConfigChanged(int event, audio_io_handle_t ioHandle, const void *param2)
     {
         Parcel data, reply;
         data.writeInterfaceToken(IAudioFlingerClient::getInterfaceDescriptor());
         data.writeInt32(event);
         data.writeInt32((int32_t) ioHandle);
         if (event == AudioSystem::STREAM_CONFIG_CHANGED) {
-            uint32_t stream = *(uint32_t *)param2;
+            uint32_t stream = *(const uint32_t *)param2;
             ALOGV("ioConfigChanged stream %d", stream);
             data.writeInt32(stream);
         } else if (event != AudioSystem::OUTPUT_CLOSED && event != AudioSystem::INPUT_CLOSED) {
-            AudioSystem::OutputDescriptor *desc = (AudioSystem::OutputDescriptor *)param2;
+            const AudioSystem::OutputDescriptor *desc = (const AudioSystem::OutputDescriptor *)param2;
             data.writeInt32(desc->samplingRate);
             data.writeInt32(desc->format);
             data.writeInt32(desc->channels);
@@ -73,7 +73,7 @@
             CHECK_INTERFACE(IAudioFlingerClient, data, reply);
             int event = data.readInt32();
             audio_io_handle_t ioHandle = (audio_io_handle_t) data.readInt32();
-            void *param2 = NULL;
+            const void *param2 = NULL;
             AudioSystem::OutputDescriptor desc;
             uint32_t stream;
             if (event == AudioSystem::STREAM_CONFIG_CHANGED) {
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index 1e2abf0..1a85c9c 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -325,7 +325,7 @@
             mStreamType, mLeftVolume, mRightVolume);
     result.append(buffer);
     snprintf(buffer, 255, "  msec per frame(%f), latency (%d)\n",
-            mMsecsPerFrame, mLatency);
+            mMsecsPerFrame, (mTrack != 0) ? mTrack->latency() : -1);
     result.append(buffer);
     snprintf(buffer, 255, "  aux effect id(%d), send level (%f)\n",
             mAuxEffectId, mSendLevel);
@@ -1384,7 +1384,6 @@
     mRightVolume = 1.0;
     mPlaybackRatePermille = 1000;
     mSampleRateHz = 0;
-    mLatency = 0;
     mMsecsPerFrame = 0;
     mAuxEffectId = 0;
     mSendLevel = 0.0;
@@ -1443,7 +1442,8 @@
 
 uint32_t MediaPlayerService::AudioOutput::latency () const
 {
-    return mLatency;
+    if (mTrack == 0) return 0;
+    return mTrack->latency();
 }
 
 float MediaPlayerService::AudioOutput::msecsPerFrame() const
@@ -1458,7 +1458,8 @@
 }
 
 status_t MediaPlayerService::AudioOutput::open(
-        uint32_t sampleRate, int channelCount, audio_format_t format, int bufferCount,
+        uint32_t sampleRate, int channelCount, audio_channel_mask_t channelMask,
+        audio_format_t format, int bufferCount,
         AudioCallback cb, void *cookie)
 {
     mCallback = cb;
@@ -1470,7 +1471,8 @@
         bufferCount = mMinBufferCount;
 
     }
-    ALOGV("open(%u, %d, %d, %d, %d)", sampleRate, channelCount, format, bufferCount,mSessionId);
+    ALOGV("open(%u, %d, 0x%x, %d, %d, %d)", sampleRate, channelCount, channelMask,
+            format, bufferCount, mSessionId);
     if (mTrack) close();
     int afSampleRate;
     int afFrameCount;
@@ -1485,13 +1487,21 @@
 
     frameCount = (sampleRate*afFrameCount*bufferCount)/afSampleRate;
 
+    if (channelMask == CHANNEL_MASK_USE_CHANNEL_ORDER) {
+        channelMask = audio_channel_mask_from_count(channelCount);
+        if (0 == channelMask) {
+            ALOGE("open() error, can\'t derive mask for %d audio channels", channelCount);
+            return NO_INIT;
+        }
+    }
+
     AudioTrack *t;
     if (mCallback != NULL) {
         t = new AudioTrack(
                 mStreamType,
                 sampleRate,
                 format,
-                (channelCount == 2) ? AUDIO_CHANNEL_OUT_STEREO : AUDIO_CHANNEL_OUT_MONO,
+                channelMask,
                 frameCount,
                 0 /* flags */,
                 CallbackWrapper,
@@ -1503,7 +1513,7 @@
                 mStreamType,
                 sampleRate,
                 format,
-                (channelCount == 2) ? AUDIO_CHANNEL_OUT_STEREO : AUDIO_CHANNEL_OUT_MONO,
+                channelMask,
                 frameCount,
                 0,
                 NULL,
@@ -1523,7 +1533,6 @@
 
     mSampleRateHz = sampleRate;
     mMsecsPerFrame = mPlaybackRatePermille / (float) sampleRate;
-    mLatency = t->latency();
     mTrack = t;
 
     status_t res = t->setSampleRate(mPlaybackRatePermille * mSampleRateHz / 1000);
@@ -1751,10 +1760,11 @@
 ////////////////////////////////////////////////////////////////////////////////
 
 status_t MediaPlayerService::AudioCache::open(
-        uint32_t sampleRate, int channelCount, audio_format_t format, int bufferCount,
+        uint32_t sampleRate, int channelCount, audio_channel_mask_t channelMask,
+        audio_format_t format, int bufferCount,
         AudioCallback cb, void *cookie)
 {
-    ALOGV("open(%u, %d, %d, %d)", sampleRate, channelCount, format, bufferCount);
+    ALOGV("open(%u, %d, 0x%x, %d, %d)", sampleRate, channelCount, channelMask, format, bufferCount);
     if (mHeap->getHeapID() < 0) {
         return NO_INIT;
     }
diff --git a/media/libmediaplayerservice/MediaPlayerService.h b/media/libmediaplayerservice/MediaPlayerService.h
index 53847ed..85cec22 100644
--- a/media/libmediaplayerservice/MediaPlayerService.h
+++ b/media/libmediaplayerservice/MediaPlayerService.h
@@ -85,7 +85,7 @@
         virtual int             getSessionId();
 
         virtual status_t        open(
-                uint32_t sampleRate, int channelCount,
+                uint32_t sampleRate, int channelCount, audio_channel_mask_t channelMask,
                 audio_format_t format, int bufferCount,
                 AudioCallback cb, void *cookie);
 
@@ -118,7 +118,6 @@
         int32_t                 mPlaybackRatePermille;
         uint32_t                mSampleRateHz; // sample rate of the content, as set in open()
         float                   mMsecsPerFrame;
-        uint32_t                mLatency;
         int                     mSessionId;
         float                   mSendLevel;
         int                     mAuxEffectId;
@@ -145,8 +144,8 @@
         virtual int             getSessionId();
 
         virtual status_t        open(
-                uint32_t sampleRate, int channelCount, audio_format_t format,
-                int bufferCount = 1,
+                uint32_t sampleRate, int channelCount, audio_channel_mask_t channelMask,
+                audio_format_t format, int bufferCount = 1,
                 AudioCallback cb = NULL, void *cookie = NULL);
 
         virtual void            start();
diff --git a/media/libmediaplayerservice/MidiFile.cpp b/media/libmediaplayerservice/MidiFile.cpp
index 7cb8c29..8db5b9b 100644
--- a/media/libmediaplayerservice/MidiFile.cpp
+++ b/media/libmediaplayerservice/MidiFile.cpp
@@ -421,7 +421,8 @@
 }
 
 status_t MidiFile::createOutputTrack() {
-    if (mAudioSink->open(pLibConfig->sampleRate, pLibConfig->numChannels, AUDIO_FORMAT_PCM_16_BIT, 2) != NO_ERROR) {
+    if (mAudioSink->open(pLibConfig->sampleRate, pLibConfig->numChannels,
+            CHANNEL_MASK_USE_CHANNEL_ORDER, AUDIO_FORMAT_PCM_16_BIT, 2) != NO_ERROR) {
         ALOGE("mAudioSink open failed");
         return ERROR_OPEN_FAILED;
     }
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
index e618f67..526120a 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
@@ -336,6 +336,7 @@
                     CHECK_EQ(mAudioSink->open(
                                 sampleRate,
                                 numChannels,
+                                CHANNEL_MASK_USE_CHANNEL_ORDER,
                                 AUDIO_FORMAT_PCM_16_BIT,
                                 8 /* bufferCount */),
                              (status_t)OK);
diff --git a/media/libstagefright/Android.mk b/media/libstagefright/Android.mk
index 21d6866..5aea8d0 100644
--- a/media/libstagefright/Android.mk
+++ b/media/libstagefright/Android.mk
@@ -34,7 +34,6 @@
         MediaDefs.cpp                     \
         MediaExtractor.cpp                \
         MediaSource.cpp                   \
-        MediaSourceSplitter.cpp           \
         MetaData.cpp                      \
         NuCachedSource2.cpp               \
         NuMediaExtractor.cpp              \
diff --git a/media/libstagefright/AudioPlayer.cpp b/media/libstagefright/AudioPlayer.cpp
index df27566..650b6c4 100644
--- a/media/libstagefright/AudioPlayer.cpp
+++ b/media/libstagefright/AudioPlayer.cpp
@@ -110,13 +110,18 @@
     success = format->findInt32(kKeySampleRate, &mSampleRate);
     CHECK(success);
 
-    int32_t numChannels;
+    int32_t numChannels, channelMask;
     success = format->findInt32(kKeyChannelCount, &numChannels);
     CHECK(success);
 
+    if(!format->findInt32(kKeyChannelMask, &channelMask)) {
+        ALOGW("source format didn't specify channel mask, using channel order");
+        channelMask = CHANNEL_MASK_USE_CHANNEL_ORDER;
+    }
+
     if (mAudioSink.get() != NULL) {
         status_t err = mAudioSink->open(
-                mSampleRate, numChannels, AUDIO_FORMAT_PCM_16_BIT,
+                mSampleRate, numChannels, channelMask, AUDIO_FORMAT_PCM_16_BIT,
                 DEFAULT_AUDIOSINK_BUFFERCOUNT,
                 &AudioPlayer::AudioSinkCallback, this);
         if (err != OK) {
@@ -137,11 +142,15 @@
 
         mAudioSink->start();
     } else {
+        // playing to an AudioTrack, set up mask if necessary
+        audio_channel_mask_t audioMask = channelMask == CHANNEL_MASK_USE_CHANNEL_ORDER ?
+                audio_channel_mask_from_count(numChannels) : channelMask;
+        if (0 == audioMask) {
+            return BAD_VALUE;
+        }
+
         mAudioTrack = new AudioTrack(
-                AUDIO_STREAM_MUSIC, mSampleRate, AUDIO_FORMAT_PCM_16_BIT,
-                (numChannels == 2)
-                    ? AUDIO_CHANNEL_OUT_STEREO
-                    : AUDIO_CHANNEL_OUT_MONO,
+                AUDIO_STREAM_MUSIC, mSampleRate, AUDIO_FORMAT_PCM_16_BIT, audioMask,
                 0, 0, &AudioCallback, this, 0);
 
         if ((err = mAudioTrack->initCheck()) != OK) {
@@ -418,6 +427,12 @@
                 break;
             }
 
+            if (mAudioSink != NULL) {
+                mLatencyUs = (int64_t)mAudioSink->latency() * 1000;
+            } else {
+                mLatencyUs = (int64_t)mAudioTrack->latency() * 1000;
+            }
+
             CHECK(mInputBuffer->meta_data()->findInt64(
                         kKeyTime, &mPositionTimeMediaUs));
 
diff --git a/media/libstagefright/MediaSourceSplitter.cpp b/media/libstagefright/MediaSourceSplitter.cpp
deleted file mode 100644
index 3b64ded..0000000
--- a/media/libstagefright/MediaSourceSplitter.cpp
+++ /dev/null
@@ -1,234 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-//#define LOG_NDEBUG 0
-#define LOG_TAG "MediaSourceSplitter"
-#include <utils/Log.h>
-
-#include <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/MediaSourceSplitter.h>
-#include <media/stagefright/MediaBuffer.h>
-#include <media/stagefright/MetaData.h>
-
-namespace android {
-
-MediaSourceSplitter::MediaSourceSplitter(sp<MediaSource> mediaSource) {
-    mNumberOfClients = 0;
-    mSource = mediaSource;
-    mSourceStarted = false;
-
-    mNumberOfClientsStarted = 0;
-    mNumberOfCurrentReads = 0;
-    mCurrentReadBit = 0;
-    mLastReadCompleted = true;
-}
-
-MediaSourceSplitter::~MediaSourceSplitter() {
-}
-
-sp<MediaSource> MediaSourceSplitter::createClient() {
-    Mutex::Autolock autoLock(mLock);
-
-    sp<MediaSource> client = new Client(this, mNumberOfClients++);
-    mClientsStarted.push(false);
-    mClientsDesiredReadBit.push(0);
-    return client;
-}
-
-status_t MediaSourceSplitter::start(int clientId, MetaData *params) {
-    Mutex::Autolock autoLock(mLock);
-
-    ALOGV("start client (%d)", clientId);
-    if (mClientsStarted[clientId]) {
-        return OK;
-    }
-
-    mNumberOfClientsStarted++;
-
-    if (!mSourceStarted) {
-        ALOGV("Starting real source from client (%d)", clientId);
-        status_t err = mSource->start(params);
-
-        if (err == OK) {
-            mSourceStarted = true;
-            mClientsStarted.editItemAt(clientId) = true;
-            mClientsDesiredReadBit.editItemAt(clientId) = !mCurrentReadBit;
-        }
-
-        return err;
-    } else {
-        mClientsStarted.editItemAt(clientId) = true;
-        if (mLastReadCompleted) {
-            // Last read was completed. So join in the threads for the next read.
-            mClientsDesiredReadBit.editItemAt(clientId) = !mCurrentReadBit;
-        } else {
-            // Last read is ongoing. So join in the threads for the current read.
-            mClientsDesiredReadBit.editItemAt(clientId) = mCurrentReadBit;
-        }
-        return OK;
-    }
-}
-
-status_t MediaSourceSplitter::stop(int clientId) {
-    Mutex::Autolock autoLock(mLock);
-
-    ALOGV("stop client (%d)", clientId);
-    CHECK(clientId >= 0 && clientId < mNumberOfClients);
-    CHECK(mClientsStarted[clientId]);
-
-    if (--mNumberOfClientsStarted == 0) {
-        ALOGV("Stopping real source from client (%d)", clientId);
-        status_t err = mSource->stop();
-        mSourceStarted = false;
-        mClientsStarted.editItemAt(clientId) = false;
-        return err;
-    } else {
-        mClientsStarted.editItemAt(clientId) = false;
-        if (!mLastReadCompleted && (mClientsDesiredReadBit[clientId] == mCurrentReadBit)) {
-            // !mLastReadCompleted implies that buffer has been read from source, but all
-            // clients haven't read it.
-            // mClientsDesiredReadBit[clientId] == mCurrentReadBit implies that this
-            // client would have wanted to read from this buffer. (i.e. it has not yet
-            // called read() for the current read buffer.)
-            // Since other threads may be waiting for all the clients' reads to complete,
-            // signal that this read has been aborted.
-            signalReadComplete_lock(true);
-        }
-        return OK;
-    }
-}
-
-sp<MetaData> MediaSourceSplitter::getFormat(int clientId) {
-    Mutex::Autolock autoLock(mLock);
-
-    ALOGV("getFormat client (%d)", clientId);
-    return mSource->getFormat();
-}
-
-status_t MediaSourceSplitter::read(int clientId,
-        MediaBuffer **buffer, const MediaSource::ReadOptions *options) {
-    Mutex::Autolock autoLock(mLock);
-
-    CHECK(clientId >= 0 && clientId < mNumberOfClients);
-
-    ALOGV("read client (%d)", clientId);
-    *buffer = NULL;
-
-    if (!mClientsStarted[clientId]) {
-        return OK;
-    }
-
-    if (mCurrentReadBit != mClientsDesiredReadBit[clientId]) {
-        // Desired buffer has not been read from source yet.
-
-        // If the current client is the special client with clientId = 0
-        // then read from source, else wait until the client 0 has finished
-        // reading from source.
-        if (clientId == 0) {
-            // Wait for all client's last read to complete first so as to not
-            // corrupt the buffer at mLastReadMediaBuffer.
-            waitForAllClientsLastRead_lock(clientId);
-
-            readFromSource_lock(options);
-            *buffer = mLastReadMediaBuffer;
-        } else {
-            waitForReadFromSource_lock(clientId);
-
-            *buffer = mLastReadMediaBuffer;
-            (*buffer)->add_ref();
-        }
-        CHECK(mCurrentReadBit == mClientsDesiredReadBit[clientId]);
-    } else {
-        // Desired buffer has already been read from source. Use the cached data.
-        CHECK(clientId != 0);
-
-        *buffer = mLastReadMediaBuffer;
-        (*buffer)->add_ref();
-    }
-
-    mClientsDesiredReadBit.editItemAt(clientId) = !mClientsDesiredReadBit[clientId];
-    signalReadComplete_lock(false);
-
-    return mLastReadStatus;
-}
-
-void MediaSourceSplitter::readFromSource_lock(const MediaSource::ReadOptions *options) {
-    mLastReadStatus = mSource->read(&mLastReadMediaBuffer , options);
-
-    mCurrentReadBit = !mCurrentReadBit;
-    mLastReadCompleted = false;
-    mReadFromSourceCondition.broadcast();
-}
-
-void MediaSourceSplitter::waitForReadFromSource_lock(int32_t clientId) {
-    mReadFromSourceCondition.wait(mLock);
-}
-
-void MediaSourceSplitter::waitForAllClientsLastRead_lock(int32_t clientId) {
-    if (mLastReadCompleted) {
-        return;
-    }
-    mAllReadsCompleteCondition.wait(mLock);
-    CHECK(mLastReadCompleted);
-}
-
-void MediaSourceSplitter::signalReadComplete_lock(bool readAborted) {
-    if (!readAborted) {
-        mNumberOfCurrentReads++;
-    }
-
-    if (mNumberOfCurrentReads == mNumberOfClientsStarted) {
-        mLastReadCompleted = true;
-        mNumberOfCurrentReads = 0;
-        mAllReadsCompleteCondition.broadcast();
-    }
-}
-
-status_t MediaSourceSplitter::pause(int clientId) {
-    return ERROR_UNSUPPORTED;
-}
-
-// Client
-
-MediaSourceSplitter::Client::Client(
-        sp<MediaSourceSplitter> splitter,
-        int32_t clientId) {
-    mSplitter = splitter;
-    mClientId = clientId;
-}
-
-status_t MediaSourceSplitter::Client::start(MetaData *params) {
-    return mSplitter->start(mClientId, params);
-}
-
-status_t MediaSourceSplitter::Client::stop() {
-    return mSplitter->stop(mClientId);
-}
-
-sp<MetaData> MediaSourceSplitter::Client::getFormat() {
-    return mSplitter->getFormat(mClientId);
-}
-
-status_t MediaSourceSplitter::Client::read(
-        MediaBuffer **buffer, const ReadOptions *options) {
-    return mSplitter->read(mClientId, buffer, options);
-}
-
-status_t MediaSourceSplitter::Client::pause() {
-    return mSplitter->pause(mClientId);
-}
-
-}  // namespace android
diff --git a/media/libstagefright/TimedEventQueue.cpp b/media/libstagefright/TimedEventQueue.cpp
index f4b5d4f..6d345bb 100644
--- a/media/libstagefright/TimedEventQueue.cpp
+++ b/media/libstagefright/TimedEventQueue.cpp
@@ -26,8 +26,6 @@
 
 #include "include/TimedEventQueue.h"
 
-#include <cutils/sched_policy.h>
-
 #include <sys/prctl.h>
 #include <sys/time.h>
 
diff --git a/media/libstagefright/codecs/m4v_h263/dec/src/vop.cpp b/media/libstagefright/codecs/m4v_h263/dec/src/vop.cpp
index 74fe478..b3c350f 100644
--- a/media/libstagefright/codecs/m4v_h263/dec/src/vop.cpp
+++ b/media/libstagefright/codecs/m4v_h263/dec/src/vop.cpp
@@ -1041,7 +1041,7 @@
     /* Marker Bit */
     if (!BitstreamRead1Bits(stream))
     {
-        mp4dec_log("DecodeShortHeader(): Market bit wrong.\n");
+        mp4dec_log("DecodeShortHeader(): Marker bit wrong.\n");
         status = PV_FAIL;
         goto return_point;
     }
diff --git a/opengl/libs/GLES_trace/dev.make b/opengl/libs/GLES_trace/dev.make
index 1d89999..a46260c 100644
--- a/opengl/libs/GLES_trace/dev.make
+++ b/opengl/libs/GLES_trace/dev.make
@@ -6,10 +6,9 @@
 	aprotoc --cpp_out=src --java_out=java gltrace.proto
 	mv src/gltrace.pb.cc src/gltrace.pb.cpp
 
-# NOTE: $OUT should be defined in the shell by doing a "lunch <config>"
-# push updated files to device
-push:
-	adb push $(OUT)/system/lib/libGLESv2.so /system/lib/
-	adb push $(OUT)/system/lib/libGLESv1_CM.so /system/lib/
-	adb push $(OUT)/system/lib/libGLES_trace.so /system/lib/
-	adb push $(OUT)/system/lib/libEGL.so /system/lib/
+sync:
+	adb root
+	adb remount
+	adb shell stop
+	adb sync
+	adb shell start
diff --git a/opengl/libs/GLES_trace/gltrace.proto b/opengl/libs/GLES_trace/gltrace.proto
index 2893e6e..bbf3554 100644
--- a/opengl/libs/GLES_trace/gltrace.proto
+++ b/opengl/libs/GLES_trace/gltrace.proto
@@ -510,7 +510,7 @@
         eglGetSystemTimeNV = 2045;
 
         invalid = 3000;
-        frameBufferContents = 3001;
+        glVertexAttribPointerData = 3001;
     }
 
     // A GL call's return data and arguments are formatted into this DataType
diff --git a/opengl/libs/GLES_trace/src/gltrace.pb.cpp b/opengl/libs/GLES_trace/src/gltrace.pb.cpp
index d5f8180..d587c49 100644
--- a/opengl/libs/GLES_trace/src/gltrace.pb.cpp
+++ b/opengl/libs/GLES_trace/src/gltrace.pb.cpp
@@ -1018,7 +1018,7 @@
 const GLMessage_Function GLMessage::eglGetSystemTimeFrequencyNV;
 const GLMessage_Function GLMessage::eglGetSystemTimeNV;
 const GLMessage_Function GLMessage::invalid;
-const GLMessage_Function GLMessage::frameBufferContents;
+const GLMessage_Function GLMessage::glVertexAttribPointerData;
 const GLMessage_Function GLMessage::Function_MIN;
 const GLMessage_Function GLMessage::Function_MAX;
 const int GLMessage::Function_ARRAYSIZE;
diff --git a/opengl/libs/GLES_trace/src/gltrace.pb.h b/opengl/libs/GLES_trace/src/gltrace.pb.h
index a4fcbd3..0901be7 100644
--- a/opengl/libs/GLES_trace/src/gltrace.pb.h
+++ b/opengl/libs/GLES_trace/src/gltrace.pb.h
@@ -535,11 +535,11 @@
   GLMessage_Function_eglGetSystemTimeFrequencyNV = 2044,
   GLMessage_Function_eglGetSystemTimeNV = 2045,
   GLMessage_Function_invalid = 3000,
-  GLMessage_Function_frameBufferContents = 3001
+  GLMessage_Function_glVertexAttribPointerData = 3001
 };
 bool GLMessage_Function_IsValid(int value);
 const GLMessage_Function GLMessage_Function_Function_MIN = GLMessage_Function_glActiveTexture;
-const GLMessage_Function GLMessage_Function_Function_MAX = GLMessage_Function_frameBufferContents;
+const GLMessage_Function GLMessage_Function_Function_MAX = GLMessage_Function_glVertexAttribPointerData;
 const int GLMessage_Function_Function_ARRAYSIZE = GLMessage_Function_Function_MAX + 1;
 
 // ===================================================================
@@ -1351,7 +1351,7 @@
   static const Function eglGetSystemTimeFrequencyNV = GLMessage_Function_eglGetSystemTimeFrequencyNV;
   static const Function eglGetSystemTimeNV = GLMessage_Function_eglGetSystemTimeNV;
   static const Function invalid = GLMessage_Function_invalid;
-  static const Function frameBufferContents = GLMessage_Function_frameBufferContents;
+  static const Function glVertexAttribPointerData = GLMessage_Function_glVertexAttribPointerData;
   static inline bool Function_IsValid(int value) {
     return GLMessage_Function_IsValid(value);
   }
diff --git a/opengl/libs/GLES_trace/src/gltrace_context.cpp b/opengl/libs/GLES_trace/src/gltrace_context.cpp
index 65b7662..45dbb43 100644
--- a/opengl/libs/GLES_trace/src/gltrace_context.cpp
+++ b/opengl/libs/GLES_trace/src/gltrace_context.cpp
@@ -129,13 +129,14 @@
     return mPerContextState[c];
 }
 
-GLTraceContext::GLTraceContext(int id, GLTraceState *state, BufferedOutputStream *stream) {
-    mId = id;
-    mState = state;
-
+GLTraceContext::GLTraceContext(int id, GLTraceState *state, BufferedOutputStream *stream) :
+    mId(id),
+    mState(state),
+    mBufferedOutputStream(stream),
+    mElementArrayBuffers(DefaultKeyedVector<GLuint, ElementArrayBuffer*>(NULL))
+{
     fbcontents = fbcompressed = NULL;
     fbcontentsSize = 0;
-    mBufferedOutputStream = stream;
 }
 
 int GLTraceContext::getId() {
@@ -208,5 +209,74 @@
     }
 }
 
+void GLTraceContext::bindBuffer(GLuint bufferId, GLvoid *data, GLsizeiptr size) {
+    // free previously bound buffer if any
+    ElementArrayBuffer *oldBuffer = mElementArrayBuffers.valueFor(bufferId);
+    if (oldBuffer != NULL) {
+        delete oldBuffer;
+    }
+
+    mElementArrayBuffers.add(bufferId, new ElementArrayBuffer(data, size));
+}
+
+void GLTraceContext::getBuffer(GLuint bufferId, GLvoid **data, GLsizeiptr *size) {
+    ElementArrayBuffer *buffer = mElementArrayBuffers.valueFor(bufferId);
+    if (buffer == NULL) {
+        *data = NULL;
+        *size = 0;
+    } else {
+        *data = buffer->getBuffer();
+        *size = buffer->getSize();
+    }
+}
+
+void GLTraceContext::updateBufferSubData(GLuint bufferId, GLintptr offset, GLvoid *data,
+                                                            GLsizeiptr size) {
+    ElementArrayBuffer *buffer = mElementArrayBuffers.valueFor(bufferId);
+    if (buffer != NULL) {
+        buffer->updateSubBuffer(offset, data, size);
+    }
+}
+
+void GLTraceContext::deleteBuffer(GLuint bufferId) {
+    ElementArrayBuffer *buffer = mElementArrayBuffers.valueFor(bufferId);
+    if (buffer != NULL) {
+        delete buffer;
+        mElementArrayBuffers.removeItem(bufferId);
+    }
+}
+
+ElementArrayBuffer::ElementArrayBuffer(GLvoid *buf, GLsizeiptr size) {
+    mBuf = malloc(size);
+    mSize = size;
+
+    if (buf != NULL) {
+        memcpy(mBuf, buf, size);
+    }
+}
+
+ElementArrayBuffer::~ElementArrayBuffer() {
+    if (mBuf != NULL) {
+        free(mBuf);
+        mSize = 0;
+    }
+
+    mBuf = NULL;
+}
+
+void ElementArrayBuffer::updateSubBuffer(GLintptr offset, const GLvoid* data, GLsizeiptr size) {
+    if (offset + size <= mSize) {
+        memcpy((char*)mBuf + offset, data, size);
+    }
+}
+
+GLvoid *ElementArrayBuffer::getBuffer() {
+    return mBuf;
+}
+
+GLsizeiptr ElementArrayBuffer::getSize() {
+    return mSize;
+}
+
 }; // namespace gltrace
 }; // namespace android
diff --git a/opengl/libs/GLES_trace/src/gltrace_context.h b/opengl/libs/GLES_trace/src/gltrace_context.h
index 129116a..323cfdc 100644
--- a/opengl/libs/GLES_trace/src/gltrace_context.h
+++ b/opengl/libs/GLES_trace/src/gltrace_context.h
@@ -19,6 +19,7 @@
 
 #include <map>
 #include <pthread.h>
+#include <utils/KeyedVector.h>
 
 #include "hooks.h"
 #include "gltrace_transport.h"
@@ -32,6 +33,20 @@
 
 class GLTraceState;
 
+class ElementArrayBuffer {
+    GLvoid *mBuf;
+    GLsizeiptr mSize;
+
+public:
+    ElementArrayBuffer():mBuf(NULL), mSize(0) {}
+    ElementArrayBuffer(GLvoid *buf, GLsizeiptr size);
+    ~ElementArrayBuffer();
+
+    void updateSubBuffer(GLintptr offset, const GLvoid* data, GLsizeiptr size);
+    GLvoid *getBuffer();
+    GLsizeiptr getSize();
+};
+
 /** GL Trace Context info associated with each EGLContext */
 class GLTraceContext {
     int mId;                    /* unique context id */
@@ -43,6 +58,9 @@
 
     BufferedOutputStream *mBufferedOutputStream; /* stream where trace info is sent */
 
+    /* list of element array buffers in use. */
+    DefaultKeyedVector<GLuint, ElementArrayBuffer*> mElementArrayBuffers;
+
     void resizeFBMemory(unsigned minSize);
 public:
     gl_hooks_t *hooks;
@@ -53,6 +71,13 @@
     void getCompressedFB(void **fb, unsigned *fbsize,
                             unsigned *fbwidth, unsigned *fbheight,
                             FBBinding fbToRead);
+
+    // Methods to work with element array buffers
+    void bindBuffer(GLuint bufferId, GLvoid *data, GLsizeiptr size);
+    void getBuffer(GLuint bufferId, GLvoid **data, GLsizeiptr *size);
+    void updateBufferSubData(GLuint bufferId, GLintptr offset, GLvoid *data, GLsizeiptr size);
+    void deleteBuffer(GLuint bufferId);
+
     void traceGLMessage(GLMessage *msg);
 };
 
diff --git a/opengl/libs/GLES_trace/src/gltrace_fixup.cpp b/opengl/libs/GLES_trace/src/gltrace_fixup.cpp
index c69ba5e1..3597b26 100644
--- a/opengl/libs/GLES_trace/src/gltrace_fixup.cpp
+++ b/opengl/libs/GLES_trace/src/gltrace_fixup.cpp
@@ -193,7 +193,7 @@
                         GLint border,
                         GLenum format,
                         GLenum type,
-                        const GLvoid *data); 
+                        const GLvoid *data);
     */
     int widthIndex = 3;
     int heightIndex = 4;
@@ -218,7 +218,7 @@
 }
 
 void fixup_glShaderSource(GLMessage *glmsg, void *pointersToFixup[]) {
-    /* void glShaderSource(GLuint shader, GLsizei count, const GLchar** string, 
+    /* void glShaderSource(GLuint shader, GLsizei count, const GLchar** string,
                                     const GLint* length) */
     GLMessage_DataType arg_count  = glmsg->args(1);
     GLMessage_DataType arg_lenp   = glmsg->args(3);
@@ -256,33 +256,13 @@
 }
 
 void fixup_glUniformMatrixGeneric(int matrixSize, GLMessage *glmsg, void *pointersToFixup[]) {
-    /* void glUniformMatrix?fv(GLint location, GLsizei count, GLboolean transpose, 
+    /* void glUniformMatrix?fv(GLint location, GLsizei count, GLboolean transpose,
                                                                 const GLfloat* value) */
     GLMessage_DataType arg_count  = glmsg->args(1);
     int n_matrices = arg_count.intvalue(0);
     fixup_glUniformGeneric(3, matrixSize * matrixSize * n_matrices, glmsg, pointersToFixup[0]);
 }
 
-void fixup_glBufferData(int sizeIndex, int dataIndex, GLMessage *glmsg, void *pointersToFixup[]) {
-    /* void glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data) */
-    /* void glBufferData(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage) */
-    GLsizeiptr size = glmsg->args(sizeIndex).intvalue(0);
-
-    GLMessage_DataType *arg_datap = glmsg->mutable_args(dataIndex);
-    GLvoid *datap = (GLvoid *) pointersToFixup[0];
-
-    if (datap == NULL) {
-        // glBufferData can be called with a NULL data pointer
-        return;
-    }
-
-    arg_datap->set_type(GLMessage::DataType::VOID);
-    arg_datap->set_isarray(true);
-    arg_datap->clear_intvalue();
-
-    arg_datap->add_rawbytes(datap, size);
-}
-
 void fixup_glGenGeneric(GLMessage *glmsg, void *pointersToFixup[]) {
     /* void glGen*(GLsizei n, GLuint * buffers); */
     GLMessage_DataType arg_n  = glmsg->args(0);
@@ -375,7 +355,7 @@
     }
 }
 
-void fixup_glGetActiveAttribOrUniform(GLTraceContext *context, GLMessage *glmsg, 
+void fixup_glGetActiveAttribOrUniform(GLTraceContext *context, GLMessage *glmsg,
                                                                 void *pointersToFixup[]) {
     /* void glGetActiveAttrib(GLuint program, GLuint index, GLsizei bufsize,
                 GLsizei* length, GLint* size, GLenum* type, GLchar* name); */
@@ -400,6 +380,303 @@
     arg_location->add_intvalue(location);
 }
 
+GLint glGetInteger(GLTraceContext *context, GLenum param) {
+    GLint x;
+    context->hooks->gl.glGetIntegerv(param, &x);
+    return x;
+}
+
+GLint glGetVertexAttrib(GLTraceContext *context, GLuint index, GLenum pname) {
+    GLint x;
+    context->hooks->gl.glGetVertexAttribiv(index, pname, &x);
+    return x;
+}
+
+bool isUsingArrayBuffers(GLTraceContext *context) {
+    return glGetInteger(context, GL_ARRAY_BUFFER_BINDING) != 0;
+}
+
+bool isUsingElementArrayBuffers(GLTraceContext *context) {
+    return glGetInteger(context, GL_ELEMENT_ARRAY_BUFFER_BINDING) != 0;
+}
+
+/** Copy @len bytes of data from @src into the @dataIndex'th argument of the message. */
+void addGlBufferData(GLMessage *glmsg, int dataIndex, GLvoid *src, GLsizeiptr len) {
+    GLMessage_DataType *arg_datap = glmsg->mutable_args(dataIndex);
+    arg_datap->set_type(GLMessage::DataType::VOID);
+    arg_datap->set_isarray(true);
+    arg_datap->clear_intvalue();
+    arg_datap->add_rawbytes(src, len);
+}
+
+void fixup_glBufferData(GLTraceContext *context, GLMessage *glmsg, void *pointersToFixup[]) {
+    /* void glBufferData(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage) */
+    GLsizeiptr size = glmsg->args(1).intvalue(0);
+    GLvoid *datap = (GLvoid *) pointersToFixup[0];
+
+    // Save element array buffers for future use to fixup glVertexAttribPointers
+    // when a glDrawElements() call is performed.
+    GLenum target = glmsg->args(0).intvalue(0);
+    if (target == GL_ELEMENT_ARRAY_BUFFER) {
+        GLint bufferId = glGetInteger(context, GL_ELEMENT_ARRAY_BUFFER_BINDING);
+        context->bindBuffer(bufferId, datap, size);
+    }
+
+    // add buffer data to the protobuf message
+    if (datap != NULL) {
+        addGlBufferData(glmsg, 2, datap, size);
+    }
+}
+
+void fixup_glBufferSubData(GLTraceContext *context, GLMessage *glmsg, void *pointersToFixup[]) {
+    /* void glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data) */
+    GLenum target = glmsg->args(0).intvalue(0);
+    GLintptr offset = glmsg->args(1).intvalue(0);
+    GLsizeiptr size = glmsg->args(2).intvalue(0);
+    GLvoid *datap = (GLvoid *) pointersToFixup[0];
+    if (target == GL_ELEMENT_ARRAY_BUFFER) {
+        GLint bufferId = glGetInteger(context, GL_ELEMENT_ARRAY_BUFFER_BINDING);
+        context->updateBufferSubData(bufferId, offset, datap, size);
+    }
+
+    // add buffer data to the protobuf message
+    addGlBufferData(glmsg, 3, datap, size);
+}
+
+/** Obtain the size of each vertex attribute. */
+int vertexAttribSize(GLenum type, GLsizei numComponents) {
+    int sizePerComponent;
+
+    switch(type) {
+    case GL_BYTE:
+    case GL_UNSIGNED_BYTE:
+        sizePerComponent = 1;
+        break;
+    case GL_SHORT:
+    case GL_UNSIGNED_SHORT:
+        sizePerComponent = 2;
+        break;
+    case GL_FIXED:
+    case GL_FLOAT:
+    default:
+        sizePerComponent = 4;
+        break;
+    }
+
+    return sizePerComponent * numComponents;
+}
+
+/** Create and send a glVertexAttribPointerData trace message to the host. */
+void trace_glVertexAttribPointerData(GLTraceContext *context,
+                    GLuint indx, GLint size, GLenum type,
+                    GLboolean normalized, GLsizei stride, const GLvoid* ptr,
+                    GLuint minIndex, GLuint maxIndex, nsecs_t startTime) {
+    /* void glVertexAttribPointerData(GLuint indx, GLint size, GLenum type,
+                    GLboolean normalized, GLsizei stride, const GLvoid* ptr,
+                    int minIndex, int maxIndex) */
+    GLMessage glmsg;
+    GLTraceContext *glContext = context;
+
+    glmsg.set_function(GLMessage::glVertexAttribPointerData);
+
+    // copy argument indx
+    GLMessage_DataType *arg_indx = glmsg.add_args();
+    arg_indx->set_isarray(false);
+    arg_indx->set_type(GLMessage::DataType::INT);
+    arg_indx->add_intvalue(indx);
+
+    // copy argument size
+    GLMessage_DataType *arg_size = glmsg.add_args();
+    arg_size->set_isarray(false);
+    arg_size->set_type(GLMessage::DataType::INT);
+    arg_size->add_intvalue(size);
+
+    // copy argument type
+    GLMessage_DataType *arg_type = glmsg.add_args();
+    arg_type->set_isarray(false);
+    arg_type->set_type(GLMessage::DataType::ENUM);
+    arg_type->add_intvalue((int)type);
+
+    // copy argument normalized
+    GLMessage_DataType *arg_normalized = glmsg.add_args();
+    arg_normalized->set_isarray(false);
+    arg_normalized->set_type(GLMessage::DataType::BOOL);
+    arg_normalized->add_boolvalue(normalized);
+
+    // copy argument stride
+    GLMessage_DataType *arg_stride = glmsg.add_args();
+    arg_stride->set_isarray(false);
+    arg_stride->set_type(GLMessage::DataType::INT);
+    arg_stride->add_intvalue(stride);
+
+    // copy argument ptr
+    GLMessage_DataType *arg_ptr = glmsg.add_args();
+    arg_ptr->set_isarray(true);
+    arg_ptr->set_type(GLMessage::DataType::BYTE);
+    int perVertexSize = vertexAttribSize(type, size);
+    GLchar *p = (GLchar*) ptr;
+    std::string data;
+    for (GLuint i = minIndex; i < maxIndex; i++) {
+        data.append(p, perVertexSize);
+        p += stride == 0 ? perVertexSize : stride;
+    }
+    arg_ptr->add_rawbytes(data);
+
+    // copy argument min index
+    GLMessage_DataType *arg_min = glmsg.add_args();
+    arg_min->set_isarray(false);
+    arg_min->set_type(GLMessage::DataType::INT);
+    arg_min->add_intvalue(minIndex);
+
+    // copy argument max index
+    GLMessage_DataType *arg_max = glmsg.add_args();
+    arg_max->set_isarray(false);
+    arg_max->set_type(GLMessage::DataType::INT);
+    arg_max->add_intvalue(maxIndex);
+
+    glmsg.set_context_id(context->getId());
+    glmsg.set_start_time(startTime);
+    glmsg.set_threadtime(0);
+    glmsg.set_duration(0);
+
+    context->traceGLMessage(&glmsg);
+}
+
+void findMinAndMaxIndices(GLvoid *indices, GLsizei count, GLenum type,
+                            GLuint *minIndex, GLuint *maxIndex) {
+    GLuint index;
+    *minIndex = UINT_MAX;
+    *maxIndex = 0;
+
+    if (indices == NULL) {
+        return;
+    }
+
+    for (GLsizei i = 0; i < count; i++) {
+        if (type == GL_UNSIGNED_BYTE) {
+            index = *((GLubyte*) indices + i);
+        } else {
+            index = *((GLushort*) indices + i);
+        }
+
+        if (index < *minIndex) *minIndex = index;
+        if (index > *maxIndex) *maxIndex = index;
+    }
+}
+
+void trace_VertexAttribPointerData(GLTraceContext *context,
+                            GLuint minIndex, GLuint maxIndex, nsecs_t time) {
+    GLuint maxAttribs = glGetInteger(context, GL_MAX_VERTEX_ATTRIBS);
+    for (GLuint index = 0; index < maxAttribs; index++) {
+        if (!glGetVertexAttrib(context, index, GL_VERTEX_ATTRIB_ARRAY_ENABLED)) {
+            // vertex array disabled
+            continue;
+        }
+
+        if (glGetVertexAttrib(context, index, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING)) {
+            // vbo
+            continue;
+        }
+
+        GLint size = glGetVertexAttrib(context, index, GL_VERTEX_ATTRIB_ARRAY_SIZE);
+        GLenum type = glGetVertexAttrib(context, index, GL_VERTEX_ATTRIB_ARRAY_TYPE);
+        GLboolean norm = glGetVertexAttrib(context, index, GL_VERTEX_ATTRIB_ARRAY_NORMALIZED);
+        GLsizei stride = glGetVertexAttrib(context, index, GL_VERTEX_ATTRIB_ARRAY_STRIDE);
+        GLvoid* ptr;
+        context->hooks->gl.glGetVertexAttribPointerv(index, GL_VERTEX_ATTRIB_ARRAY_POINTER, &ptr);
+
+        trace_glVertexAttribPointerData(context,
+                    index, size, type, norm, stride, ptr,
+                    minIndex, maxIndex, time);
+    }
+}
+
+void trace_VertexAttribPointerDataForGlDrawArrays(GLTraceContext *context, GLMessage *glmsg) {
+    /* void glDrawArrays(GLenum mode, GLint first, GLsizei count) */
+    GLsizei count = glmsg->args(2).intvalue(0);
+
+    // Vertex attrib pointer data patchup calls should appear as if
+    // they occurred right before the draw call.
+    nsecs_t time = glmsg->start_time() - 1;
+
+    trace_VertexAttribPointerData(context, 0, count, time);
+}
+
+void trace_VertexAttribPointerDataForGlDrawElements(GLTraceContext *context, GLMessage *glmsg,
+                            GLvoid *indices) {
+    /* void glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices) */
+    GLsizei count = glmsg->args(1).intvalue(0);
+    GLenum type = glmsg->args(2).intvalue(0);
+    GLuint index;
+
+    GLuint minIndex, maxIndex;
+
+    // The index buffer is either passed in as an argument to the glDrawElements() call,
+    // or it is stored in the current GL_ELEMENT_ARRAY_BUFFER.
+    GLvoid *indexBuffer;
+    if (isUsingElementArrayBuffers(context)) {
+        GLsizeiptr eaBufferSize;
+        GLuint bufferId = glGetInteger(context, GL_ELEMENT_ARRAY_BUFFER_BINDING);
+        context->getBuffer(bufferId, &indexBuffer, &eaBufferSize);
+    } else {
+        indexBuffer = indices;
+    }
+
+    // Rather than sending vertex attribute data that corresponds to the indices
+    // being drawn, we send the vertex attribute data for the entire range of
+    // indices being drawn, including the ones not drawn. The min & max indices
+    // provide the range of indices being drawn.
+    findMinAndMaxIndices(indexBuffer, count, type, &minIndex, &maxIndex);
+
+    // Vertex attrib pointer data patchup calls should appear as if
+    // they occurred right before the draw call.
+    nsecs_t time = glmsg->start_time() - 1;
+
+    trace_VertexAttribPointerData(context, minIndex, maxIndex + 1, time);
+}
+
+void fixup_glDrawArrays(GLTraceContext *context, GLMessage *glmsg) {
+    // Trace all vertex attribute data stored in client space.
+    trace_VertexAttribPointerDataForGlDrawArrays(context, glmsg);
+
+    // Attach the FB if requested
+    if (context->getGlobalTraceState()->shouldCollectFbOnGlDraw()) {
+        fixup_addFBContents(context, glmsg, CURRENTLY_BOUND_FB);
+    }
+}
+
+void fixup_glDrawElements(GLTraceContext *context, GLMessage *glmsg, void *pointersToFixup[]) {
+    /* void glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices) */
+    GLvoid *indices = pointersToFixup[0];
+    GLenum type = glmsg->args(2).intvalue(0);
+    GLsizei count = glmsg->args(1).intvalue(0);
+    GLuint index;
+
+    // Trace all vertex attribute data stored in client space.
+    trace_VertexAttribPointerDataForGlDrawElements(context, glmsg, indices);
+
+    // Fixup indices argument
+    if (!isUsingElementArrayBuffers(context)) {
+        GLMessage_DataType *arg_indices = glmsg->mutable_args(3);
+        arg_indices->set_isarray(true);
+        arg_indices->clear_intvalue();
+        arg_indices->set_type(GLMessage::DataType::INT);
+        for (GLsizei i = 0; i < count; i++) {
+            if (type == GL_UNSIGNED_BYTE) {
+                index = *((GLubyte*) indices + i);
+            } else {
+                index = *((GLushort*) indices + i);
+            }
+            arg_indices->add_intvalue(index);
+        }
+    }
+
+    // Attach the FB if requested
+    if (context->getGlobalTraceState()->shouldCollectFbOnGlDraw()) {
+        fixup_addFBContents(context, glmsg, CURRENTLY_BOUND_FB);
+    }
+}
+
 void fixupGLMessage(GLTraceContext *context, nsecs_t wallStart, nsecs_t wallEnd,
                                              nsecs_t threadStart, nsecs_t threadEnd,
                                              GLMessage *glmsg, void *pointersToFixup[]) {
@@ -438,8 +715,8 @@
         /* void glBindAttribLocation(GLuint program, GLuint index, const GLchar* name); */
         fixup_CStringPtr(2, glmsg, pointersToFixup[0]);
         break;
-    case GLMessage::glGetAttribLocation:  
-    case GLMessage::glGetUniformLocation: 
+    case GLMessage::glGetAttribLocation:
+    case GLMessage::glGetUniformLocation:
         /* int glGetAttribLocation(GLuint program, const GLchar* name) */
         /* int glGetUniformLocation(GLuint program, const GLchar* name) */
         fixup_CStringPtr(1, glmsg, pointersToFixup[0]);
@@ -526,23 +803,19 @@
         break;
     case GLMessage::glBufferData:
         /* void glBufferData(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage) */
-        fixup_glBufferData(1, 2, glmsg, pointersToFixup);
+        fixup_glBufferData(context, glmsg, pointersToFixup);
         break;
     case GLMessage::glBufferSubData:
         /* void glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data) */
-        fixup_glBufferData(2, 3, glmsg, pointersToFixup);
+        fixup_glBufferSubData(context, glmsg, pointersToFixup);
         break;
     case GLMessage::glDrawArrays:
         /* void glDrawArrays(GLenum mode, GLint first, GLsizei count) */
-        if (context->getGlobalTraceState()->shouldCollectFbOnGlDraw()) {
-            fixup_addFBContents(context, glmsg, CURRENTLY_BOUND_FB);
-        }
+        fixup_glDrawArrays(context, glmsg);
         break;
     case GLMessage::glDrawElements:
         /* void glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices) */
-        if (context->getGlobalTraceState()->shouldCollectFbOnGlDraw()) {
-            fixup_addFBContents(context, glmsg, CURRENTLY_BOUND_FB);
-        }
+        fixup_glDrawElements(context, glmsg, pointersToFixup);
         break;
     case GLMessage::glPushGroupMarkerEXT:
         /* void PushGroupMarkerEXT(sizei length, const char *marker); */
diff --git a/opengl/tests/angeles/Android.mk b/opengl/tests/angeles/Android.mk
index 84b754b..ae4f76d 100644
--- a/opengl/tests/angeles/Android.mk
+++ b/opengl/tests/angeles/Android.mk
@@ -4,7 +4,7 @@
 include $(CLEAR_VARS)
 LOCAL_SRC_FILES:= app-linux.cpp demo.c.arm
 LOCAL_SHARED_LIBRARIES := libEGL libGLESv1_CM libui
-LOCAL_C_INCLUDES += frameworks/base/opengl/tests/include
+LOCAL_C_INCLUDES += $(call include-path-for, opengl-tests-includes)
 LOCAL_MODULE:= angeles
 LOCAL_MODULE_TAGS := optional
 include $(BUILD_EXECUTABLE)
diff --git a/opengl/tests/fillrate/Android.mk b/opengl/tests/fillrate/Android.mk
index 835f858..4dade21 100644
--- a/opengl/tests/fillrate/Android.mk
+++ b/opengl/tests/fillrate/Android.mk
@@ -11,7 +11,7 @@
     libGLESv1_CM \
     libui
 
-LOCAL_C_INCLUDES += frameworks/base/opengl/tests/include
+LOCAL_C_INCLUDES += $(call include-path-for, opengl-tests-includes)
 
 LOCAL_MODULE:= test-opengl-fillrate
 
diff --git a/opengl/tests/filter/Android.mk b/opengl/tests/filter/Android.mk
index d780362..d3e4d38 100644
--- a/opengl/tests/filter/Android.mk
+++ b/opengl/tests/filter/Android.mk
@@ -10,7 +10,7 @@
     libGLESv1_CM \
     libui
 
-LOCAL_C_INCLUDES += frameworks/base/opengl/tests/include
+LOCAL_C_INCLUDES += $(call include-path-for, opengl-tests-includes)
 
 LOCAL_MODULE:= test-opengl-filter
 
diff --git a/opengl/tests/finish/Android.mk b/opengl/tests/finish/Android.mk
index 8f4f9c3..aa8adca 100644
--- a/opengl/tests/finish/Android.mk
+++ b/opengl/tests/finish/Android.mk
@@ -11,7 +11,7 @@
     libGLESv1_CM \
     libui
 
-LOCAL_C_INCLUDES += frameworks/base/opengl/tests/include
+LOCAL_C_INCLUDES += $(call include-path-for, opengl-tests-includes)
 
 LOCAL_MODULE:= test-opengl-finish
 
diff --git a/opengl/tests/gl2_basic/Android.mk b/opengl/tests/gl2_basic/Android.mk
index 07469a0..d7819a1 100644
--- a/opengl/tests/gl2_basic/Android.mk
+++ b/opengl/tests/gl2_basic/Android.mk
@@ -10,7 +10,7 @@
     libGLESv2 \
     libui
 
-LOCAL_C_INCLUDES += frameworks/base/opengl/tests/include
+LOCAL_C_INCLUDES += $(call include-path-for, opengl-tests-includes)
 
 LOCAL_MODULE:= test-opengl-gl2_basic
 
diff --git a/opengl/tests/gl2_copyTexImage/Android.mk b/opengl/tests/gl2_copyTexImage/Android.mk
index b616428..005c383 100644
--- a/opengl/tests/gl2_copyTexImage/Android.mk
+++ b/opengl/tests/gl2_copyTexImage/Android.mk
@@ -10,7 +10,7 @@
     libGLESv2 \
     libui
 
-LOCAL_C_INCLUDES += frameworks/base/opengl/tests/include
+LOCAL_C_INCLUDES += $(call include-path-for, opengl-tests-includes)
 
 LOCAL_MODULE:= test-opengl-gl2_copyTexImage
 
diff --git a/opengl/tests/gl2_yuvtex/Android.mk b/opengl/tests/gl2_yuvtex/Android.mk
index e36f319..7d43759 100644
--- a/opengl/tests/gl2_yuvtex/Android.mk
+++ b/opengl/tests/gl2_yuvtex/Android.mk
@@ -10,7 +10,7 @@
     libGLESv2 \
     libui
 
-LOCAL_C_INCLUDES += frameworks/base/opengl/tests/include
+LOCAL_C_INCLUDES += $(call include-path-for, opengl-tests-includes)
 
 LOCAL_MODULE:= test-opengl-gl2_yuvtex
 
diff --git a/opengl/tests/gl_basic/Android.mk b/opengl/tests/gl_basic/Android.mk
index 2ba327b..46bcc60 100644
--- a/opengl/tests/gl_basic/Android.mk
+++ b/opengl/tests/gl_basic/Android.mk
@@ -10,7 +10,7 @@
     libGLESv1_CM \
     libui
 
-LOCAL_C_INCLUDES += frameworks/base/opengl/tests/include
+LOCAL_C_INCLUDES += $(call include-path-for, opengl-tests-includes)
 
 LOCAL_MODULE:= test-opengl-gl_basic
 
diff --git a/opengl/tests/gl_perf/Android.mk b/opengl/tests/gl_perf/Android.mk
index f32abd3..cfca089 100644
--- a/opengl/tests/gl_perf/Android.mk
+++ b/opengl/tests/gl_perf/Android.mk
@@ -11,7 +11,7 @@
     libGLESv2 \
     libui
 
-LOCAL_C_INCLUDES += frameworks/base/opengl/tests/include
+LOCAL_C_INCLUDES += $(call include-path-for, opengl-tests-includes)
 
 LOCAL_MODULE:= test-opengl-gl2_perf
 
diff --git a/opengl/tests/gl_yuvtex/Android.mk b/opengl/tests/gl_yuvtex/Android.mk
index 5b87f2e..9e5dba0 100644
--- a/opengl/tests/gl_yuvtex/Android.mk
+++ b/opengl/tests/gl_yuvtex/Android.mk
@@ -10,7 +10,7 @@
     libGLESv1_CM \
     libui
 
-LOCAL_C_INCLUDES += frameworks/base/opengl/tests/include
+LOCAL_C_INCLUDES += $(call include-path-for, opengl-tests-includes)
 
 LOCAL_MODULE:= test-opengl-gl_yuvtex
 
diff --git a/opengl/tests/hwc/Android.mk b/opengl/tests/hwc/Android.mk
index e4d7e28..9eb58b1 100644
--- a/opengl/tests/hwc/Android.mk
+++ b/opengl/tests/hwc/Android.mk
@@ -22,8 +22,7 @@
     bionic \
     bionic/libstdc++/include \
     external/stlport/stlport \
-    frameworks/base/opengl/tests \
-    frameworks/base/opengl/tests/include \
+	$(call include-path-for, opengl-tests-includes)
 
 LOCAL_CFLAGS := -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
 
@@ -51,8 +50,7 @@
 LOCAL_C_INCLUDES += \
     system/extras/tests/include \
     hardware/libhardware/include \
-    frameworks/base/opengl/tests \
-    frameworks/base/opengl/tests/include \
+	$(call include-path-for, opengl-tests-includes)
 
 LOCAL_CFLAGS := -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
 
@@ -83,8 +81,7 @@
 LOCAL_C_INCLUDES += \
     system/extras/tests/include \
     hardware/libhardware/include \
-    frameworks/base/opengl/tests \
-    frameworks/base/opengl/tests/include \
+	$(call include-path-for, opengl-tests-includes)
 
 LOCAL_MODULE:= hwcRects
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA)/nativeutil
@@ -113,8 +110,7 @@
 LOCAL_C_INCLUDES += \
     system/extras/tests/include \
     hardware/libhardware/include \
-    frameworks/base/opengl/tests \
-    frameworks/base/opengl/tests/include \
+	$(call include-path-for, opengl-tests-includes)
 
 LOCAL_MODULE:= hwcColorEquiv
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA)/nativeutil
@@ -143,8 +139,7 @@
 LOCAL_C_INCLUDES += \
     system/extras/tests/include \
     hardware/libhardware/include \
-    frameworks/base/opengl/tests \
-    frameworks/base/opengl/tests/include \
+	$(call include-path-for, opengl-tests-includes)
 
 LOCAL_MODULE:= hwcCommit
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA)/nativebenchmark
diff --git a/opengl/tests/hwc/hwcCommit.cpp b/opengl/tests/hwc/hwcCommit.cpp
index 685dc5d..efa646c 100644
--- a/opengl/tests/hwc/hwcCommit.cpp
+++ b/opengl/tests/hwc/hwcCommit.cpp
@@ -106,7 +106,7 @@
 #include <hardware/hwcomposer.h>
 
 #include <glTestLib.h>
-#include <hwc/hwcTestLib.h>
+#include "hwcTestLib.h"
 
 using namespace std;
 using namespace android;
diff --git a/opengl/tests/hwc/hwcRects.cpp b/opengl/tests/hwc/hwcRects.cpp
index 80cde23..906c169 100644
--- a/opengl/tests/hwc/hwcRects.cpp
+++ b/opengl/tests/hwc/hwcRects.cpp
@@ -114,7 +114,7 @@
 #include <hardware/hwcomposer.h>
 
 #include <glTestLib.h>
-#include <hwc/hwcTestLib.h>
+#include "hwcTestLib.h"
 
 using namespace std;
 using namespace android;
diff --git a/opengl/tests/hwc/hwcStress.cpp b/opengl/tests/hwc/hwcStress.cpp
index 7d7bc1f..b02a424 100644
--- a/opengl/tests/hwc/hwcStress.cpp
+++ b/opengl/tests/hwc/hwcStress.cpp
@@ -111,7 +111,7 @@
 #include <hardware/hwcomposer.h>
 
 #include <glTestLib.h>
-#include <hwc/hwcTestLib.h>
+#include "hwcTestLib.h"
 
 using namespace std;
 using namespace android;
diff --git a/opengl/tests/hwc/hwcTestLib.cpp b/opengl/tests/hwc/hwcTestLib.cpp
index 63f42ba..28e0c3f 100644
--- a/opengl/tests/hwc/hwcTestLib.cpp
+++ b/opengl/tests/hwc/hwcTestLib.cpp
@@ -25,7 +25,7 @@
 
 #include <arpa/inet.h> // For ntohl() and htonl()
 
-#include <hwc/hwcTestLib.h>
+#include "hwcTestLib.h"
 
 #include "EGLUtils.h"
 
diff --git a/opengl/tests/lib/Android.mk b/opengl/tests/lib/Android.mk
index ac1e183..0352a37 100644
--- a/opengl/tests/lib/Android.mk
+++ b/opengl/tests/lib/Android.mk
@@ -22,7 +22,7 @@
     bionic \
     bionic/libstdc++/include \
     external/stlport/stlport \
-    frameworks/base/opengl/tests/include \
+	$(call include-path-for, opengl-tests-includes)
 
 LOCAL_CFLAGS := -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
 
diff --git a/opengl/tests/linetex/Android.mk b/opengl/tests/linetex/Android.mk
index 261940e..5b6384e 100644
--- a/opengl/tests/linetex/Android.mk
+++ b/opengl/tests/linetex/Android.mk
@@ -10,7 +10,7 @@
     libGLESv1_CM \
     libui
 
-LOCAL_C_INCLUDES += frameworks/base/opengl/tests/include
+LOCAL_C_INCLUDES += $(call include-path-for, opengl-tests-includes)
 
 LOCAL_MODULE:= test-opengl-linetex
 
diff --git a/opengl/tests/swapinterval/Android.mk b/opengl/tests/swapinterval/Android.mk
index d014cc9..5517f60 100644
--- a/opengl/tests/swapinterval/Android.mk
+++ b/opengl/tests/swapinterval/Android.mk
@@ -11,7 +11,7 @@
     libGLESv1_CM \
     libui
 
-LOCAL_C_INCLUDES += frameworks/base/opengl/tests/include
+LOCAL_C_INCLUDES += $(call include-path-for, opengl-tests-includes)
 
 LOCAL_MODULE:= test-opengl-swapinterval
 
diff --git a/opengl/tests/textures/Android.mk b/opengl/tests/textures/Android.mk
index fe9f43c..97697d7 100644
--- a/opengl/tests/textures/Android.mk
+++ b/opengl/tests/textures/Android.mk
@@ -10,7 +10,7 @@
     libGLESv1_CM \
     libui
 
-LOCAL_C_INCLUDES += frameworks/base/opengl/tests/include
+LOCAL_C_INCLUDES += $(call include-path-for, opengl-tests-includes)
 
 LOCAL_MODULE:= test-opengl-textures
 
diff --git a/opengl/tests/tritex/Android.mk b/opengl/tests/tritex/Android.mk
index fc544e4..89faa87 100644
--- a/opengl/tests/tritex/Android.mk
+++ b/opengl/tests/tritex/Android.mk
@@ -10,7 +10,7 @@
     libGLESv1_CM \
     libui
 
-LOCAL_C_INCLUDES += frameworks/base/opengl/tests/include
+LOCAL_C_INCLUDES += $(call include-path-for, opengl-tests-includes)
 
 LOCAL_MODULE:= test-opengl-tritex
 
diff --git a/packages/FakeOemFeatures/AndroidManifest.xml b/packages/FakeOemFeatures/AndroidManifest.xml
index 57938ac..93b8b47 100644
--- a/packages/FakeOemFeatures/AndroidManifest.xml
+++ b/packages/FakeOemFeatures/AndroidManifest.xml
@@ -15,9 +15,9 @@
 
         <service android:name=".FakeCoreService" android:process=":core"
                 android:label="Fake OEM Core Service" />
-        <service android:name=".FakeCoreService2" android:process=":core"
+        <service android:name=".FakeCoreService2" android:process=":core2"
                 android:label="Fake OEM Core Service Also" />
-        <service android:name=".FakeCoreService3" android:process=":core"
+        <service android:name=".FakeCoreService3" android:process=":core3"
                 android:label="Fake OEM Core Service Me Too" />
         <service android:name=".FakeBackgroundService" android:process=":background"
                 android:label="Fake OEM Bg Service" />
diff --git a/packages/SettingsProvider/res/values-in/strings.xml b/packages/SettingsProvider/res/values-in/strings.xml
index bed20eb..d5aea43 100644
--- a/packages/SettingsProvider/res/values-in/strings.xml
+++ b/packages/SettingsProvider/res/values-in/strings.xml
@@ -19,5 +19,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_label" msgid="4567566098528588863">"Setelan Penyimpanan"</string>
+    <string name="app_label" msgid="4567566098528588863">"Pengaturan Penyimpanan"</string>
 </resources>
diff --git a/packages/SystemUI/res/layout/status_bar_expanded.xml b/packages/SystemUI/res/layout/status_bar_expanded.xml
index cd4e37c..c64aabe 100644
--- a/packages/SystemUI/res/layout/status_bar_expanded.xml
+++ b/packages/SystemUI/res/layout/status_bar_expanded.xml
@@ -18,116 +18,123 @@
 */
 -->
 
-<com.android.systemui.statusbar.phone.ExpandedView 
+<FrameLayout 
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:systemui="http://schemas.android.com/apk/res/com.android.systemui"
-    android:orientation="vertical"
     android:focusable="true"
     android:descendantFocusability="afterDescendants"
     >
 
-    <RelativeLayout
-        android:layout_width="match_parent"
-        android:layout_height="52dp"
-        android:paddingTop="3dp"
-        android:paddingBottom="5dp"
-        android:paddingRight="3dp"
-        android:background="@drawable/notification_header_bg"
-        >
-        <com.android.systemui.statusbar.policy.DateView android:id="@+id/date"
-            android:textAppearance="@style/TextAppearance.StatusBar.Date"
-            android:layout_width="wrap_content"
-            android:layout_height="match_parent"
-            android:layout_alignParentLeft="true"
-            android:singleLine="true"
-            android:gravity="center_vertical|left"
-            android:paddingLeft="16dp"
-            />
-        <!--
-        <com.android.systemui.statusbar.phone.CarrierLabel
-            android:layout_width="0dp"
-            android:layout_height="wrap_content"
-            android:layout_weight="1"
-            android:layout_marginTop="1dp"
-            android:layout_marginLeft="5dp"
-            android:layout_gravity="center_vertical"
-            android:paddingBottom="1dp"
-            android:paddingLeft="4dp"
-            android:textAppearance="?android:attr/textAppearanceLarge"
-            android:textColor="?android:attr/textColorSecondary"
-            />
-        -->
-
-        <ImageView android:id="@+id/settings_button"
-            android:layout_width="wrap_content"
-            android:layout_height="match_parent"
-            android:layout_toRightOf="@id/date"
-            android:paddingLeft="8dp"
-            android:paddingRight="8dp"
-            android:src="@drawable/ic_notify_quicksettings"
-            android:contentDescription="@string/accessibility_settings_button"
-            />
-
-        <ImageView android:id="@+id/clear_all_button"
-            android:layout_width="wrap_content"
-            android:layout_height="match_parent"
-            android:layout_alignParentRight="true"
-            android:paddingLeft="8dp"
-            android:paddingRight="8dp"
-            android:src="@drawable/ic_notify_clear"
-            android:contentDescription="@string/accessibility_clear_all"
-            />            
-    </RelativeLayout>
-
-    <View
-        android:layout_width="match_parent"
-        android:layout_height="2dp"
-        android:background="@drawable/status_bar_hr"
-        />
-
     <FrameLayout
-        android:layout_width="match_parent" 
+        android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:layout_weight="1"
+        android:orientation="vertical"
+        android:id="@+id/notification_panel"
+        android:background="@drawable/notification_tracking_bg"
+        android:paddingTop="@*android:dimen/status_bar_height"
         >
-        <TextView android:id="@+id/noNotificationsTitle"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:textAppearance="@android:style/TextAppearance.Large"
-            android:padding="8dp"
-            android:layout_gravity="top"
-            android:gravity="left"
-            android:text="@string/status_bar_no_notifications_title"
-            />
 
+        <RelativeLayout
+            android:layout_width="match_parent"
+            android:layout_height="52dp"
+            android:paddingTop="3dp"
+            android:paddingBottom="5dp"
+            android:paddingRight="3dp"
+            android:background="@drawable/notification_header_bg"
+            >
+            <com.android.systemui.statusbar.policy.DateView android:id="@+id/date"
+                android:textAppearance="@style/TextAppearance.StatusBar.Date"
+                android:layout_width="wrap_content"
+                android:layout_height="match_parent"
+                android:layout_alignParentLeft="true"
+                android:singleLine="true"
+                android:gravity="center_vertical|left"
+                android:paddingLeft="16dp"
+                />
+            <!--
+            <com.android.systemui.statusbar.phone.CarrierLabel
+                android:layout_width="0dp"
+                android:layout_height="wrap_content"
+                android:layout_weight="1"
+                android:layout_marginTop="1dp"
+                android:layout_marginLeft="5dp"
+                android:layout_gravity="center_vertical"
+                android:paddingBottom="1dp"
+                android:paddingLeft="4dp"
+                android:textAppearance="?android:attr/textAppearanceLarge"
+                android:textColor="?android:attr/textColorSecondary"
+                />
+            -->
+    
+            <ImageView android:id="@+id/settings_button"
+                android:layout_width="wrap_content"
+                android:layout_height="match_parent"
+                android:layout_toRightOf="@id/date"
+                android:paddingLeft="8dp"
+                android:paddingRight="8dp"
+                android:src="@drawable/ic_notify_quicksettings"
+                android:contentDescription="@string/accessibility_settings_button"
+                />
+    
+            <ImageView android:id="@+id/clear_all_button"
+                android:layout_width="wrap_content"
+                android:layout_height="match_parent"
+                android:layout_alignParentRight="true"
+                android:paddingLeft="8dp"
+                android:paddingRight="8dp"
+                android:src="@drawable/ic_notify_clear"
+                android:contentDescription="@string/accessibility_clear_all"
+                />            
+        </RelativeLayout>
+    
+        <View
+            android:layout_width="match_parent"
+            android:layout_height="2dp"
+            android:layout_marginTop="52dp"
+            android:background="@drawable/status_bar_hr"
+            />
+    
         <ScrollView
             android:id="@+id/scroll"
             android:layout_width="match_parent"
             android:layout_height="match_parent"
             android:fadingEdge="none"
             android:overScrollMode="ifContentScrolls"
+			android:layout_marginTop="54dp"
+			android:layout_marginBottom="34dp"
             >
-            <LinearLayout
+            <com.android.systemui.statusbar.policy.NotificationRowLayout
+                android:id="@+id/latestItems"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
-                android:orientation="vertical"
-                >
-                <com.android.systemui.statusbar.policy.NotificationRowLayout
-                    android:id="@+id/latestItems"
-                    android:layout_width="match_parent"
-                    android:layout_height="wrap_content"
-                    systemui:rowHeight="@dimen/notification_height"
-                    />
-
-            </LinearLayout>
+                systemui:rowHeight="@dimen/notification_height"
+                />
         </ScrollView>
-
+    
         <ImageView
             android:layout_width="match_parent"
-            android:layout_height="match_parent"
+            android:layout_height="wrap_content"
             android:src="@drawable/title_bar_shadow"
+			android:layout_marginTop="54dp"
             android:scaleType="fitXY"
         />
+   
+        <com.android.systemui.statusbar.phone.CloseDragHandle android:id="@+id/close"
+            android:layout_width="match_parent"
+            android:layout_height="34dp"
+            android:layout_gravity="bottom"
+            android:orientation="vertical"
+            >
+            <ImageView
+                android:layout_width="match_parent"
+                android:layout_height="34dp"
+                android:layout_gravity="bottom"
+                android:scaleType="fitXY"
+                android:src="@drawable/status_bar_close_on"
+                />
+    
+        </com.android.systemui.statusbar.phone.CloseDragHandle>
+    
+    </FrameLayout><!-- end of sliding panel -->
 
-    </FrameLayout>
-</com.android.systemui.statusbar.phone.ExpandedView>
+</FrameLayout><!-- end of window -->
\ No newline at end of file
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index 612b666..e2e65b9 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -66,7 +66,7 @@
     <string name="screenshot_saving_title" msgid="8242282144535555697">"ቅጽበታዊ ገጽ እይታ በማስቀመጥ ላይ..."</string>
     <string name="screenshot_saving_text" msgid="2419718443411738818">"ቅጽበታዊ ገጽ እይታ እየተቀመጠ ነው::"</string>
     <string name="screenshot_saved_title" msgid="6461865960961414961">"ቅጽበታዊ ገጽ እይታ ተቀርጿል"</string>
-    <string name="screenshot_saved_text" msgid="1152839647677558815">"ያንተን ቅጽበታዊ ገጽ እይታ ለማየት ንካ"</string>
+    <string name="screenshot_saved_text" msgid="1152839647677558815">"የአንተን ቅጽበታዊ ገጽ እይታ ለማየት ንካ"</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"ቅጽበታዊ ገጽ እይታ መቅረጽ አልተቻለም::"</string>
     <string name="screenshot_failed_text" msgid="8134011269572415402">"የማያ ፎቶማስቀመጥ አልተቻለም። ማከማቻም አገልግሎት ላይ ሊሆን ይችላል።"</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"የUSB ፋይል ሰደዳ አማራጮች"</string>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index a8b024d..7c1cd18 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -39,7 +39,7 @@
     <string name="battery_low_percent_format" msgid="1077244949318261761">"<xliff:g id="NUMBER">%d%%</xliff:g> tersisa"</string>
     <string name="invalid_charger" msgid="4549105996740522523">"Pengisian daya USB tidak didukung."\n"Gunakan hanya pengisi daya yang disediakan."</string>
     <string name="battery_low_why" msgid="7279169609518386372">"Penggunaan baterai"</string>
-    <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Setelan"</string>
+    <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Pengaturan"</string>
     <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
     <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Mode pesawat"</string>
     <string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"Putar layar secara otomatis"</string>
@@ -69,10 +69,10 @@
     <string name="screenshot_saved_text" msgid="1152839647677558815">"Sentuh untuk melihat tangkapan layar Anda."</string>
     <string name="screenshot_failed_title" msgid="705781116746922771">"Tidak dapat mengambil tangkapan layar."</string>
     <string name="screenshot_failed_text" msgid="8134011269572415402">"Tidak dapat menyimpan tangkapan layar. Penyimpanan mungkin sedang digunakan."</string>
-    <string name="usb_preference_title" msgid="6551050377388882787">"Opsi transfer berkas USB"</string>
+    <string name="usb_preference_title" msgid="6551050377388882787">"Opsi transfer file USB"</string>
     <string name="use_mtp_button_title" msgid="4333504413563023626">"Pasang sebagai pemutar media (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Pasang sebagai kamera (PTP)"</string>
-    <string name="installer_cd_button_title" msgid="2312667578562201583">"Pasang apl Transfer Berkas Android untuk Mac"</string>
+    <string name="installer_cd_button_title" msgid="2312667578562201583">"Pasang apl Transfer File Android untuk Mac"</string>
     <string name="accessibility_back" msgid="567011538994429120">"Kembali"</string>
     <string name="accessibility_home" msgid="8217216074895377641">"Utama"</string>
     <string name="accessibility_menu" msgid="316839303324695949">"Menu"</string>
@@ -118,7 +118,7 @@
     <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"Penambatan bluetooth."</string>
     <string name="accessibility_airplane_mode" msgid="834748999790763092">"Mode pesawat."</string>
     <string name="accessibility_battery_level" msgid="7451474187113371965">"Baterai <xliff:g id="NUMBER">%d</xliff:g> persen."</string>
-    <string name="accessibility_settings_button" msgid="799583911231893380">"Setelan sistem."</string>
+    <string name="accessibility_settings_button" msgid="799583911231893380">"Pengaturan sistem."</string>
     <string name="accessibility_notifications_button" msgid="4498000369779421892">"Pemberitahuan."</string>
     <string name="accessibility_remove_notification" msgid="3603099514902182350">"Menghapus pemberitahuan."</string>
     <string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS diaktifkan."</string>
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index a08b99a..7f00c38 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -26,7 +26,7 @@
     <color name="status_bar_recents_app_label_color">#ffffffff</color>
     <drawable name="status_bar_notification_row_background_color">#ff090909</drawable>
     <drawable name="notification_header_bg">#FF000000</drawable>
-    <drawable name="notification_tracking_bg">#d8000000</drawable>
+    <drawable name="notification_tracking_bg">#66000000</drawable>
     <color name="notification_list_shadow_top">#80000000</color>
     <drawable name="recents_callout_line">#99ffffff</drawable>
     <drawable name="notification_item_background_legacy_color">#ffaaaaaa</drawable>
diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java
index 61aaa43..66cb32c 100644
--- a/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java
@@ -54,7 +54,7 @@
 import android.widget.TextView;
 
 import com.android.systemui.R;
-import com.android.systemui.statusbar.StatusBar;
+import com.android.systemui.statusbar.BaseStatusBar;
 import com.android.systemui.statusbar.phone.PhoneStatusBar;
 import com.android.systemui.statusbar.tablet.StatusBarPanel;
 import com.android.systemui.statusbar.tablet.TabletStatusBar;
@@ -66,7 +66,7 @@
     static final String TAG = "RecentsPanelView";
     static final boolean DEBUG = TabletStatusBar.DEBUG || PhoneStatusBar.DEBUG || false;
     private Context mContext;
-    private StatusBar mBar;
+    private BaseStatusBar mBar;
     private View mRecentsScrim;
     private View mRecentsNoApps;
     private ViewGroup mRecentsContainer;
@@ -379,7 +379,7 @@
         return mShowing;
     }
 
-    public void setBar(StatusBar bar) {
+    public void setBar(BaseStatusBar bar) {
         mBar = bar;
 
     }
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
index c4a92f7..9a76c14 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
@@ -34,7 +34,7 @@
 import android.graphics.Matrix;
 import android.graphics.PixelFormat;
 import android.graphics.PointF;
-import android.hardware.CameraSound;
+import android.media.MediaActionSound;
 import android.net.Uri;
 import android.os.AsyncTask;
 import android.os.Environment;
@@ -256,7 +256,7 @@
     private float mBgPadding;
     private float mBgPaddingScale;
 
-    private CameraSound mCameraSound;
+    private MediaActionSound mCameraSound;
 
 
     /**
@@ -309,7 +309,8 @@
         mBgPaddingScale = mBgPadding /  mDisplayMetrics.widthPixels;
 
         // Setup the Camera shutter sound
-        mCameraSound = new CameraSound();
+        mCameraSound = new MediaActionSound();
+        mCameraSound.load(MediaActionSound.SHUTTER_CLICK);
     }
 
     /**
@@ -422,7 +423,7 @@
             @Override
             public void run() {
                 // Play the shutter sound to notify that we've taken a screenshot
-                mCameraSound.playSound(CameraSound.SHUTTER_CLICK);
+                mCameraSound.play(MediaActionSound.SHUTTER_CLICK);
 
                 mScreenshotView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
                 mScreenshotView.buildLayer();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
similarity index 61%
rename from packages/SystemUI/src/com/android/systemui/statusbar/StatusBar.java
rename to packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index 2be35b7..36d9316 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -16,60 +16,75 @@
 
 package com.android.systemui.statusbar;
 
-import android.app.ActivityManager;
-import android.app.Service;
+import java.util.ArrayList;
+
 import android.content.Context;
-import android.content.Intent;
-import android.content.res.Resources;
-import android.graphics.PixelFormat;
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.os.ServiceManager;
-import android.util.Slog;
 import android.util.Log;
+import android.util.Slog;
 import android.view.Display;
-import android.view.Gravity;
+import android.view.IWindowManager;
 import android.view.View;
-import android.view.ViewGroup;
 import android.view.WindowManager;
-import android.view.WindowManagerImpl;
-
-import java.util.ArrayList;
 
 import com.android.internal.statusbar.IStatusBarService;
 import com.android.internal.statusbar.StatusBarIcon;
 import com.android.internal.statusbar.StatusBarIconList;
 import com.android.internal.statusbar.StatusBarNotification;
-
 import com.android.systemui.SystemUI;
+import com.android.systemui.statusbar.CommandQueue;
+
 import com.android.systemui.R;
 
-public abstract class StatusBar extends SystemUI implements CommandQueue.Callbacks {
+public abstract class BaseStatusBar extends SystemUI implements CommandQueue.Callbacks {
     static final String TAG = "StatusBar";
-    private static final boolean SPEW = false;
+    private static final boolean DEBUG = false;
 
     protected CommandQueue mCommandQueue;
     protected IStatusBarService mBarService;
 
-    // Up-call methods
-    protected abstract View makeStatusBarView();
-    protected abstract int getStatusBarGravity();
-    public abstract int getStatusBarHeight();
-    public abstract void animateCollapse();
+    // UI-specific methods
+    
+    /**
+     * Create all windows necessary for the status bar (including navigation, overlay panels, etc)
+     * and add them to the window manager.
+     */
+    protected abstract void createAndAddWindows();
 
-    private DoNotDisturb mDoNotDisturb;
+    protected Display mDisplay;
+    private IWindowManager mWindowManager;
+
+    
+    public IWindowManager getWindowManager() {
+        return mWindowManager;
+    }
+    
+    public Display getDisplay() {
+        return mDisplay;
+    }
+    
+    public IStatusBarService getStatusBarService() {
+        return mBarService;
+    }
 
     public void start() {
-        // First set up our views and stuff.
-        View sb = makeStatusBarView();
+        mDisplay = ((WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE))
+                .getDefaultDisplay();
+
+        mWindowManager = IWindowManager.Stub.asInterface(
+                ServiceManager.getService(Context.WINDOW_SERVICE));
+
+        mBarService = IStatusBarService.Stub.asInterface(
+                ServiceManager.getService(Context.STATUS_BAR_SERVICE));
 
         // Connect in to the status bar manager service
         StatusBarIconList iconList = new StatusBarIconList();
         ArrayList<IBinder> notificationKeys = new ArrayList<IBinder>();
         ArrayList<StatusBarNotification> notifications = new ArrayList<StatusBarNotification>();
         mCommandQueue = new CommandQueue(this, iconList);
-        mBarService = IStatusBarService.Stub.asInterface(
-                ServiceManager.getService(Context.STATUS_BAR_SERVICE));
+        
         int[] switches = new int[7];
         ArrayList<IBinder> binders = new ArrayList<IBinder>();
         try {
@@ -78,6 +93,8 @@
         } catch (RemoteException ex) {
             // If the system process isn't there we're doomed anyway.
         }
+        
+        createAndAddWindows();
 
         disable(switches[0]);
         setSystemUiVisibility(switches[1]);
@@ -108,50 +125,18 @@
                     + " notifications=" + notifications.size());
         }
 
-        // Put up the view
-        final int height = getStatusBarHeight();
-
-        final WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
-                ViewGroup.LayoutParams.MATCH_PARENT,
-                height,
-                WindowManager.LayoutParams.TYPE_STATUS_BAR,
-                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
-                    | WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING
-                    | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
-                // We use a pixel format of RGB565 for the status bar to save memory bandwidth and
-                // to ensure that the layer can be handled by HWComposer.  On some devices the
-                // HWComposer is unable to handle SW-rendered RGBX_8888 layers.
-                PixelFormat.RGB_565);
-        
-        // the status bar should be in an overlay if possible
-        final Display defaultDisplay 
-            = ((WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE))
-                .getDefaultDisplay();
-
-        // We explicitly leave FLAG_HARDWARE_ACCELERATED out of the flags.  The status bar occupies
-        // very little screen real-estate and is updated fairly frequently.  By using CPU rendering
-        // for the status bar, we prevent the GPU from having to wake up just to do these small
-        // updates, which should help keep power consumption down.
-
-        lp.gravity = getStatusBarGravity();
-        lp.setTitle("StatusBar");
-        lp.packageName = mContext.getPackageName();
-        lp.windowAnimations = R.style.Animation_StatusBar;
-        WindowManagerImpl.getDefault().addView(sb, lp);
-
-        if (SPEW) {
-            Slog.d(TAG, "Added status bar view: gravity=0x" + Integer.toHexString(lp.gravity) 
-                   + " icons=" + iconList.size()
-                   + " disabled=0x" + Integer.toHexString(switches[0])
-                   + " lights=" + switches[1]
-                   + " menu=" + switches[2]
-                   + " imeButton=" + switches[3]
-                   );
+        if (DEBUG) {
+            Slog.d(TAG, String.format(
+                    "init: icons=%d disabled=0x%08x lights=0x%08x menu=0x%08x imeButton=0x%08x", 
+                   iconList.size(),
+                   switches[0],
+                   switches[1],
+                   switches[2],
+                   switches[3]
+                   ));
         }
-
-        mDoNotDisturb = new DoNotDisturb(mContext);
     }
-
+    
     protected View updateNotificationVetoButton(View row, StatusBarNotification n) {
         View vetoButton = row.findViewById(R.id.veto);
         if (n.isClearable()) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
index 8228df5..6a9e838 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
@@ -119,7 +119,7 @@
         if (!iconEquals) {
             Drawable drawable = getIcon(icon);
             if (drawable == null) {
-                Slog.w(StatusBar.TAG, "No icon for slot " + mSlot);
+                Slog.w(TAG, "No icon for slot " + mSlot);
                 return false;
             }
             setImageDrawable(drawable);
@@ -167,7 +167,7 @@
             try {
                 r = context.getPackageManager().getResourcesForApplication(icon.iconPackage);
             } catch (PackageManager.NameNotFoundException ex) {
-                Slog.e(StatusBar.TAG, "Icon package not found: " + icon.iconPackage);
+                Slog.e(TAG, "Icon package not found: " + icon.iconPackage);
                 return null;
             }
         } else {
@@ -181,7 +181,7 @@
         try {
             return r.getDrawable(icon.iconId);
         } catch (RuntimeException e) {
-            Slog.w(StatusBar.TAG, "Icon not found in "
+            Slog.w(TAG, "Icon not found in "
                   + (icon.iconPackage != null ? icon.iconId : "<system>")
                   + ": " + Integer.toHexString(icon.iconId));
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ExpandedView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ExpandedView.java
deleted file mode 100644
index 2d3ecae..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ExpandedView.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.statusbar.phone;
-
-import android.content.Context;
-import android.util.AttributeSet;
-import android.util.Slog;
-import android.widget.LinearLayout;
-
-public class ExpandedView extends LinearLayout {
-    PhoneStatusBar mService;
-    int mPrevHeight = -1;
-
-    public ExpandedView(Context context, AttributeSet attrs) {
-        super(context, attrs);
-    }
-
-    @Override
-    protected void onFinishInflate() {
-        super.onFinishInflate();
-    }
-
-    /** We want to shrink down to 0, and ignore the background. */
-    @Override
-    public int getSuggestedMinimumHeight() {
-        return 0;
-    }
-
-    @Override
-    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
-         super.onLayout(changed, left, top, right, bottom);
-         int height = bottom - top;
-         if (height != mPrevHeight) {
-             if (PhoneStatusBar.DEBUG) {
-                 Slog.d(PhoneStatusBar.TAG, "ExpandedView height changed old=" + mPrevHeight
-                      + " new=" + height);
-             }
-             mPrevHeight = height;
-             mService.updateExpandedViewPos(PhoneStatusBar.EXPANDED_LEAVE_ALONE);
-         }
-     }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index 2e1f120..f721cdc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -81,7 +81,7 @@
 import com.android.systemui.recent.RecentsPanelView;
 import com.android.systemui.recent.TaskDescription;
 import com.android.systemui.statusbar.NotificationData;
-import com.android.systemui.statusbar.StatusBar;
+import com.android.systemui.statusbar.BaseStatusBar;
 import com.android.systemui.statusbar.StatusBarIconView;
 import com.android.systemui.statusbar.SignalClusterView;
 import com.android.systemui.statusbar.policy.DateView;
@@ -90,10 +90,10 @@
 import com.android.systemui.statusbar.policy.NetworkController;
 import com.android.systemui.statusbar.policy.NotificationRowLayout;
 
-public class PhoneStatusBar extends StatusBar {
+public class PhoneStatusBar extends BaseStatusBar {
     static final String TAG = "PhoneStatusBar";
     public static final boolean DEBUG = false;
-    public static final boolean SPEW = false;
+    public static final boolean SPEW = true;
     public static final boolean DUMPTRUCK = true; // extra dumpsys info
 
     // additional instrumentation for testing purposes; intended to be left on during development
@@ -160,12 +160,12 @@
 
     // expanded notifications
     Dialog mExpandedDialog;
-    ExpandedView mExpandedView;
     WindowManager.LayoutParams mExpandedParams;
+    View mExpandedWindowView;
+    View mNotificationPanel; // the sliding/resizing panel within the notification window
     ScrollView mScrollView;
     View mExpandedContents;
     // top bar
-    TextView mNoNotificationsTitle;
     View mClearButton;
     View mSettingsButton;
 
@@ -191,8 +191,6 @@
     private NavigationBarView mNavigationBarView = null;
 
     // the tracker view
-    TrackingView mTrackingView;
-    WindowManager.LayoutParams mTrackingParams;
     int mTrackingPosition; // the position of the top of the tracking view.
     private boolean mPanelSlightlyVisible;
 
@@ -266,7 +264,7 @@
         mWindowManager = IWindowManager.Stub.asInterface(
                 ServiceManager.getService(Context.WINDOW_SERVICE));
 
-        super.start(); // calls makeStatusBarView()
+        super.start(); // calls createAndAddWindows()
 
         addNavigationBar();
 
@@ -289,12 +287,12 @@
 
         mIconSize = res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_icon_size);
 
-        ExpandedView expanded = (ExpandedView)View.inflate(context,
+        final View expanded = mExpandedWindowView = View.inflate(context,
                 R.layout.status_bar_expanded, null);
         if (DEBUG) {
             expanded.setBackgroundColor(0x6000FF80);
         }
-        expanded.mService = this;
+        mNotificationPanel = expanded.findViewById(R.id.notification_panel);
 
         mIntruderAlertView = View.inflate(context, R.layout.intruder_alert, null);
         mIntruderAlertView.setVisibility(View.GONE);
@@ -327,11 +325,8 @@
         mTickerView = sb.findViewById(R.id.ticker);
 
         mExpandedDialog = new ExpandedDialog(context);
-        mExpandedView = expanded;
         mPile = (NotificationRowLayout)expanded.findViewById(R.id.latestItems);
         mExpandedContents = mPile; // was: expanded.findViewById(R.id.notificationLinearLayout);
-        mNoNotificationsTitle = (TextView)expanded.findViewById(R.id.noNotificationsTitle);
-        mNoNotificationsTitle.setVisibility(View.GONE); // disabling for now
 
         mClearButton = expanded.findViewById(R.id.clear_all_button);
         mClearButton.setOnClickListener(mClearButtonListener);
@@ -341,15 +336,14 @@
         mSettingsButton = expanded.findViewById(R.id.settings_button);
         mSettingsButton.setOnClickListener(mSettingsButtonListener);
         mScrollView = (ScrollView)expanded.findViewById(R.id.scroll);
+        mScrollView.setVerticalScrollBarEnabled(false); // less drawing during pulldowns
 
         mTicker = new MyTicker(context, sb);
 
         TickerView tickerView = (TickerView)sb.findViewById(R.id.tickerText);
         tickerView.mTicker = mTicker;
 
-        mTrackingView = (TrackingView)View.inflate(context, R.layout.status_bar_tracking, null);
-        mTrackingView.mService = this;
-        mCloseView = (CloseDragHandle)mTrackingView.findViewById(R.id.close);
+        mCloseView = (CloseDragHandle)mExpandedWindowView.findViewById(R.id.close);
         mCloseView.mService = this;
 
         mEdgeBorder = res.getDimensionPixelSize(R.dimen.status_bar_edge_ignore);
@@ -975,22 +969,10 @@
         }
         mClearButton.setEnabled(clearable);
 
-        /*
-        if (mNoNotificationsTitle.isShown()) {
-            if (any != (mNoNotificationsTitle.getAlpha() == 0.0f)) {
-                ObjectAnimator a = ObjectAnimator.ofFloat(mNoNotificationsTitle, "alpha",
-                            (any ? 0.0f : 0.75f));
-                a.setDuration(any ? 0 : 500);
-                a.setStartDelay(any ? 250 : 1000);
-                a.start();
-            }
-        } else {
-            mNoNotificationsTitle.setAlpha(any ? 0.0f : 0.75f);
-        }
-        */
     }
 
     public void showClock(boolean show) {
+        if (mStatusBarView == null) return;
         View clock = mStatusBarView.findViewById(R.id.clock);
         if (clock != null) {
             clock.setVisibility(show ? View.VISIBLE : View.GONE);
@@ -1128,6 +1110,7 @@
         if (mExpandedVisible) {
             return;
         }
+        mExpandedDialog.show(); // XXX HAX
         mExpandedVisible = true;
         visibilityChanged(true);
 
@@ -1138,8 +1121,8 @@
             Slog.d(TAG, "makeExpandedVisible: expanded params = " + mExpandedParams);
         }
         mExpandedDialog.getWindow().setAttributes(mExpandedParams);
-        mExpandedView.requestFocus(View.FOCUS_FORWARD);
-        mTrackingView.setVisibility(View.VISIBLE);
+        mExpandedWindowView.requestFocus(View.FOCUS_FORWARD);
+        mExpandedWindowView.setVisibility(View.VISIBLE);
     }
 
     public void animateExpand() {
@@ -1223,7 +1206,8 @@
         mExpandedParams.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
         mExpandedParams.flags &= ~WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
         mExpandedDialog.getWindow().setAttributes(mExpandedParams);
-        mTrackingView.setVisibility(View.GONE);
+        mExpandedDialog.hide(); // XXX HAX
+        mExpandedWindowView.setVisibility(View.GONE);
 
         if ((mDisabled & StatusBarManager.DISABLE_NOTIFICATION_ICONS) == 0) {
             setNotificationIconVisibility(true, com.android.internal.R.anim.fade_in);
@@ -1267,6 +1251,7 @@
 
     void stopTracking() {
         mTracking = false;
+        mPile.setLayerType(View.LAYER_TYPE_NONE, null);
         mVelocityTracker.recycle();
         mVelocityTracker = null;
     }
@@ -1310,6 +1295,7 @@
         updateExpandedSize();
 
         mTracking = true;
+        mPile.setLayerType(View.LAYER_TYPE_HARDWARE, null);
         mVelocityTracker = VelocityTracker.obtain();
         if (opening) {
             mAnimAccel = mExpandAccelPx;
@@ -1427,8 +1413,8 @@
             if (!mExpanded) {
                 mViewDelta = statusBarSize - y;
             } else {
-                mTrackingView.getLocationOnScreen(mAbsPos);
-                mViewDelta = mAbsPos[1] + mTrackingView.getHeight() - y;
+//                mCloseView.getLocationOnScreen(mAbsPos)...?
+//                mViewDelta = mAbsPos[1] + mTrackingView.getHeight() - y;
             }
             if ((!mExpanded && y < hitSize) ||
                     (mExpanded && y > (mDisplayMetrics.heightPixels-hitSize))) {
@@ -1733,12 +1719,9 @@
                     + " mViewDelta=" + mViewDelta);
             pw.println("  mDisplayMetrics=" + mDisplayMetrics);
             pw.println("  mExpandedParams: " + mExpandedParams);
-            pw.println("  mExpandedView: " + viewInfo(mExpandedView));
+            pw.println("  mExpandedView: " + viewInfo(mExpandedWindowView));
             pw.println("  mExpandedDialog: " + mExpandedDialog);
-            pw.println("  mTrackingParams: " + mTrackingParams);
-            pw.println("  mTrackingView: " + viewInfo(mTrackingView));
             pw.println("  mPile: " + viewInfo(mPile));
-            pw.println("  mNoNotificationsTitle: " + viewInfo(mNoNotificationsTitle));
             pw.println("  mCloseView: " + viewInfo(mCloseView));
             pw.println("  mTickerView: " + viewInfo(mTickerView));
             pw.println("  mScrollView: " + viewInfo(mScrollView)
@@ -1784,17 +1767,11 @@
                                     + mStatusBarView.getHeight());
                             mStatusBarView.debug();
 
-                            mExpandedView.getLocationOnScreen(mAbsPos);
+                            mExpandedWindowView.getLocationOnScreen(mAbsPos);
                             Slog.d(TAG, "mExpandedView: ----- (" + mAbsPos[0] + "," + mAbsPos[1]
-                                    + ") " + mExpandedView.getWidth() + "x"
-                                    + mExpandedView.getHeight());
-                            mExpandedView.debug();
-
-                            mTrackingView.getLocationOnScreen(mAbsPos);
-                            Slog.d(TAG, "mTrackingView: ----- (" + mAbsPos[0] + "," + mAbsPos[1]
-                                    + ") " + mTrackingView.getWidth() + "x"
-                                    + mTrackingView.getHeight());
-                            mTrackingView.debug();
+                                    + ") " + mExpandedWindowView.getWidth() + "x"
+                                    + mExpandedWindowView.getHeight());
+                            mExpandedWindowView.debug();
                         }
                     });
             }
@@ -1803,44 +1780,47 @@
         mNetworkController.dump(fd, pw, args);
     }
 
-    void onBarViewAttached() {
-        // The status bar has just been attached to the view hierarchy; it's possible that the
-        // screen has rotated in-between when we set up the window and now, so let's double-check
-        // the display metrics just in case.
-        updateDisplaySize();
-
-        WindowManager.LayoutParams lp;
-        int pixelFormat;
-        Drawable bg;
-
-        /// ---------- Tracking View --------------
-        bg = mTrackingView.getBackground();
-        if (bg != null) {
-            pixelFormat = bg.getOpacity();
-        }
-
-        lp = new WindowManager.LayoutParams(
-                ViewGroup.LayoutParams.MATCH_PARENT,
-                ViewGroup.LayoutParams.MATCH_PARENT,
-                WindowManager.LayoutParams.TYPE_STATUS_BAR_SUB_PANEL,
-                0
-                | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
-                | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
-                | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
-                PixelFormat.TRANSLUCENT);
-        if (ActivityManager.isHighEndGfx(mDisplay)) {
-            lp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
-        }
-//        lp.token = mStatusBarView.getWindowToken();
-        lp.gravity = Gravity.TOP | Gravity.FILL_HORIZONTAL;
-        lp.setTitle("TrackingView");
-        lp.y = mTrackingPosition;
-        mTrackingParams = lp;
-
-        WindowManagerImpl.getDefault().addView(mTrackingView, lp);
+    @Override
+    public void createAndAddWindows() {
+        addStatusBarWindow();
+        addExpandedWindow();
     }
+    
+    private void addStatusBarWindow() {
+        // Put up the view
+        final int height = getStatusBarHeight();
 
-    void onTrackingViewAttached() {
+        final WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
+                ViewGroup.LayoutParams.MATCH_PARENT,
+                height,
+                WindowManager.LayoutParams.TYPE_STATUS_BAR,
+                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
+                    | WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING
+                    | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
+                // We use a pixel format of RGB565 for the status bar to save memory bandwidth and
+                // to ensure that the layer can be handled by HWComposer.  On some devices the
+                // HWComposer is unable to handle SW-rendered RGBX_8888 layers.
+                PixelFormat.RGB_565);
+
+        // the status bar should be in an overlay if possible
+        final Display defaultDisplay
+            = ((WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE))
+                .getDefaultDisplay();
+
+        // We explicitly leave FLAG_HARDWARE_ACCELERATED out of the flags.  The status bar occupies
+        // very little screen real-estate and is updated fairly frequently.  By using CPU rendering
+        // for the status bar, we prevent the GPU from having to wake up just to do these small
+        // updates, which should help keep power consumption down.
+
+        lp.gravity = getStatusBarGravity();
+        lp.setTitle("StatusBar");
+        lp.packageName = mContext.getPackageName();
+        lp.windowAnimations = R.style.Animation_StatusBar;
+        WindowManagerImpl.getDefault().addView(makeStatusBarView(), lp);
+
+    }
+    
+    void addExpandedWindow() {
         WindowManager.LayoutParams lp;
         int pixelFormat;
 
@@ -1849,7 +1829,7 @@
 
         lp = mExpandedDialog.getWindow().getAttributes();
         lp.x = 0;
-        mTrackingPosition = lp.y = mDisplayMetrics.heightPixels; // sufficiently large negative
+        lp.y = 0;
         lp.type = WindowManager.LayoutParams.TYPE_STATUS_BAR_SUB_PANEL;
         lp.flags = 0
                 | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
@@ -1868,11 +1848,11 @@
         mExpandedDialog.getWindow().setFormat(pixelFormat);
 
         mExpandedDialog.getWindow().requestFeature(Window.FEATURE_NO_TITLE);
-        mExpandedDialog.setContentView(mExpandedView,
+        mExpandedDialog.setContentView(mExpandedWindowView,
                 new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
                                            ViewGroup.LayoutParams.MATCH_PARENT));
         mExpandedDialog.getWindow().setBackgroundDrawable(null);
-        mExpandedDialog.show();
+        //mExpandedDialog.show();
     }
 
     void setNotificationIconVisibility(boolean visible, int anim) {
@@ -1885,28 +1865,18 @@
     }
 
     void updateExpandedInvisiblePosition() {
-        if (mTrackingView != null) {
-            mTrackingPosition = -mDisplayMetrics.heightPixels;
-            if (mTrackingParams != null) {
-                mTrackingParams.y = mTrackingPosition;
-                WindowManagerImpl.getDefault().updateViewLayout(mTrackingView, mTrackingParams);
-            }
-        }
-        if (mExpandedParams != null) {
-            mExpandedParams.y = -mDisplayMetrics.heightPixels;
-            mExpandedDialog.getWindow().setAttributes(mExpandedParams);
-        }
+        mTrackingPosition = -mDisplayMetrics.heightPixels;
     }
 
     void updateExpandedViewPos(int expandedPosition) {
         if (SPEW) {
             Slog.d(TAG, "updateExpandedViewPos before expandedPosition=" + expandedPosition
-                    + " mTrackingParams.y=" + ((mTrackingParams == null) ? "?" : mTrackingParams.y)
+                    //+ " mTrackingParams.y=" + ((mTrackingParams == null) ? "?" : mTrackingParams.y)
                     + " mTrackingPosition=" + mTrackingPosition);
         }
 
-        int h = mStatusBarView.getHeight();
-        int disph = mDisplayMetrics.heightPixels;
+        int panelh = 0;
+        final int disph = mDisplayMetrics.heightPixels;
 
         // If the expanded view is not visible, make sure they're still off screen.
         // Maybe the view was resized.
@@ -1918,82 +1888,96 @@
         // tracking view...
         int pos;
         if (expandedPosition == EXPANDED_FULL_OPEN) {
-            pos = h;
+            panelh = disph;
         }
         else if (expandedPosition == EXPANDED_LEAVE_ALONE) {
-            pos = mTrackingPosition;
+            panelh = mTrackingPosition;
         }
         else {
             if (expandedPosition <= disph) {
-                pos = expandedPosition;
+                panelh = expandedPosition;
             } else {
-                pos = disph;
-            }
-            pos -= disph-h;
-        }
-        mTrackingPosition = mTrackingParams.y = pos;
-        mTrackingParams.height = disph-h;
-        WindowManagerImpl.getDefault().updateViewLayout(mTrackingView, mTrackingParams);
-
-        if (mExpandedParams != null) {
-            if (mCloseView.getWindowVisibility() == View.VISIBLE) {
-                mCloseView.getLocationInWindow(mPositionTmp);
-                final int closePos = mPositionTmp[1];
-
-                mExpandedContents.getLocationInWindow(mPositionTmp);
-                final int contentsBottom = mPositionTmp[1] + mExpandedContents.getHeight();
-
-                mExpandedParams.y = pos + mTrackingView.getHeight()
-                        - (mTrackingParams.height-closePos) - contentsBottom;
-
-                if (SPEW) {
-                    Slog.d(PhoneStatusBar.TAG,
-                            "pos=" + pos +
-                            " trackingHeight=" + mTrackingView.getHeight() +
-                            " (trackingParams.height - closePos)=" +
-                                (mTrackingParams.height - closePos) +
-                            " contentsBottom=" + contentsBottom);
-                }
-
-            } else {
-                // If the tracking view is not yet visible, then we can't have
-                // a good value of the close view location.  We need to wait for
-                // it to be visible to do a layout.
-                mExpandedParams.y = -mDisplayMetrics.heightPixels;
-            }
-            int max = h;
-            if (mExpandedParams.y > max) {
-                mExpandedParams.y = max;
-            }
-            int min = mTrackingPosition;
-            if (mExpandedParams.y < min) {
-                mExpandedParams.y = min;
-            }
-
-            boolean visible = (mTrackingPosition + mTrackingView.getHeight()) > h;
-            if (!visible) {
-                // if the contents aren't visible, move the expanded view way off screen
-                // because the window itself extends below the content view.
-                mExpandedParams.y = -disph;
-            }
-            mExpandedDialog.getWindow().setAttributes(mExpandedParams);
-
-            // As long as this isn't just a repositioning that's not supposed to affect
-            // the user's perception of what's showing, call to say that the visibility
-            // has changed. (Otherwise, someone else will call to do that).
-            if (expandedPosition != EXPANDED_LEAVE_ALONE) {
-                if (SPEW) Slog.d(TAG, "updateExpandedViewPos visibilityChanged(" + visible + ")");
-                visibilityChanged(visible);
+                panelh = disph;
             }
         }
-
-        if (SPEW) {
-            Slog.d(TAG, "updateExpandedViewPos after  expandedPosition=" + expandedPosition
-                    + " mTrackingParams.y=" + mTrackingParams.y
-                    + " mTrackingPosition=" + mTrackingPosition
-                    + " mExpandedParams.y=" + mExpandedParams.y
-                    + " mExpandedParams.height=" + mExpandedParams.height);
-        }
+        
+        // catch orientation changes and other peculiar cases
+        if (panelh > disph || (panelh < disph && !mTracking && !mAnimating))
+            panelh = disph;
+        
+        mTrackingPosition = panelh;
+        // XXX: this is all very WIP
+        //mNotificationPanel.setY(panelh);
+        final View cropView = mNotificationPanel;
+        ViewGroup.LayoutParams lp = cropView.getLayoutParams();
+        lp.height = panelh;
+        cropView.setLayoutParams(lp);
+        // woo, special effects
+        final float frac = (float)panelh / disph;
+        final int color = ((int)(0xB0 * frac * frac)) << 24;
+        mExpandedWindowView.setBackgroundColor(color);
+        
+//        Slog.d(TAG, String.format("updateExpanded: pos=%d frac=%.2f col=0x%08x", pos, frac, color));
+        
+//        if (mExpandedParams != null) {
+//            if (mCloseView.getWindowVisibility() == View.VISIBLE) {
+//                mCloseView.getLocationInWindow(mPositionTmp);
+//                final int closePos = mPositionTmp[1];
+//
+//                mExpandedContents.getLocationInWindow(mPositionTmp);
+//                final int contentsBottom = mPositionTmp[1] + mExpandedContents.getHeight();
+//
+//                mExpandedParams.y = pos + mTrackingView.getHeight()
+//                        - (mTrackingParams.height-closePos) - contentsBottom;
+//
+//                if (SPEW) {
+//                    Slog.d(PhoneStatusBar.TAG,
+//                            "pos=" + pos +
+//                            " trackingHeight=" + mTrackingView.getHeight() +
+//                            " (trackingParams.height - closePos)=" +
+//                                (mTrackingParams.height - closePos) +
+//                            " contentsBottom=" + contentsBottom);
+//                }
+//
+//            } else {
+//                // If the tracking view is not yet visible, then we can't have
+//                // a good value of the close view location.  We need to wait for
+//                // it to be visible to do a layout.
+//                mExpandedParams.y = -mDisplayMetrics.heightPixels;
+//            }
+//            int max = h;
+//            if (mExpandedParams.y > max) {
+//                mExpandedParams.y = max;
+//            }
+//            int min = mTrackingPosition;
+//            if (mExpandedParams.y < min) {
+//                mExpandedParams.y = min;
+//            }
+//
+//            boolean visible = (mTrackingPosition + mTrackingView.getHeight()) > h;
+//            if (!visible) {
+//                // if the contents aren't visible, move the expanded view way off screen
+//                // because the window itself extends below the content view.
+//                mExpandedParams.y = -disph;
+//            }
+//            mExpandedDialog.getWindow().setAttributes(mExpandedParams);
+//
+//            // As long as this isn't just a repositioning that's not supposed to affect
+//            // the user's perception of what's showing, call to say that the visibility
+//            // has changed. (Otherwise, someone else will call to do that).
+//            if (expandedPosition != EXPANDED_LEAVE_ALONE) {
+//                if (SPEW) Slog.d(TAG, "updateExpandedViewPos visibilityChanged(" + visible + ")");
+//                visibilityChanged(visible);
+//            }
+//        }
+//
+//        if (SPEW) {
+//            Slog.d(TAG, "updateExpandedViewPos after  expandedPosition=" + expandedPosition
+//                    + " mTrackingParams.y=" + mTrackingParams.y
+//                    + " mTrackingPosition=" + mTrackingPosition
+//                    + " mExpandedParams.y=" + mExpandedParams.y
+//                    + " mExpandedParams.height=" + mExpandedParams.height);
+//        }
     }
 
     int getExpandedHeight(int disph) {
@@ -2001,7 +1985,7 @@
             Slog.d(TAG, "getExpandedHeight(" + disph + "): sbView="
                     + mStatusBarView.getHeight() + " closeView=" + mCloseView.getHeight());
         }
-        return disph - mStatusBarView.getHeight() - mCloseView.getHeight();
+        return disph; // - mStatusBarView.getHeight();
     }
 
     void updateDisplaySize() {
@@ -2215,8 +2199,6 @@
         if (mClearButton instanceof TextView) {
             ((TextView)mClearButton).setText(context.getText(R.string.status_bar_clear_all_button));
         }
-        mNoNotificationsTitle.setText(context.getText(R.string.status_bar_no_notifications_title));
-
         loadDimens();
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
index 809b742..16071d4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
@@ -64,7 +64,7 @@
     @Override
     protected void onAttachedToWindow() {
         super.onAttachedToWindow();
-        mService.onBarViewAttached();
+        //mService.onBarViewAttached();
     }
     
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/TrackingView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/TrackingView.java
deleted file mode 100644
index cc23afc..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/TrackingView.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.statusbar.phone;
-
-import android.content.Context;
-import android.os.Handler;
-import android.util.AttributeSet;
-import android.view.Display;
-import android.view.KeyEvent;
-import android.view.WindowManager;
-import android.widget.LinearLayout;
-
-
-public class TrackingView extends LinearLayout {
-    PhoneStatusBar mService;
-    boolean mTracking;
-    int mStartX, mStartY;
-    Handler mHandler = new Handler();
-
-    public TrackingView(Context context, AttributeSet attrs) {
-        super(context, attrs);
-    }
-    
-    @Override
-    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
-        super.onLayout(changed, left, top, right, bottom);
-    }
-
-    @Override
-    public boolean dispatchKeyEvent(KeyEvent event) {
-        boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
-        switch (event.getKeyCode()) {
-        case KeyEvent.KEYCODE_BACK:
-            if (down) {
-                //mService.deactivate();
-            }
-            return true;
-        }
-        return super.dispatchKeyEvent(event);
-    }
-
-    @Override
-    protected void onAttachedToWindow() {
-        super.onAttachedToWindow();
-        mService.onTrackingViewAttached();
-    }
-
-    @Override
-    protected void onWindowVisibilityChanged(int visibility) {
-        super.onWindowVisibilityChanged(visibility);
-        if (visibility == VISIBLE) {
-            mHandler.post(new Runnable() {
-                @Override public void run() {
-                    mService.updateExpandedViewPos(PhoneStatusBar.EXPANDED_LEAVE_ALONE);
-                }
-            });
-        }
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NotificationRowLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NotificationRowLayout.java
index 3649f75e..9fd89ed 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NotificationRowLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NotificationRowLayout.java
@@ -18,6 +18,7 @@
 
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
+import android.animation.LayoutTransition;
 import android.animation.ObjectAnimator;
 import android.animation.ValueAnimator;
 import android.content.Context;
@@ -31,13 +32,14 @@
 import android.view.View;
 import android.view.ViewConfiguration;
 import android.view.ViewGroup;
+import android.widget.LinearLayout;
 
 import com.android.systemui.R;
 import com.android.systemui.SwipeHelper;
 
 import java.util.HashMap;
 
-public class NotificationRowLayout extends ViewGroup implements SwipeHelper.Callback {
+public class NotificationRowLayout extends LinearLayout implements SwipeHelper.Callback {
     private static final String TAG = "NotificationRowLayout";
     private static final boolean DEBUG = false;
     private static final boolean SLOW_ANIMATIONS = DEBUG;
@@ -48,9 +50,6 @@
     boolean mAnimateBounds = true;
 
     Rect mTmpRect = new Rect();
-    int mNumRows = 0;
-    int mRowHeight = 0;
-    int mHeight = 0;
 
     HashMap<View, ValueAnimator> mAppearingViews = new HashMap<View, ValueAnimator>();
     HashMap<View, ValueAnimator> mDisappearingViews = new HashMap<View, ValueAnimator>();
@@ -68,12 +67,9 @@
     public NotificationRowLayout(Context context, AttributeSet attrs, int defStyle) {
         super(context, attrs, defStyle);
 
-        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.NotificationRowLayout,
-                defStyle, 0);
-        mRowHeight = a.getDimensionPixelSize(R.styleable.NotificationRowLayout_rowHeight, 0);
-        a.recycle();
-
-        setLayoutTransition(null);
+        setLayoutTransition(new LayoutTransition());
+        
+        setOrientation(LinearLayout.VERTICAL);
 
         if (DEBUG) {
             setOnHierarchyChangeListener(new ViewGroup.OnHierarchyChangeListener() {
@@ -145,7 +141,7 @@
             if (slidingChild.getVisibility() == GONE) {
                 continue;
             }
-            y += mRowHeight;
+            y += slidingChild.getMeasuredHeight();
             if (touchY < y) return slidingChild;
         }
         return null;
@@ -164,31 +160,6 @@
         mSwipeHelper.setPagingTouchSlop(pagingTouchSlop);
     }
 
-    //**
-    @Override
-    public void addView(View child, int index, LayoutParams params) {
-        super.addView(child, index, params);
-
-        final View childF = child;
-
-        if (mAnimateBounds) {
-            final ObjectAnimator alphaFade = ObjectAnimator.ofFloat(child, "alpha", 0f, 1f);
-            alphaFade.setDuration(APPEAR_ANIM_LEN);
-            alphaFade.addListener(new AnimatorListenerAdapter() {
-                @Override
-                public void onAnimationEnd(Animator animation) {
-                    mAppearingViews.remove(childF);
-                    requestLayout(); // pick up any final changes in position
-                }
-            });
-
-            alphaFade.start();
-
-            mAppearingViews.put(child, alphaFade);
-
-            requestLayout(); // start the container animation
-        }
-    }
 
     /**
      * Sets a flag to tell us whether to actually remove views. Removal is delayed by setting this
@@ -209,58 +180,9 @@
     }
 
     @Override
-    public void removeView(View child) {
-        if (!mRemoveViews) {
-            // This flag is cleared during an animation that removes all notifications. There
-            // should be a call to remove all notifications when the animation is done, at which
-            // time the view will be removed.
-            return;
-        }
-        if (mAnimateBounds) {
-            if (mAppearingViews.containsKey(child)) {
-                mAppearingViews.remove(child);
-            }
-
-            // Don't fade it out if it already has a low alpha value, but run a non-visual
-            // animation which is used by onLayout() to animate shrinking the gap that it left
-            // in the list
-            ValueAnimator anim;
-            float currentAlpha = child.getAlpha();
-            if (currentAlpha > .1) {
-                anim = ObjectAnimator.ofFloat(child, "alpha", currentAlpha, 0);
-            } else {
-                if (currentAlpha > 0) {
-                    // Just make it go away - no need to render it anymore
-                    child.setAlpha(0);
-                }
-                anim = ValueAnimator.ofFloat(0, 1);
-            }
-            anim.setDuration(DISAPPEAR_ANIM_LEN);
-            final View childF = child;
-            anim.addListener(new AnimatorListenerAdapter() {
-                @Override
-                public void onAnimationEnd(Animator animation) {
-                    if (DEBUG) Slog.d(TAG, "actually removing child: " + childF);
-                    NotificationRowLayout.super.removeView(childF);
-                    mDisappearingViews.remove(childF);
-                    requestLayout(); // pick up any final changes in position
-                }
-            });
-
-            anim.start();
-            mDisappearingViews.put(child, anim);
-
-            requestLayout(); // start the container animation
-        } else {
-            super.removeView(child);
-        }
-    }
-    //**
-
-    @Override
     public void onFinishInflate() {
         super.onFinishInflate();
-        setWillNotDraw(false);
+        if (DEBUG) setWillNotDraw(false);
     }
 
     @Override
@@ -276,111 +198,4 @@
             c.restore();
         }
     }
-
-    @Override
-    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
-        final int count = getChildCount();
-
-        // pass 1: count the number of non-GONE views
-        int numRows = 0;
-        for (int i = 0; i < count; i++) {
-            final View child = getChildAt(i);
-            if (child.getVisibility() == GONE) {
-                continue;
-            }
-            if (mDisappearingViews.containsKey(child)) {
-                continue;
-            }
-            numRows++;
-        }
-        if (numRows != mNumRows) {
-            // uh oh, now you made us go and do work
-            
-            final int computedHeight = numRows * mRowHeight;
-            if (DEBUG) {
-                Slog.d(TAG, String.format("rows went from %d to %d, resizing to %dpx",
-                            mNumRows, numRows, computedHeight));
-            }
-
-            mNumRows = numRows;
-
-            if (mAnimateBounds && isShown()) {
-                ObjectAnimator.ofInt(this, "forcedHeight", computedHeight)
-                    .setDuration(APPEAR_ANIM_LEN)
-                    .start();
-            } else {
-                setForcedHeight(computedHeight);
-            }
-        }
-
-        // pass 2: you know, do the measuring
-        final int childWidthMS = widthMeasureSpec;
-        final int childHeightMS = MeasureSpec.makeMeasureSpec(
-                mRowHeight, MeasureSpec.EXACTLY);
-
-        for (int i = 0; i < count; i++) {
-            final View child = getChildAt(i);
-            if (child.getVisibility() == GONE) {
-                continue;
-            }
-
-            child.measure(childWidthMS, childHeightMS);
-        }
-
-        setMeasuredDimension(
-                getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
-                resolveSize(getForcedHeight(), heightMeasureSpec));
-    }
-
-    @Override
-    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
-        final int width = right - left;
-        final int height = bottom - top;
-
-        if (DEBUG) Slog.d(TAG, "onLayout: height=" + height);
-
-        final int count = getChildCount();
-        int y = 0;
-        for (int i = 0; i < count; i++) {
-            final View child = getChildAt(i);
-            if (child.getVisibility() == GONE) {
-                continue;
-            }
-            float progress = 1.0f;
-            if (mDisappearingViews.containsKey(child)) {
-                progress = 1.0f - mDisappearingViews.get(child).getAnimatedFraction();
-            } else if (mAppearingViews.containsKey(child)) {
-                progress = 1.0f - mAppearingViews.get(child).getAnimatedFraction();
-            }
-            if (progress > 1.0f) {
-                if (DEBUG) {
-                    Slog.w(TAG, "progress=" + progress + " > 1!!! " + child);
-                }
-                progress = 1f;
-            }
-            final int thisRowHeight = (int)(progress * mRowHeight);
-            if (DEBUG) {
-                Slog.d(TAG, String.format(
-                            "laying out child #%d: (0, %d, %d, %d) h=%d",
-                            i, y, width, y + thisRowHeight, thisRowHeight));
-            }
-            child.layout(0, y, width, y + thisRowHeight);
-            y += thisRowHeight;
-        }
-        if (DEBUG) {
-            Slog.d(TAG, "onLayout: final y=" + y);
-        }
-    }
-
-    public void setForcedHeight(int h) {
-        if (DEBUG) Slog.d(TAG, "forcedHeight: " + h);
-        if (h != mHeight) {
-            mHeight = h;
-            requestLayout();
-        }
-    }
-
-    public int getForcedHeight() {
-        return mHeight;
-    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
index 6e56cd4..eda52fc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
@@ -75,9 +75,10 @@
 import com.android.systemui.R;
 import com.android.systemui.recent.RecentTasksLoader;
 import com.android.systemui.recent.RecentsPanelView;
+import com.android.systemui.statusbar.BaseStatusBar;
 import com.android.systemui.statusbar.NotificationData;
 import com.android.systemui.statusbar.SignalClusterView;
-import com.android.systemui.statusbar.StatusBar;
+import com.android.systemui.statusbar.BaseStatusBar;
 import com.android.systemui.statusbar.StatusBarIconView;
 import com.android.systemui.statusbar.policy.BatteryController;
 import com.android.systemui.statusbar.policy.BluetoothController;
@@ -86,7 +87,7 @@
 import com.android.systemui.statusbar.policy.NetworkController;
 import com.android.systemui.statusbar.policy.Prefs;
 
-public class TabletStatusBar extends StatusBar implements
+public class TabletStatusBar extends BaseStatusBar implements
         HeightReceiver.OnBarHeightChangedListener,
         InputMethodsPanel.OnHardKeyboardEnabledChangeListener,
         RecentsPanelView.OnRecentsPanelVisibilityChangedListener {
@@ -199,6 +200,45 @@
 
     public Context getContext() { return mContext; }
 
+    @Override
+    protected void createAndAddWindows() {
+        addStatusBarWindow();
+        addPanelWindows();
+    }
+    
+    private void addStatusBarWindow() {
+        final View sb = makeStatusBarView();
+        final int height = getStatusBarHeight();
+
+        final WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
+                ViewGroup.LayoutParams.MATCH_PARENT,
+                height,
+                WindowManager.LayoutParams.TYPE_STATUS_BAR,
+                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
+                    | WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING
+                    | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
+                // We use a pixel format of RGB565 for the status bar to save memory bandwidth and
+                // to ensure that the layer can be handled by HWComposer.  On some devices the
+                // HWComposer is unable to handle SW-rendered RGBX_8888 layers.
+                PixelFormat.RGB_565);
+
+        // the status bar should be in an overlay if possible
+        final Display defaultDisplay
+            = ((WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE))
+                .getDefaultDisplay();
+
+        // We explicitly leave FLAG_HARDWARE_ACCELERATED out of the flags.  The status bar occupies
+        // very little screen real-estate and is updated fairly frequently.  By using CPU rendering
+        // for the status bar, we prevent the GPU from having to wake up just to do these small
+        // updates, which should help keep power consumption down.
+
+        lp.gravity = getStatusBarGravity();
+        lp.setTitle("StatusBar");
+        lp.packageName = mContext.getPackageName();
+        lp.windowAnimations = R.style.Animation_StatusBar;
+        WindowManagerImpl.getDefault().addView(sb, lp);
+    }
+
     protected void addPanelWindows() {
         final Context context = mContext;
         final Resources res = mContext.getResources();
@@ -379,6 +419,14 @@
         lp.windowAnimations = android.R.style.Animation_Dialog;
 
         WindowManagerImpl.getDefault().addView(mCompatModePanel, lp);
+        
+        mRecentButton.setOnTouchListener(mRecentsPanel);
+
+        mPile = (ViewGroup)mNotificationPanel.findViewById(R.id.content);
+        mPile.removeAllViews();
+
+        ScrollView scroller = (ScrollView)mPile.getParent();
+        scroller.setFillViewport(true);
     }
 
     private int getNotificationPanelHeight() {
@@ -599,16 +647,6 @@
         // set the initial view visibility
         setAreThereNotifications();
 
-        // Add the windows
-        addPanelWindows();
-        mRecentButton.setOnTouchListener(mRecentsPanel);
-
-        mPile = (ViewGroup)mNotificationPanel.findViewById(R.id.content);
-        mPile.removeAllViews();
-
-        ScrollView scroller = (ScrollView)mPile.getParent();
-        scroller.setFillViewport(true);
-
         mHeightReceiver.addOnBarHeightChangedListener(this);
 
         // receive broadcasts
@@ -1942,6 +1980,7 @@
         pw.println("mNetworkController:");
         mNetworkController.dump(fd, pw, args);
     }
+
 }
 
 
diff --git a/policy/src/com/android/internal/policy/impl/KeyguardViewBase.java b/policy/src/com/android/internal/policy/impl/KeyguardViewBase.java
index f204070..39fdf92 100644
--- a/policy/src/com/android/internal/policy/impl/KeyguardViewBase.java
+++ b/policy/src/com/android/internal/policy/impl/KeyguardViewBase.java
@@ -72,8 +72,9 @@
         }
     };
 
-    public KeyguardViewBase(Context context) {
+    public KeyguardViewBase(Context context, KeyguardViewCallback callback) {
         super(context);
+        mCallback = callback;
         resetBackground();
     }
 
@@ -81,11 +82,6 @@
         setBackgroundDrawable(mBackgroundDrawable);
     }
 
-    // used to inject callback
-    void setCallback(KeyguardViewCallback callback) {
-        mCallback = callback;
-    }
-
     public KeyguardViewCallback getCallback() {
         return mCallback;
     }
diff --git a/policy/src/com/android/internal/policy/impl/KeyguardViewManager.java b/policy/src/com/android/internal/policy/impl/KeyguardViewManager.java
index 4bba71b..7100e89 100644
--- a/policy/src/com/android/internal/policy/impl/KeyguardViewManager.java
+++ b/policy/src/com/android/internal/policy/impl/KeyguardViewManager.java
@@ -158,9 +158,9 @@
 
         if (mKeyguardView == null) {
             if (DEBUG) Log.d(TAG, "keyguard view is null, creating it...");
-            mKeyguardView = mKeyguardViewProperties.createKeyguardView(mContext, mUpdateMonitor, this);
+            mKeyguardView = mKeyguardViewProperties.createKeyguardView(mContext, mCallback,
+                    mUpdateMonitor, this);
             mKeyguardView.setId(R.id.lock_screen);
-            mKeyguardView.setCallback(mCallback);
 
             final ViewGroup.LayoutParams lp = new FrameLayout.LayoutParams(
                     ViewGroup.LayoutParams.MATCH_PARENT,
diff --git a/policy/src/com/android/internal/policy/impl/KeyguardViewProperties.java b/policy/src/com/android/internal/policy/impl/KeyguardViewProperties.java
index bda08eb..51b7f1e 100644
--- a/policy/src/com/android/internal/policy/impl/KeyguardViewProperties.java
+++ b/policy/src/com/android/internal/policy/impl/KeyguardViewProperties.java
@@ -24,16 +24,17 @@
  * of whether the keyguard instance is around or not.
  */
 public interface KeyguardViewProperties {
-    
+
     /**
      * Create a keyguard view.
      * @param context the context to use when creating the view.
+     * @param callback keyguard callback object for pokewakelock(), etc.
      * @param updateMonitor configuration may be based on this.
      * @param controller for talking back with the containing window.
      * @return the view.
      */
     KeyguardViewBase createKeyguardView(Context context,
-            KeyguardUpdateMonitor updateMonitor,
+            KeyguardViewCallback mCallback, KeyguardUpdateMonitor updateMonitor,
             KeyguardWindowController controller);
 
     /**
diff --git a/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java b/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java
index 1e9784c..3ca57c6 100644
--- a/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java
+++ b/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java
@@ -291,17 +291,16 @@
 
     /**
      * @param context Used to inflate, and create views.
+     * @param callback Keyguard callback object for pokewakelock(), etc.
      * @param updateMonitor Knows the state of the world, and passed along to each
      *   screen so they can use the knowledge, and also register for callbacks
      *   on dynamic information.
      * @param lockPatternUtils Used to look up state of lock pattern.
      */
     public LockPatternKeyguardView(
-            Context context,
-            KeyguardUpdateMonitor updateMonitor,
-            LockPatternUtils lockPatternUtils,
-            KeyguardWindowController controller) {
-        super(context);
+            Context context, KeyguardViewCallback callback, KeyguardUpdateMonitor updateMonitor,
+            LockPatternUtils lockPatternUtils, KeyguardWindowController controller) {
+        super(context, callback);
 
         mHandler = new Handler(this);
         mConfiguration = context.getResources().getConfiguration();
diff --git a/policy/src/com/android/internal/policy/impl/LockPatternKeyguardViewProperties.java b/policy/src/com/android/internal/policy/impl/LockPatternKeyguardViewProperties.java
index 19adb3e..d7fb19a 100644
--- a/policy/src/com/android/internal/policy/impl/LockPatternKeyguardViewProperties.java
+++ b/policy/src/com/android/internal/policy/impl/LockPatternKeyguardViewProperties.java
@@ -43,9 +43,10 @@
     }
 
     public KeyguardViewBase createKeyguardView(Context context,
+            KeyguardViewCallback callback,
             KeyguardUpdateMonitor updateMonitor,
             KeyguardWindowController controller) {
-        return new LockPatternKeyguardView(context, updateMonitor,
+        return new LockPatternKeyguardView(context, callback, updateMonitor,
                 mLockPatternUtils, controller);
     }
 
diff --git a/policy/tests/src/com/android/internal/policy/impl/LockPatternKeyguardViewTest.java b/policy/tests/src/com/android/internal/policy/impl/LockPatternKeyguardViewTest.java
index bdfe652..db71e2b 100644
--- a/policy/tests/src/com/android/internal/policy/impl/LockPatternKeyguardViewTest.java
+++ b/policy/tests/src/com/android/internal/policy/impl/LockPatternKeyguardViewTest.java
@@ -17,6 +17,7 @@
 package com.android.internal.policy.impl;
 
 import android.content.Context;
+import com.android.internal.policy.impl.KeyguardViewCallback;
 import com.android.internal.telephony.IccCard;
 import android.content.res.Configuration;
 import android.test.AndroidTestCase;
@@ -133,9 +134,10 @@
 
 
 
-        private TestableLockPatternKeyguardView(Context context, KeyguardUpdateMonitor updateMonitor,
+        private TestableLockPatternKeyguardView(Context context, KeyguardViewCallback callback,
+                KeyguardUpdateMonitor updateMonitor,
                 LockPatternUtils lockPatternUtils, KeyguardWindowController controller) {
-            super(context, updateMonitor, lockPatternUtils, controller);
+            super(context, callback, updateMonitor, lockPatternUtils, controller);
         }
 
         @Override
@@ -198,14 +200,13 @@
         super.setUp();
         mUpdateMonitor = new MockUpdateMonitor(getContext());
         mLockPatternUtils = new MockLockPatternUtils(getContext());
+        mKeyguardViewCallback = new MockKeyguardCallback();
 
-        mLPKV = new TestableLockPatternKeyguardView(getContext(), mUpdateMonitor,
-                mLockPatternUtils, new KeyguardWindowController() {
+        mLPKV = new TestableLockPatternKeyguardView(getContext(), mKeyguardViewCallback,
+                mUpdateMonitor, mLockPatternUtils, new KeyguardWindowController() {
             public void setNeedsInput(boolean needsInput) {
             }
         });
-        mKeyguardViewCallback = new MockKeyguardCallback();
-        mLPKV.setCallback(mKeyguardViewCallback);
     }
 
     public void testStateAfterCreatedWhileScreenOff() {
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 8f7b35c..fd7418c 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -310,10 +310,10 @@
     }
 
     result.append("Global session refs:\n");
-    result.append(" session pid cnt\n");
+    result.append(" session pid count\n");
     for (size_t i = 0; i < mAudioSessionRefs.size(); i++) {
         AudioSessionRef *r = mAudioSessionRefs[i];
-        snprintf(buffer, SIZE, " %7d %3d %3d\n", r->sessionid, r->pid, r->cnt);
+        snprintf(buffer, SIZE, " %7d %3d %3d\n", r->mSessionid, r->mPid, r->mCnt);
         result.append(buffer);
     }
     write(fd, result.string(), result.size());
@@ -1036,9 +1036,9 @@
     bool removed = false;
     for (size_t i = 0; i< num; ) {
         AudioSessionRef *ref = mAudioSessionRefs.itemAt(i);
-        ALOGV(" pid %d @ %d", ref->pid, i);
-        if (ref->pid == pid) {
-            ALOGV(" removing entry for pid %d session %d", pid, ref->sessionid);
+        ALOGV(" pid %d @ %d", ref->mPid, i);
+        if (ref->mPid == pid) {
+            ALOGV(" removing entry for pid %d session %d", pid, ref->mSessionid);
             mAudioSessionRefs.removeAt(i);
             delete ref;
             removed = true;
@@ -1053,7 +1053,7 @@
 }
 
 // audioConfigChanged_l() must be called with AudioFlinger::mLock held
-void AudioFlinger::audioConfigChanged_l(int event, audio_io_handle_t ioHandle, void *param2)
+void AudioFlinger::audioConfigChanged_l(int event, audio_io_handle_t ioHandle, const void *param2)
 {
     size_t size = mNotificationClients.size();
     for (size_t i = 0; i < size; i++) {
@@ -1462,7 +1462,9 @@
         // Assumes constructor is called by AudioFlinger with it's mLock held,
         // but it would be safer to explicitly pass initial masterVolume as parameter
         mMasterVolume(audioFlinger->masterVolumeSW_l()),
-        mLastWriteTime(0), mNumWrites(0), mNumDelayedWrites(0), mInWrite(false)
+        mLastWriteTime(0), mNumWrites(0), mNumDelayedWrites(0), mInWrite(false),
+        // mMixerStatus
+        mPrevMixerStatus(MIXER_IDLE)
 {
     snprintf(mName, kNameLength, "AudioOut_%X", id);
 
@@ -1919,10 +1921,9 @@
 
 AudioFlinger::MixerThread::MixerThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output,
         audio_io_handle_t id, uint32_t device, type_t type)
-    :   PlaybackThread(audioFlinger, output, id, device, type),
-        mAudioMixer(new AudioMixer(mFrameCount, mSampleRate)),
-        mPrevMixerStatus(MIXER_IDLE)
+    :   PlaybackThread(audioFlinger, output, id, device, type)
 {
+    mAudioMixer = new AudioMixer(mFrameCount, mSampleRate);
     // FIXME - Current mixer implementation only supports stereo output
     if (mChannelCount == 1) {
         ALOGE("Invalid audio hardware channel count");
@@ -1991,44 +1992,59 @@
     }
 }
 
-bool AudioFlinger::MixerThread::threadLoop()
+bool AudioFlinger::PlaybackThread::threadLoop()
 {
-    // DirectOutputThread has single trackToRemove instead of Vector
     Vector< sp<Track> > tracksToRemove;
-    // DirectOutputThread has activeTrack here
-    nsecs_t standbyTime = systemTime();
-    size_t mixBufferSize = mFrameCount * mFrameSize;
 
+    standbyTime = systemTime();
+    mixBufferSize = mFrameCount * mFrameSize;
+
+    // MIXER
     // FIXME: Relaxed timing because of a certain device that can't meet latency
     // Should be reduced to 2x after the vendor fixes the driver issue
     // increase threshold again due to low power audio mode. The way this warning threshold is
     // calculated and its usefulness should be reconsidered anyway.
     nsecs_t maxPeriod = seconds(mFrameCount) / mSampleRate * 15;
     nsecs_t lastWarning = 0;
-    bool longStandbyExit = false;
+if (mType == MIXER) {
+    longStandbyExit = false;
+}
 
-    uint32_t activeSleepTime = activeSleepTimeUs();
-    uint32_t idleSleepTime = idleSleepTimeUs();
-    uint32_t sleepTime = idleSleepTime;
+    // DUPLICATING
+    // FIXME could this be made local to while loop?
+    writeFrames = 0;
 
-    uint32_t sleepTimeShift = 0;
+    activeSleepTime = activeSleepTimeUs();
+    idleSleepTime = idleSleepTimeUs();
+    sleepTime = idleSleepTime;
+
+if (mType == MIXER) {
+    sleepTimeShift = 0;
+}
+
+    // MIXER
     CpuStats cpuStats;
 
-    // DirectOutputThread has shorter standbyDelay
+    // DIRECT
+if (mType == DIRECT) {
+    // use shorter standby delay as on normal output to release
+    // hardware resources as soon as possible
+    standbyDelay = microseconds(activeSleepTime*2);
+}
 
     acquireWakeLock();
 
     while (!exitPending())
     {
+if (mType == MIXER) {
         cpuStats.sample();
-
-        // DirectOutputThread has rampVolume, leftVol, rightVol
+}
 
         Vector< sp<EffectChain> > effectChains;
 
         processConfigEvents();
 
-        mixer_state mixerStatus = MIXER_IDLE;
+        mMixerStatus = MIXER_IDLE;
         { // scope for mLock
 
             Mutex::Autolock _l(mLock);
@@ -2036,23 +2052,34 @@
             if (checkForNewParameters_l()) {
                 mixBufferSize = mFrameCount * mFrameSize;
 
+if (mType == MIXER) {
                 // FIXME: Relaxed timing because of a certain device that can't meet latency
                 // Should be reduced to 2x after the vendor fixes the driver issue
                 // increase threshold again due to low power audio mode. The way this warning
                 // threshold is calculated and its usefulness should be reconsidered anyway.
                 maxPeriod = seconds(mFrameCount) / mSampleRate * 15;
+}
+
+                updateWaitTime_l();
 
                 activeSleepTime = activeSleepTimeUs();
                 idleSleepTime = idleSleepTimeUs();
-                // DirectOutputThread updates standbyDelay also
+
+if (mType == DIRECT) {
+                standbyDelay = microseconds(activeSleepTime*2);
+}
+
             }
 
+            saveOutputTracks();
+
             // put audio hardware into standby after short delay
             if (CC_UNLIKELY((!mActiveTracks.size() && systemTime() > standbyTime) ||
                         mSuspended > 0)) {
                 if (!mStandby) {
-                    ALOGV("Audio hardware entering standby, mixer %p, suspend count %u", this, mSuspended);
-                    mOutput->stream->common.standby(&mOutput->stream->common);
+
+                    threadLoop_standby();
+
                     mStandby = true;
                     mBytesWritten = 0;
                 }
@@ -2061,6 +2088,8 @@
                     // we're about to wait, flush the binder command buffer
                     IPCThreadState::self()->flushCommands();
 
+                    clearOutputTracks();
+
                     if (exitPending()) break;
 
                     releaseWakeLock_l();
@@ -2071,16 +2100,32 @@
                     acquireWakeLock_l();
 
                     mPrevMixerStatus = MIXER_IDLE;
+
                     checkSilentMode_l();
 
+if (mType == MIXER || mType == DUPLICATING) {
                     standbyTime = systemTime() + mStandbyTimeInNsecs;
+}
+
+if (mType == DIRECT) {
+                    standbyTime = systemTime() + standbyDelay;
+}
+
                     sleepTime = idleSleepTime;
+
+if (mType == MIXER) {
                     sleepTimeShift = 0;
+}
+
                     continue;
                 }
             }
 
-            mixerStatus = prepareTracks_l(&tracksToRemove);
+            mixer_state newMixerStatus = prepareTracks_l(&tracksToRemove);
+            // Shift in the new status; this could be a queue if it's
+            // useful to filter the mixer status over several cycles.
+            mPrevMixerStatus = mMixerStatus;
+            mMixerStatus = newMixerStatus;
 
             // prevent any changes in effect chain list and in each effect chain
             // during mixing and effect process as the audio buffers could be deleted
@@ -2088,58 +2133,10 @@
             lockEffectChains_l(effectChains);
         }
 
-        if (CC_LIKELY(mixerStatus == MIXER_TRACKS_READY)) {
-            // obtain the presentation timestamp of the next output buffer
-            int64_t pts;
-            status_t status = INVALID_OPERATION;
-
-            if (NULL != mOutput->stream->get_next_write_timestamp) {
-                status = mOutput->stream->get_next_write_timestamp(
-                        mOutput->stream, &pts);
-            }
-
-            if (status != NO_ERROR) {
-                pts = AudioBufferProvider::kInvalidPTS;
-            }
-
-            // mix buffers...
-            mAudioMixer->process(pts);
-            // increase sleep time progressively when application underrun condition clears.
-            // Only increase sleep time if the mixer is ready for two consecutive times to avoid
-            // that a steady state of alternating ready/not ready conditions keeps the sleep time
-            // such that we would underrun the audio HAL.
-            if ((sleepTime == 0) && (sleepTimeShift > 0)) {
-                sleepTimeShift--;
-            }
-            sleepTime = 0;
-            standbyTime = systemTime() + mStandbyTimeInNsecs;
-            //TODO: delay standby when effects have a tail
+        if (CC_LIKELY(mMixerStatus == MIXER_TRACKS_READY)) {
+            threadLoop_mix();
         } else {
-            // If no tracks are ready, sleep once for the duration of an output
-            // buffer size, then write 0s to the output
-            if (sleepTime == 0) {
-                if (mixerStatus == MIXER_TRACKS_ENABLED) {
-                    sleepTime = activeSleepTime >> sleepTimeShift;
-                    if (sleepTime < kMinThreadSleepTimeUs) {
-                        sleepTime = kMinThreadSleepTimeUs;
-                    }
-                    // reduce sleep time in case of consecutive application underruns to avoid
-                    // starving the audio HAL. As activeSleepTimeUs() is larger than a buffer
-                    // duration we would end up writing less data than needed by the audio HAL if
-                    // the condition persists.
-                    if (sleepTimeShift < kMaxThreadSleepTimeShift) {
-                        sleepTimeShift++;
-                    }
-                } else {
-                    sleepTime = idleSleepTime;
-                }
-            } else if (mBytesWritten != 0 ||
-                       (mixerStatus == MIXER_TRACKS_ENABLED && longStandbyExit)) {
-                memset (mMixBuffer, 0, mixBufferSize);
-                sleepTime = 0;
-                ALOGV_IF((mBytesWritten == 0 && (mixerStatus == MIXER_TRACKS_ENABLED && longStandbyExit)), "anticipated start");
-            }
-            // TODO add standby time extension fct of effect tail
+            threadLoop_sleepTime();
         }
 
         if (mSuspended > 0) {
@@ -2148,9 +2145,6 @@
 
         // only process effects if we're going to write
         if (sleepTime == 0) {
-
-            // DirectOutputThread adds applyVolume here
-
             for (size_t i = 0; i < effectChains.size(); i ++) {
                 effectChains[i]->process_l();
             }
@@ -2161,16 +2155,11 @@
 
         // sleepTime == 0 means we must write to audio hardware
         if (sleepTime == 0) {
-            // FIXME Only in MixerThread, and rewrite to reduce number of system calls
-            mLastWriteTime = systemTime();
-            mInWrite = true;
-            mBytesWritten += mixBufferSize;
-            int bytesWritten = (int)mOutput->stream->write(mOutput->stream, mMixBuffer, mixBufferSize);
-            if (bytesWritten < 0) mBytesWritten -= mixBufferSize;
-            mNumWrites++;
-            mInWrite = false;
 
-            // Only in MixerThread: start of write blocked detection
+            threadLoop_write();
+
+if (mType == MIXER) {
+            // write blocked detection
             nsecs_t now = systemTime();
             nsecs_t delta = now - mLastWriteTime;
             if (!mStandby && delta > maxPeriod) {
@@ -2180,11 +2169,13 @@
                             ns2ms(delta), mNumDelayedWrites, this);
                     lastWarning = now;
                 }
+                // FIXME this is broken: longStandbyExit should be handled out of the if() and with
+                // a different threshold. Or completely removed for what it is worth anyway...
                 if (mStandby) {
                     longStandbyExit = true;
                 }
             }
-            // end of write blocked detection
+}
 
             mStandby = false;
         } else {
@@ -2196,6 +2187,11 @@
         // same lock.
         tracksToRemove.clear();
 
+        // FIXME I don't understand the need for this here;
+        //       it was in the original code but maybe the
+        //       assignment in saveOutputTracks() makes this unnecessary?
+        clearOutputTracks();
+
         // Effect chains will be actually deleted here if they were removed from
         // mEffectChains list during mixing or effects processing
         effectChains.clear();
@@ -2204,10 +2200,15 @@
         // is now local to this block, but will keep it for now (at least until merge done).
     }
 
+if (mType == MIXER || mType == DIRECT) {
     // put output stream into standby mode
     if (!mStandby) {
         mOutput->stream->common.standby(&mOutput->stream->common);
     }
+}
+if (mType == DUPLICATING) {
+    // for DuplicatingThread, standby mode is handled by the outputTracks
+}
 
     releaseWakeLock();
 
@@ -2215,6 +2216,84 @@
     return false;
 }
 
+// shared by MIXER and DIRECT, overridden by DUPLICATING
+void AudioFlinger::PlaybackThread::threadLoop_write()
+{
+    // FIXME rewrite to reduce number of system calls
+    mLastWriteTime = systemTime();
+    mInWrite = true;
+    mBytesWritten += mixBufferSize;
+    int bytesWritten = (int)mOutput->stream->write(mOutput->stream, mMixBuffer, mixBufferSize);
+    if (bytesWritten < 0) mBytesWritten -= mixBufferSize;
+    mNumWrites++;
+    mInWrite = false;
+}
+
+// shared by MIXER and DIRECT, overridden by DUPLICATING
+void AudioFlinger::PlaybackThread::threadLoop_standby()
+{
+    ALOGV("Audio hardware entering standby, mixer %p, suspend count %u", this, mSuspended);
+    mOutput->stream->common.standby(&mOutput->stream->common);
+}
+
+void AudioFlinger::MixerThread::threadLoop_mix()
+{
+    // obtain the presentation timestamp of the next output buffer
+    int64_t pts;
+    status_t status = INVALID_OPERATION;
+
+    if (NULL != mOutput->stream->get_next_write_timestamp) {
+        status = mOutput->stream->get_next_write_timestamp(
+                mOutput->stream, &pts);
+    }
+
+    if (status != NO_ERROR) {
+        pts = AudioBufferProvider::kInvalidPTS;
+    }
+
+    // mix buffers...
+    mAudioMixer->process(pts);
+    // increase sleep time progressively when application underrun condition clears.
+    // Only increase sleep time if the mixer is ready for two consecutive times to avoid
+    // that a steady state of alternating ready/not ready conditions keeps the sleep time
+    // such that we would underrun the audio HAL.
+    if ((sleepTime == 0) && (sleepTimeShift > 0)) {
+        sleepTimeShift--;
+    }
+    sleepTime = 0;
+    standbyTime = systemTime() + mStandbyTimeInNsecs;
+    //TODO: delay standby when effects have a tail
+}
+
+void AudioFlinger::MixerThread::threadLoop_sleepTime()
+{
+    // If no tracks are ready, sleep once for the duration of an output
+    // buffer size, then write 0s to the output
+    if (sleepTime == 0) {
+        if (mMixerStatus == MIXER_TRACKS_ENABLED) {
+            sleepTime = activeSleepTime >> sleepTimeShift;
+            if (sleepTime < kMinThreadSleepTimeUs) {
+                sleepTime = kMinThreadSleepTimeUs;
+            }
+            // reduce sleep time in case of consecutive application underruns to avoid
+            // starving the audio HAL. As activeSleepTimeUs() is larger than a buffer
+            // duration we would end up writing less data than needed by the audio HAL if
+            // the condition persists.
+            if (sleepTimeShift < kMaxThreadSleepTimeShift) {
+                sleepTimeShift++;
+            }
+        } else {
+            sleepTime = idleSleepTime;
+        }
+    } else if (mBytesWritten != 0 ||
+               (mMixerStatus == MIXER_TRACKS_ENABLED && longStandbyExit)) {
+        memset (mMixBuffer, 0, mixBufferSize);
+        sleepTime = 0;
+        ALOGV_IF((mBytesWritten == 0 && (mMixerStatus == MIXER_TRACKS_ENABLED && longStandbyExit)), "anticipated start");
+    }
+    // TODO add standby time extension fct of effect tail
+}
+
 // prepareTracks_l() must be called with ThreadBase::mLock held
 AudioFlinger::PlaybackThread::mixer_state AudioFlinger::MixerThread::prepareTracks_l(
         Vector< sp<Track> > *tracksToRemove)
@@ -2466,7 +2545,6 @@
         memset(mMixBuffer, 0, mFrameCount * mChannelCount * sizeof(int16_t));
     }
 
-    mPrevMixerStatus = mixerStatus;
     return mixerStatus;
 }
 
@@ -2653,7 +2731,7 @@
 {
 }
 
-void AudioFlinger::DirectOutputThread::applyVolume(uint16_t leftVol, uint16_t rightVol, bool ramp)
+void AudioFlinger::DirectOutputThread::applyVolume()
 {
     // Do not apply volume on compressed audio
     if (!audio_is_linear_pcm(mFormat)) {
@@ -2672,7 +2750,7 @@
 
     size_t frameCount = mFrameCount;
     int16_t *out = mMixBuffer;
-    if (ramp) {
+    if (rampVolume) {
         if (mChannelCount == 1) {
             int32_t d = ((int32_t)leftVol - (int32_t)mLeftVolShort) << 16;
             int32_t vlInc = d / (int32_t)frameCount;
@@ -2727,320 +2805,181 @@
     mRightVolShort = rightVol;
 }
 
-bool AudioFlinger::DirectOutputThread::threadLoop()
+AudioFlinger::PlaybackThread::mixer_state AudioFlinger::DirectOutputThread::prepareTracks_l(
+    Vector< sp<Track> > *tracksToRemove
+)
 {
-    // MixerThread has Vector instead of single trackToRemove
     sp<Track> trackToRemove;
 
-    nsecs_t standbyTime = systemTime();
-    size_t mixBufferSize = mFrameCount * mFrameSize;
+    mixer_state mixerStatus = MIXER_IDLE;
 
-    // MixerThread has relaxed timing: maxPeriod, lastWarning, longStandbyExit
+    // find out which tracks need to be processed
+    if (mActiveTracks.size() != 0) {
+        sp<Track> t = mActiveTracks[0].promote();
+        // The track died recently
+        if (t == 0) return MIXER_IDLE;
 
-    uint32_t activeSleepTime = activeSleepTimeUs();
-    uint32_t idleSleepTime = idleSleepTimeUs();
-    uint32_t sleepTime = idleSleepTime;
+        Track* const track = t.get();
+        audio_track_cblk_t* cblk = track->cblk();
 
-    // MixerThread has sleepTimeShift and cpuStats
+        // The first time a track is added we wait
+        // for all its buffers to be filled before processing it
+        if (cblk->framesReady() && track->isReady() &&
+                !track->isPaused() && !track->isTerminated())
+        {
+            //ALOGV("track %d u=%08x, s=%08x [OK]", track->name(), cblk->user, cblk->server);
 
-    // use shorter standby delay as on normal output to release
-    // hardware resources as soon as possible
-    nsecs_t standbyDelay = microseconds(activeSleepTime*2);
-
-    acquireWakeLock();
-
-    while (!exitPending())
-    {
-        // MixerThread has cpuStats.sample()
-
-        bool rampVolume;
-        uint16_t leftVol;
-        uint16_t rightVol;
-
-        Vector< sp<EffectChain> > effectChains;
-
-        processConfigEvents();
-
-        // MixerThread does not have activeTrack here
-        sp<Track> activeTrack;
-
-        mixer_state mixerStatus = MIXER_IDLE;
-        { // scope for the mLock
-
-            Mutex::Autolock _l(mLock);
-
-            if (checkForNewParameters_l()) {
-                mixBufferSize = mFrameCount * mFrameSize;
-
-                // different calculations here
-                standbyDelay = microseconds(activeSleepTime*2);
-
-                activeSleepTime = activeSleepTimeUs();
-                idleSleepTime = idleSleepTimeUs();
-                standbyDelay = microseconds(activeSleepTime*2);
+            if (track->mFillingUpStatus == Track::FS_FILLED) {
+                track->mFillingUpStatus = Track::FS_ACTIVE;
+                mLeftVolFloat = mRightVolFloat = 0;
+                mLeftVolShort = mRightVolShort = 0;
+                if (track->mState == TrackBase::RESUMING) {
+                    track->mState = TrackBase::ACTIVE;
+                    rampVolume = true;
+                }
+            } else if (cblk->server != 0) {
+                // If the track is stopped before the first frame was mixed,
+                // do not apply ramp
+                rampVolume = true;
+            }
+            // compute volume for this track
+            float left, right;
+            if (track->isMuted() || mMasterMute || track->isPausing() ||
+                mStreamTypes[track->streamType()].mute) {
+                left = right = 0;
+                if (track->isPausing()) {
+                    track->setPaused();
+                }
+            } else {
+                float typeVolume = mStreamTypes[track->streamType()].volume;
+                float v = mMasterVolume * typeVolume;
+                uint32_t vlr = cblk->getVolumeLR();
+                float v_clamped = v * (vlr & 0xFFFF);
+                if (v_clamped > MAX_GAIN) v_clamped = MAX_GAIN;
+                left = v_clamped/MAX_GAIN;
+                v_clamped = v * (vlr >> 16);
+                if (v_clamped > MAX_GAIN) v_clamped = MAX_GAIN;
+                right = v_clamped/MAX_GAIN;
             }
 
-            // put audio hardware into standby after short delay
-            if (CC_UNLIKELY((!mActiveTracks.size() && systemTime() > standbyTime) ||
-                        mSuspended > 0)) {
-                if (!mStandby) {
-                    ALOGV("Audio hardware entering standby, mixer %p, suspend count %u", this, mSuspended);
-                    mOutput->stream->common.standby(&mOutput->stream->common);
-                    mStandby = true;
-                    mBytesWritten = 0;
+            if (left != mLeftVolFloat || right != mRightVolFloat) {
+                mLeftVolFloat = left;
+                mRightVolFloat = right;
+
+                // If audio HAL implements volume control,
+                // force software volume to nominal value
+                if (mOutput->stream->set_volume(mOutput->stream, left, right) == NO_ERROR) {
+                    left = 1.0f;
+                    right = 1.0f;
                 }
 
-                if (!mActiveTracks.size() && mConfigEvents.isEmpty()) {
-                    // we're about to wait, flush the binder command buffer
-                    IPCThreadState::self()->flushCommands();
+                // Convert volumes from float to 8.24
+                uint32_t vl = (uint32_t)(left * (1 << 24));
+                uint32_t vr = (uint32_t)(right * (1 << 24));
 
-                    if (exitPending()) break;
-
-                    releaseWakeLock_l();
-                    // wait until we have something to do...
-                    ALOGV("Thread %p type %d TID %d going to sleep", this, mType, gettid());
-                    mWaitWorkCV.wait(mLock);
-                    ALOGV("Thread %p type %d TID %d waking up", this, mType, gettid());
-                    acquireWakeLock_l();
-
-                    // MixerThread has "mPrevMixerStatus = MIXER_IDLE"
-                    checkSilentMode_l();
-
-                    // MixerThread has different standbyDelay
-                    standbyTime = systemTime() + standbyDelay;
-                    sleepTime = idleSleepTime;
-                    // MixerThread has "sleepTimeShift = 0"
-                    continue;
-                }
-            }
-
-            // MixerThread has "mixerStatus = prepareTracks_l(...)"
-
-            // equivalent to MixerThread's lockEffectChains_l, but without the lock
-            // FIXME - is it OK to omit the lock here?
-            effectChains = mEffectChains;
-
-            // find out which tracks need to be processed
-            if (mActiveTracks.size() != 0) {
-                sp<Track> t = mActiveTracks[0].promote();
-                if (t == 0) continue;
-
-                Track* const track = t.get();
-                audio_track_cblk_t* cblk = track->cblk();
-
-                // The first time a track is added we wait
-                // for all its buffers to be filled before processing it
-                if (cblk->framesReady() && track->isReady() &&
-                        !track->isPaused() && !track->isTerminated())
-                {
-                    //ALOGV("track %d u=%08x, s=%08x [OK]", track->name(), cblk->user, cblk->server);
-
-                    if (track->mFillingUpStatus == Track::FS_FILLED) {
-                        track->mFillingUpStatus = Track::FS_ACTIVE;
-                        mLeftVolFloat = mRightVolFloat = 0;
-                        mLeftVolShort = mRightVolShort = 0;
-                        if (track->mState == TrackBase::RESUMING) {
-                            track->mState = TrackBase::ACTIVE;
-                            rampVolume = true;
-                        }
-                    } else if (cblk->server != 0) {
-                        // If the track is stopped before the first frame was mixed,
-                        // do not apply ramp
-                        rampVolume = true;
-                    }
-                    // compute volume for this track
-                    float left, right;
-                    if (track->isMuted() || mMasterMute || track->isPausing() ||
-                        mStreamTypes[track->streamType()].mute) {
-                        left = right = 0;
-                        if (track->isPausing()) {
-                            track->setPaused();
-                        }
-                    } else {
-                        float typeVolume = mStreamTypes[track->streamType()].volume;
-                        float v = mMasterVolume * typeVolume;
-                        uint32_t vlr = cblk->getVolumeLR();
-                        float v_clamped = v * (vlr & 0xFFFF);
-                        if (v_clamped > MAX_GAIN) v_clamped = MAX_GAIN;
-                        left = v_clamped/MAX_GAIN;
-                        v_clamped = v * (vlr >> 16);
-                        if (v_clamped > MAX_GAIN) v_clamped = MAX_GAIN;
-                        right = v_clamped/MAX_GAIN;
-                    }
-
-                    if (left != mLeftVolFloat || right != mRightVolFloat) {
-                        mLeftVolFloat = left;
-                        mRightVolFloat = right;
-
-                        // If audio HAL implements volume control,
-                        // force software volume to nominal value
-                        if (mOutput->stream->set_volume(mOutput->stream, left, right) == NO_ERROR) {
-                            left = 1.0f;
-                            right = 1.0f;
-                        }
-
-                        // Convert volumes from float to 8.24
-                        uint32_t vl = (uint32_t)(left * (1 << 24));
-                        uint32_t vr = (uint32_t)(right * (1 << 24));
-
-                        // Delegate volume control to effect in track effect chain if needed
-                        // only one effect chain can be present on DirectOutputThread, so if
-                        // there is one, the track is connected to it
-                        if (!effectChains.isEmpty()) {
-                            // Do not ramp volume if volume is controlled by effect
-                            if(effectChains[0]->setVolume_l(&vl, &vr)) {
-                                rampVolume = false;
-                            }
-                        }
-
-                        // Convert volumes from 8.24 to 4.12 format
-                        uint32_t v_clamped = (vl + (1 << 11)) >> 12;
-                        if (v_clamped > MAX_GAIN_INT) v_clamped = MAX_GAIN_INT;
-                        leftVol = (uint16_t)v_clamped;
-                        v_clamped = (vr + (1 << 11)) >> 12;
-                        if (v_clamped > MAX_GAIN_INT) v_clamped = MAX_GAIN_INT;
-                        rightVol = (uint16_t)v_clamped;
-                    } else {
-                        leftVol = mLeftVolShort;
-                        rightVol = mRightVolShort;
+                // Delegate volume control to effect in track effect chain if needed
+                // only one effect chain can be present on DirectOutputThread, so if
+                // there is one, the track is connected to it
+                if (!mEffectChains.isEmpty()) {
+                    // Do not ramp volume if volume is controlled by effect
+                    if (mEffectChains[0]->setVolume_l(&vl, &vr)) {
                         rampVolume = false;
                     }
-
-                    // reset retry count
-                    track->mRetryCount = kMaxTrackRetriesDirect;
-                    activeTrack = t;
-                    mixerStatus = MIXER_TRACKS_READY;
-                } else {
-                    //ALOGV("track %d u=%08x, s=%08x [NOT READY]", track->name(), cblk->user, cblk->server);
-                    if (track->isStopped()) {
-                        track->reset();
-                    }
-                    if (track->isTerminated() || track->isStopped() || track->isPaused()) {
-                        // We have consumed all the buffers of this track.
-                        // Remove it from the list of active tracks.
-                        trackToRemove = track;
-                    } else {
-                        // No buffers for this track. Give it a few chances to
-                        // fill a buffer, then remove it from active list.
-                        if (--(track->mRetryCount) <= 0) {
-                            ALOGV("BUFFER TIMEOUT: remove(%d) from active list", track->name());
-                            trackToRemove = track;
-                        } else {
-                            mixerStatus = MIXER_TRACKS_ENABLED;
-                        }
-                    }
                 }
+
+                // Convert volumes from 8.24 to 4.12 format
+                uint32_t v_clamped = (vl + (1 << 11)) >> 12;
+                if (v_clamped > MAX_GAIN_INT) v_clamped = MAX_GAIN_INT;
+                leftVol = (uint16_t)v_clamped;
+                v_clamped = (vr + (1 << 11)) >> 12;
+                if (v_clamped > MAX_GAIN_INT) v_clamped = MAX_GAIN_INT;
+                rightVol = (uint16_t)v_clamped;
+            } else {
+                leftVol = mLeftVolShort;
+                rightVol = mRightVolShort;
+                rampVolume = false;
             }
 
-            // remove all the tracks that need to be...
-            if (CC_UNLIKELY(trackToRemove != 0)) {
-                mActiveTracks.remove(trackToRemove);
-                if (!effectChains.isEmpty()) {
-                    ALOGV("stopping track on chain %p for session Id: %d", effectChains[0].get(),
-                            trackToRemove->sessionId());
-                    effectChains[0]->decActiveTrackCnt();
-                }
-                if (trackToRemove->isTerminated()) {
-                    removeTrack_l(trackToRemove);
-                }
-            }
-
-            lockEffectChains_l(effectChains);
-       }
-
-        // For DirectOutputThread, this test is equivalent to "activeTrack != 0"
-        if (CC_LIKELY(mixerStatus == MIXER_TRACKS_READY)) {
-            AudioBufferProvider::Buffer buffer;
-            size_t frameCount = mFrameCount;
-            int8_t *curBuf = (int8_t *)mMixBuffer;
-            // output audio to hardware
-            while (frameCount) {
-                buffer.frameCount = frameCount;
-                activeTrack->getNextBuffer(&buffer);
-                if (CC_UNLIKELY(buffer.raw == NULL)) {
-                    memset(curBuf, 0, frameCount * mFrameSize);
-                    break;
-                }
-                memcpy(curBuf, buffer.raw, buffer.frameCount * mFrameSize);
-                frameCount -= buffer.frameCount;
-                curBuf += buffer.frameCount * mFrameSize;
-                activeTrack->releaseBuffer(&buffer);
-            }
-            sleepTime = 0;
-            standbyTime = systemTime() + standbyDelay;
+            // reset retry count
+            track->mRetryCount = kMaxTrackRetriesDirect;
+            mActiveTrack = t;
+            mixerStatus = MIXER_TRACKS_READY;
         } else {
-            if (sleepTime == 0) {
-                if (mixerStatus == MIXER_TRACKS_ENABLED) {
-                    sleepTime = activeSleepTime;
+            //ALOGV("track %d u=%08x, s=%08x [NOT READY]", track->name(), cblk->user, cblk->server);
+            if (track->isStopped()) {
+                track->reset();
+            }
+            if (track->isTerminated() || track->isStopped() || track->isPaused()) {
+                // We have consumed all the buffers of this track.
+                // Remove it from the list of active tracks.
+                trackToRemove = track;
+            } else {
+                // No buffers for this track. Give it a few chances to
+                // fill a buffer, then remove it from active list.
+                if (--(track->mRetryCount) <= 0) {
+                    ALOGV("BUFFER TIMEOUT: remove(%d) from active list", track->name());
+                    trackToRemove = track;
                 } else {
-                    sleepTime = idleSleepTime;
+                    mixerStatus = MIXER_TRACKS_ENABLED;
                 }
-            } else if (mBytesWritten != 0 && audio_is_linear_pcm(mFormat)) {
-                memset (mMixBuffer, 0, mFrameCount * mFrameSize);
-                sleepTime = 0;
             }
         }
-
-        if (mSuspended > 0) {
-            sleepTime = suspendSleepTimeUs();
-        }
-
-        // only process effects if we're going to write
-        if (sleepTime == 0) {
-
-            // MixerThread does not have applyVolume
-            if (mixerStatus == MIXER_TRACKS_READY) {
-                applyVolume(leftVol, rightVol, rampVolume);
-            }
-
-            for (size_t i = 0; i < effectChains.size(); i ++) {
-                effectChains[i]->process_l();
-            }
-        }
-
-        // enable changes in effect chain
-        unlockEffectChains(effectChains);
-
-        // sleepTime == 0 means we must write to audio hardware
-        if (sleepTime == 0) {
-            mLastWriteTime = systemTime();
-            mInWrite = true;
-            mBytesWritten += mixBufferSize;
-            int bytesWritten = (int)mOutput->stream->write(mOutput->stream, mMixBuffer, mixBufferSize);
-            if (bytesWritten < 0) mBytesWritten -= mixBufferSize;
-            mNumWrites++;
-            mInWrite = false;
-
-            // MixerThread has write blocked detection here
-
-            mStandby = false;
-        } else {
-            usleep(sleepTime);
-        }
-
-        // finally let go of removed track(s), without the lock held
-        // since we can't guarantee the destructors won't acquire that
-        // same lock.
-        trackToRemove.clear();
-        activeTrack.clear();
-
-        // Effect chains will be actually deleted here if they were removed from
-        // mEffectChains list during mixing or effects processing
-        effectChains.clear();
-
-        // FIXME Note that the above .clear() is no longer necessary since effectChains
-        // is now local to this block, but will keep it for now (at least until merge done).
     }
 
-    // put output stream into standby mode
-    if (!mStandby) {
-        mOutput->stream->common.standby(&mOutput->stream->common);
+    // FIXME merge this with similar code for removing multiple tracks
+    // remove all the tracks that need to be...
+    if (CC_UNLIKELY(trackToRemove != 0)) {
+        tracksToRemove->add(trackToRemove);
+        mActiveTracks.remove(trackToRemove);
+        if (!mEffectChains.isEmpty()) {
+            ALOGV("stopping track on chain %p for session Id: %d", effectChains[0].get(),
+                    trackToRemove->sessionId());
+            mEffectChains[0]->decActiveTrackCnt();
+        }
+        if (trackToRemove->isTerminated()) {
+            removeTrack_l(trackToRemove);
+        }
     }
 
-    releaseWakeLock();
+    return mixerStatus;
+}
 
-    ALOGV("Thread %p type %d exiting", this, mType);
-    return false;
+void AudioFlinger::DirectOutputThread::threadLoop_mix()
+{
+    AudioBufferProvider::Buffer buffer;
+    size_t frameCount = mFrameCount;
+    int8_t *curBuf = (int8_t *)mMixBuffer;
+    // output audio to hardware
+    while (frameCount) {
+        buffer.frameCount = frameCount;
+        mActiveTrack->getNextBuffer(&buffer);
+        if (CC_UNLIKELY(buffer.raw == NULL)) {
+            memset(curBuf, 0, frameCount * mFrameSize);
+            break;
+        }
+        memcpy(curBuf, buffer.raw, buffer.frameCount * mFrameSize);
+        frameCount -= buffer.frameCount;
+        curBuf += buffer.frameCount * mFrameSize;
+        mActiveTrack->releaseBuffer(&buffer);
+    }
+    sleepTime = 0;
+    standbyTime = systemTime() + standbyDelay;
+    mActiveTrack.clear();
+    applyVolume();
+}
+
+void AudioFlinger::DirectOutputThread::threadLoop_sleepTime()
+{
+    if (sleepTime == 0) {
+        if (mMixerStatus == MIXER_TRACKS_ENABLED) {
+            sleepTime = activeSleepTime;
+        } else {
+            sleepTime = idleSleepTime;
+        }
+    } else if (mBytesWritten != 0 && audio_is_linear_pcm(mFormat)) {
+        memset (mMixBuffer, 0, mFrameCount * mFrameSize);
+        sleepTime = 0;
+    }
 }
 
 // getTrackName_l() must be called with ThreadBase::mLock held
@@ -3153,174 +3092,64 @@
     }
 }
 
-bool AudioFlinger::DuplicatingThread::threadLoop()
+void AudioFlinger::DuplicatingThread::threadLoop_mix()
 {
-    Vector< sp<Track> > tracksToRemove;
-    nsecs_t standbyTime = systemTime();
-    size_t mixBufferSize = mFrameCount * mFrameSize;
-
-    // Only in DuplicatingThread
-    SortedVector< sp<OutputTrack> > outputTracks;
-    uint32_t writeFrames = 0;
-
-    uint32_t activeSleepTime = activeSleepTimeUs();
-    uint32_t idleSleepTime = idleSleepTimeUs();
-    uint32_t sleepTime = idleSleepTime;
-
-    acquireWakeLock();
-
-    while (!exitPending())
-    {
-        // MixerThread has cpuStats.sample
-
-        Vector< sp<EffectChain> > effectChains;
-
-        processConfigEvents();
-
-        mixer_state mixerStatus = MIXER_IDLE;
-        { // scope for the mLock
-
-            Mutex::Autolock _l(mLock);
-
-            if (checkForNewParameters_l()) {
-                mixBufferSize = mFrameCount * mFrameSize;
-
-                // Only in DuplicatingThread
-                updateWaitTime();
-
-                activeSleepTime = activeSleepTimeUs();
-                idleSleepTime = idleSleepTimeUs();
-            }
-
-            // Only in DuplicatingThread
-            for (size_t i = 0; i < mOutputTracks.size(); i++) {
-                outputTracks.add(mOutputTracks[i]);
-            }
-
-            // put audio hardware into standby after short delay
-            if (CC_UNLIKELY((!mActiveTracks.size() && systemTime() > standbyTime) ||
-                         mSuspended > 0)) {
-                if (!mStandby) {
-                    // DuplicatingThread implements standby by stopping all tracks
-                    for (size_t i = 0; i < outputTracks.size(); i++) {
-                        outputTracks[i]->stop();
-                    }
-                    mStandby = true;
-                    mBytesWritten = 0;
-                }
-
-                if (!mActiveTracks.size() && mConfigEvents.isEmpty()) {
-                    // we're about to wait, flush the binder command buffer
-                    IPCThreadState::self()->flushCommands();
-                    outputTracks.clear();
-
-                    if (exitPending()) break;
-
-                    releaseWakeLock_l();
-                    // wait until we have something to do...
-                    ALOGV("Thread %p type %d TID %d going to sleep", this, mType, gettid());
-                    mWaitWorkCV.wait(mLock);
-                    ALOGV("Thread %p type %d TID %d waking up", this, mType, gettid());
-                    acquireWakeLock_l();
-
-                    // MixerThread has "mPrevMixerStatus = MIXER_IDLE"
-                    checkSilentMode_l();
-
-                    standbyTime = systemTime() + mStandbyTimeInNsecs;
-                    sleepTime = idleSleepTime;
-                    // MixerThread has sleepTimeShift
-                    continue;
-                }
-            }
-
-            mixerStatus = prepareTracks_l(&tracksToRemove);
-
-            // prevent any changes in effect chain list and in each effect chain
-            // during mixing and effect process as the audio buffers could be deleted
-            // or modified if an effect is created or deleted
-            lockEffectChains_l(effectChains);
-        }
-
-        // Duplicating Thread is completely different here
-        if (CC_LIKELY(mixerStatus == MIXER_TRACKS_READY)) {
-            // mix buffers...
-            if (outputsReady(outputTracks)) {
-                mAudioMixer->process(AudioBufferProvider::kInvalidPTS);
-            } else {
-                memset(mMixBuffer, 0, mixBufferSize);
-            }
-            sleepTime = 0;
-            writeFrames = mFrameCount;
-        } else {
-            if (sleepTime == 0) {
-                if (mixerStatus == MIXER_TRACKS_ENABLED) {
-                    sleepTime = activeSleepTime;
-                } else {
-                    sleepTime = idleSleepTime;
-                }
-            } else if (mBytesWritten != 0) {
-                // flush remaining overflow buffers in output tracks
-                for (size_t i = 0; i < outputTracks.size(); i++) {
-                    if (outputTracks[i]->isActive()) {
-                        sleepTime = 0;
-                        writeFrames = 0;
-                        memset(mMixBuffer, 0, mixBufferSize);
-                        break;
-                    }
-                }
-            }
-        }
-
-        if (mSuspended > 0) {
-            sleepTime = suspendSleepTimeUs();
-        }
-
-        // only process effects if we're going to write
-        if (sleepTime == 0) {
-            for (size_t i = 0; i < effectChains.size(); i ++) {
-                effectChains[i]->process_l();
-            }
-        }
-
-        // enable changes in effect chain
-        unlockEffectChains(effectChains);
-
-        // sleepTime == 0 means we must write to audio hardware
-        if (sleepTime == 0) {
-            standbyTime = systemTime() + mStandbyTimeInNsecs;
-            for (size_t i = 0; i < outputTracks.size(); i++) {
-                outputTracks[i]->write(mMixBuffer, writeFrames);
-            }
-            mStandby = false;
-            mBytesWritten += mixBufferSize;
-
-            // MixerThread has write blocked detection here
-
-        } else {
-            usleep(sleepTime);
-        }
-
-        // finally let go of removed track(s), without the lock held
-        // since we can't guarantee the destructors won't acquire that
-        // same lock.
-        tracksToRemove.clear();
-        outputTracks.clear();
-
-        // Effect chains will be actually deleted here if they were removed from
-        // mEffectChains list during mixing or effects processing
-        effectChains.clear();
-
-        // FIXME Note that the above .clear() is no longer necessary since effectChains
-        // is now local to this block, but will keep it for now (at least until merge done).
+    // mix buffers...
+    if (outputsReady(outputTracks)) {
+        mAudioMixer->process(AudioBufferProvider::kInvalidPTS);
+    } else {
+        memset(mMixBuffer, 0, mixBufferSize);
     }
+    sleepTime = 0;
+    writeFrames = mFrameCount;
+}
 
-    // MixerThread and DirectOutpuThread have standby here,
-    // but for DuplicatingThread this is handled by the outputTracks
+void AudioFlinger::DuplicatingThread::threadLoop_sleepTime()
+{
+    if (sleepTime == 0) {
+        if (mMixerStatus == MIXER_TRACKS_ENABLED) {
+            sleepTime = activeSleepTime;
+        } else {
+            sleepTime = idleSleepTime;
+        }
+    } else if (mBytesWritten != 0) {
+        // flush remaining overflow buffers in output tracks
+        for (size_t i = 0; i < outputTracks.size(); i++) {
+            if (outputTracks[i]->isActive()) {
+                sleepTime = 0;
+                writeFrames = 0;
+                memset(mMixBuffer, 0, mixBufferSize);
+                break;
+            }
+        }
+    }
+}
 
-    releaseWakeLock();
+void AudioFlinger::DuplicatingThread::threadLoop_write()
+{
+    standbyTime = systemTime() + mStandbyTimeInNsecs;
+    for (size_t i = 0; i < outputTracks.size(); i++) {
+        outputTracks[i]->write(mMixBuffer, writeFrames);
+    }
+    mBytesWritten += mixBufferSize;
+}
 
-    ALOGV("Thread %p type %d exiting", this, mType);
-    return false;
+void AudioFlinger::DuplicatingThread::threadLoop_standby()
+{
+    // DuplicatingThread implements standby by stopping all tracks
+    for (size_t i = 0; i < outputTracks.size(); i++) {
+        outputTracks[i]->stop();
+    }
+}
+
+void AudioFlinger::DuplicatingThread::saveOutputTracks()
+{
+    outputTracks = mOutputTracks;
+}
+
+void AudioFlinger::DuplicatingThread::clearOutputTracks()
+{
+    outputTracks.clear();
 }
 
 void AudioFlinger::DuplicatingThread::addOutputTrack(MixerThread *thread)
@@ -3338,7 +3167,7 @@
         thread->setStreamVolume(AUDIO_STREAM_CNT, 1.0f);
         mOutputTracks.add(outputTrack);
         ALOGV("addOutputTrack() track %p, on thread %p", outputTrack, thread);
-        updateWaitTime();
+        updateWaitTime_l();
     }
 }
 
@@ -3349,14 +3178,15 @@
         if (mOutputTracks[i]->thread() == thread) {
             mOutputTracks[i]->destroy();
             mOutputTracks.removeAt(i);
-            updateWaitTime();
+            updateWaitTime_l();
             return;
         }
     }
     ALOGV("removeOutputTrack(): unkonwn thread: %p", thread);
 }
 
-void AudioFlinger::DuplicatingThread::updateWaitTime()
+// caller must hold mLock
+void AudioFlinger::DuplicatingThread::updateWaitTime_l()
 {
     mWaitTimeMs = UINT_MAX;
     for (size_t i = 0; i < mOutputTracks.size(); i++) {
@@ -5836,9 +5666,9 @@
     size_t num = mAudioSessionRefs.size();
     for (size_t i = 0; i< num; i++) {
         AudioSessionRef *ref = mAudioSessionRefs.editItemAt(i);
-        if (ref->sessionid == audioSession && ref->pid == caller) {
-            ref->cnt++;
-            ALOGV(" incremented refcount to %d", ref->cnt);
+        if (ref->mSessionid == audioSession && ref->mPid == caller) {
+            ref->mCnt++;
+            ALOGV(" incremented refcount to %d", ref->mCnt);
             return;
         }
     }
@@ -5854,10 +5684,10 @@
     size_t num = mAudioSessionRefs.size();
     for (size_t i = 0; i< num; i++) {
         AudioSessionRef *ref = mAudioSessionRefs.itemAt(i);
-        if (ref->sessionid == audioSession && ref->pid == caller) {
-            ref->cnt--;
-            ALOGV(" decremented refcount to %d", ref->cnt);
-            if (ref->cnt == 0) {
+        if (ref->mSessionid == audioSession && ref->mPid == caller) {
+            ref->mCnt--;
+            ALOGV(" decremented refcount to %d", ref->mCnt);
+            if (ref->mCnt == 0) {
                 mAudioSessionRefs.removeAt(i);
                 delete ref;
                 purgeStaleEffects_l();
@@ -5902,9 +5732,9 @@
         bool found = false;
         for (size_t k = 0; k < numsessionrefs; k++) {
             AudioSessionRef *ref = mAudioSessionRefs.itemAt(k);
-            if (ref->sessionid == sessionid) {
+            if (ref->mSessionid == sessionid) {
                 ALOGV(" session %d still exists for %d with %d refs",
-                     sessionid, ref->pid, ref->cnt);
+                     sessionid, ref->mPid, ref->mCnt);
                 found = true;
                 break;
             }
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index bdaf97c..2e259c0 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -207,7 +207,9 @@
     // call in any IAudioFlinger method that accesses mPrimaryHardwareDev
     status_t                initCheck() const { return mPrimaryHardwareDev == NULL ? NO_INIT : NO_ERROR; }
 
+    // RefBase
     virtual     void        onFirstRef();
+
     audio_hw_device_t*      findSuitableHwDev_l(uint32_t devices);
     void                    purgeStaleEffects_l();
 
@@ -532,7 +534,10 @@
         friend class RecordTrack;
 
                     const type_t            mType;
+
+                    // Used by parameters, config events, addTrack_l, exit
                     Condition               mWaitWorkCV;
+
                     const sp<AudioFlinger>  mAudioFlinger;
                     uint32_t                mSampleRate;
                     size_t                  mFrameCount;
@@ -540,9 +545,30 @@
                     uint16_t                mChannelCount;
                     size_t                  mFrameSize;
                     audio_format_t          mFormat;
+
+                    // Parameter sequence by client: binder thread calling setParameters():
+                    //  1. Lock mLock
+                    //  2. Append to mNewParameters
+                    //  3. mWaitWorkCV.signal
+                    //  4. mParamCond.waitRelative with timeout
+                    //  5. read mParamStatus
+                    //  6. mWaitWorkCV.signal
+                    //  7. Unlock
+                    //
+                    // Parameter sequence by server: threadLoop calling checkForNewParameters_l():
+                    // 1. Lock mLock
+                    // 2. If there is an entry in mNewParameters proceed ...
+                    // 2. Read first entry in mNewParameters
+                    // 3. Process
+                    // 4. Remove first entry from mNewParameters
+                    // 5. Set mParamStatus
+                    // 6. mParamCond.signal
+                    // 7. mWaitWorkCV.wait with timeout (this is to avoid overwriting mParamStatus)
+                    // 8. Unlock
                     Condition               mParamCond;
                     Vector<String8>         mNewParameters;
                     status_t                mParamStatus;
+
                     Vector<ConfigEvent>     mConfigEvents;
                     bool                    mStandby;
                     const audio_io_handle_t mId;
@@ -793,8 +819,32 @@
 
         // Thread virtuals
         virtual     status_t    readyToRun();
+        virtual     bool        threadLoop();
+
+        // RefBase
         virtual     void        onFirstRef();
 
+protected:
+        // Code snippets that were lifted up out of threadLoop()
+        virtual     void        threadLoop_mix() = 0;
+        virtual     void        threadLoop_sleepTime() = 0;
+        virtual     void        threadLoop_write();
+        virtual     void        threadLoop_standby();
+
+        // Non-trivial for DUPLICATING only
+        virtual     void        updateWaitTime_l() { }
+
+        // Non-trivial for DIRECT only
+        virtual     void        applyVolume() { }
+
+                    // prepareTracks_l reads and writes mActiveTracks, and also returns the
+                    // pending set of tracks to remove via Vector 'tracksToRemove'.  The caller is
+                    // responsible for clearing or destroying this Vector later on, when it
+                    // is safe to do so. That will drop the final ref count and destroy the tracks.
+        virtual     mixer_state prepareTracks_l(Vector< sp<Track> > *tracksToRemove) = 0;
+
+public:
+
         virtual     status_t    initCheck() const { return (mOutput == NULL) ? NO_INIT : NO_ERROR; }
 
         virtual     uint32_t    latency() const;
@@ -866,6 +916,10 @@
         // Code snippets that are temporarily lifted up out of threadLoop() until the merge
                     void        checkSilentMode_l();
 
+        // Non-trivial for DUPLICATING only
+        virtual     void        saveOutputTracks() { }
+        virtual     void        clearOutputTracks() { }
+
     private:
 
         friend class AudioFlinger;
@@ -897,6 +951,26 @@
         int                             mNumWrites;
         int                             mNumDelayedWrites;
         bool                            mInWrite;
+
+        // FIXME rename these former local variables of threadLoop to standard "m" names
+        nsecs_t                         standbyTime;
+        size_t                          mixBufferSize;
+        uint32_t                        activeSleepTime;
+        uint32_t                        idleSleepTime;
+        uint32_t                        sleepTime;
+
+        // mixer status returned by prepareTracks_l()
+        mixer_state                     mMixerStatus;       // current cycle
+        mixer_state                     mPrevMixerStatus;   // previous cycle
+
+        // FIXME move these declarations into the specific sub-class that needs them
+        // MIXER only
+        bool                            longStandbyExit;
+        uint32_t                        sleepTimeShift;
+        // DIRECT only
+        nsecs_t                         standbyDelay;
+        // DUPLICATING only
+        uint32_t                        writeFrames;
     };
 
     class MixerThread : public PlaybackThread {
@@ -909,25 +983,23 @@
         virtual             ~MixerThread();
 
         // Thread virtuals
-        virtual     bool        threadLoop();
 
                     void        invalidateTracks(audio_stream_type_t streamType);
         virtual     bool        checkForNewParameters_l();
         virtual     status_t    dumpInternals(int fd, const Vector<String16>& args);
 
     protected:
-                    // prepareTracks_l reads and writes mActiveTracks, and also returns the
-                    // pending set of tracks to remove via Vector 'tracksToRemove'.  The caller is
-                    // responsible for clearing or destroying this Vector later on, when it
-                    // is safe to do so. That will drop the final ref count and destroy the tracks.
-                    mixer_state prepareTracks_l(Vector< sp<Track> > *tracksToRemove);
+        virtual     mixer_state prepareTracks_l(Vector< sp<Track> > *tracksToRemove);
         virtual     int         getTrackName_l();
         virtual     void        deleteTrackName_l(int name);
         virtual     uint32_t    idleSleepTimeUs();
         virtual     uint32_t    suspendSleepTimeUs();
 
+        // threadLoop snippets
+        virtual     void        threadLoop_mix();
+        virtual     void        threadLoop_sleepTime();
+
                     AudioMixer* mAudioMixer;
-                    mixer_state mPrevMixerStatus; // previous status returned by prepareTracks_l()
     };
 
     class DirectOutputThread : public PlaybackThread {
@@ -938,7 +1010,6 @@
         virtual                 ~DirectOutputThread();
 
         // Thread virtuals
-        virtual     bool        threadLoop();
 
         virtual     bool        checkForNewParameters_l();
 
@@ -949,8 +1020,10 @@
         virtual     uint32_t    idleSleepTimeUs();
         virtual     uint32_t    suspendSleepTimeUs();
 
-    private:
-        void applyVolume(uint16_t leftVol, uint16_t rightVol, bool ramp);
+        // threadLoop snippets
+        virtual     mixer_state prepareTracks_l(Vector< sp<Track> > *tracksToRemove);
+        virtual     void        threadLoop_mix();
+        virtual     void        threadLoop_sleepTime();
 
         // volumes last sent to audio HAL with stream->set_volume()
         // FIXME use standard representation and names
@@ -958,6 +1031,18 @@
         float mRightVolFloat;
         uint16_t mLeftVolShort;
         uint16_t mRightVolShort;
+
+        // FIXME rename these former local variables of threadLoop to standard names
+        // next 3 were local to the while !exitingPending loop
+        bool rampVolume;
+        uint16_t leftVol;
+        uint16_t rightVol;
+
+private:
+                    void        applyVolume();  // FIXME inline into threadLoop_mix()
+
+        // prepareTracks_l() tells threadLoop_mix() the name of the single active track
+        sp<Track>               mActiveTrack;
     };
 
     class DuplicatingThread : public MixerThread {
@@ -967,7 +1052,6 @@
         virtual                 ~DuplicatingThread();
 
         // Thread virtuals
-        virtual     bool        threadLoop();
                     void        addOutputTrack(MixerThread* thread);
                     void        removeOutputTrack(MixerThread* thread);
                     uint32_t    waitTimeMs() { return mWaitTimeMs; }
@@ -976,10 +1060,22 @@
 
     private:
                     bool        outputsReady(const SortedVector<sp<OutputTrack> > &outputTracks);
-                    void        updateWaitTime();
+    protected:
+        // threadLoop snippets
+        virtual     void        threadLoop_mix();
+        virtual     void        threadLoop_sleepTime();
+        virtual     void        threadLoop_write();
+        virtual     void        threadLoop_standby();
 
-        SortedVector < sp<OutputTrack> >  mOutputTracks;
+        // called from threadLoop, addOutputTrack, removeOutputTrack
+        virtual     void        updateWaitTime_l();
+        virtual     void        saveOutputTracks();
+        virtual     void        clearOutputTracks();
+    private:
+
                     uint32_t    mWaitTimeMs;
+        SortedVector < sp<OutputTrack> >  outputTracks;
+        SortedVector < sp<OutputTrack> >  mOutputTracks;
     };
 
               PlaybackThread *checkPlaybackThread_l(audio_io_handle_t output) const;
@@ -991,7 +1087,7 @@
               // no range check, doesn't check per-thread stream volume, AudioFlinger::mLock held
               float streamVolume_l(audio_stream_type_t stream) const
                                 { return mStreamTypes[stream].volume; }
-              void audioConfigChanged_l(int event, audio_io_handle_t ioHandle, void *param2);
+              void audioConfigChanged_l(int event, audio_io_handle_t ioHandle, const void *param2);
 
               // allocate an audio_io_handle_t, session ID, or effect ID
               uint32_t nextUniqueId();
@@ -1086,8 +1182,11 @@
                         uint32_t device);
                 virtual     ~RecordThread();
 
+        // Thread
         virtual bool        threadLoop();
         virtual status_t    readyToRun();
+
+        // RefBase
         virtual void        onFirstRef();
 
         virtual status_t    initCheck() const { return (mInput == NULL) ? NO_INIT : NO_ERROR; }
@@ -1497,12 +1596,11 @@
 
     // for mAudioSessionRefs only
     struct AudioSessionRef {
-        // FIXME rename parameter names when fields get "m" prefix
-        AudioSessionRef(int sessionid_, pid_t pid_) :
-            sessionid(sessionid_), pid(pid_), cnt(1) {}
-        const int sessionid;
-        const pid_t pid;
-        int cnt;
+        AudioSessionRef(int sessionid, pid_t pid) :
+            mSessionid(sessionid), mPid(pid), mCnt(1) {}
+        const int   mSessionid;
+        const pid_t mPid;
+        int         mCnt;
     };
 
     friend class RecordThread;
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java
index eab60a7..352decf 100644
--- a/services/java/com/android/server/ConnectivityService.java
+++ b/services/java/com/android/server/ConnectivityService.java
@@ -2179,8 +2179,9 @@
             String dnsString = dns.getHostAddress();
             if (changed || !dnsString.equals(SystemProperties.get("net.dns" + j + "." + pid))) {
                 changed = true;
-                SystemProperties.set("net.dns" + j++ + "." + pid, dns.getHostAddress());
+                SystemProperties.set("net.dns" + j + "." + pid, dns.getHostAddress());
             }
+            j++;
         }
         return changed;
     }
diff --git a/services/java/com/android/server/DropBoxManagerService.java b/services/java/com/android/server/DropBoxManagerService.java
index d37c9ab..932cba1 100644
--- a/services/java/com/android/server/DropBoxManagerService.java
+++ b/services/java/com/android/server/DropBoxManagerService.java
@@ -28,6 +28,7 @@
 import android.os.DropBoxManager;
 import android.os.FileUtils;
 import android.os.Handler;
+import android.os.Message;
 import android.os.StatFs;
 import android.os.SystemClock;
 import android.provider.Settings;
@@ -64,6 +65,9 @@
     private static final int DEFAULT_RESERVE_PERCENT = 10;
     private static final int QUOTA_RESCAN_MILLIS = 5000;
 
+    // mHandler 'what' value.
+    private static final int MSG_SEND_BROADCAST = 1;
+
     private static final boolean PROFILE_DUMP = false;
 
     // TODO: This implementation currently uses one file per entry, which is
@@ -88,11 +92,11 @@
     private int mCachedQuotaBlocks = 0;  // Space we can use: computed from free space, etc.
     private long mCachedQuotaUptimeMillis = 0;
 
-    // Ensure that all log entries have a unique timestamp
-    private long mLastTimestamp = 0;
-
     private volatile boolean mBooted = false;
 
+    // Provide a way to perform sendBroadcast asynchronously to avoid deadlocks.
+    private final Handler mHandler;
+
     /** Receives events that might indicate a need to clean up files. */
     private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
         @Override
@@ -143,11 +147,21 @@
         mContentResolver.registerContentObserver(
             Settings.Secure.CONTENT_URI, true,
             new ContentObserver(new Handler()) {
+                @Override
                 public void onChange(boolean selfChange) {
                     mReceiver.onReceive(context, (Intent) null);
                 }
             });
 
+        mHandler = new Handler() {
+            @Override
+            public void handleMessage(Message msg) {
+                if (msg.what == MSG_SEND_BROADCAST) {
+                    mContext.sendBroadcast((Intent)msg.obj, android.Manifest.permission.READ_LOGS);
+                }
+            }
+        };
+
         // The real work gets done lazily in init() -- that way service creation always
         // succeeds, and things like disk problems cause individual method failures.
     }
@@ -157,6 +171,7 @@
         mContext.unregisterReceiver(mReceiver);
     }
 
+    @Override
     public void add(DropBoxManager.Entry entry) {
         File temp = null;
         OutputStream output = null;
@@ -227,14 +242,17 @@
             long time = createEntry(temp, tag, flags);
             temp = null;
 
-            Intent dropboxIntent = new Intent(DropBoxManager.ACTION_DROPBOX_ENTRY_ADDED);
+            final Intent dropboxIntent = new Intent(DropBoxManager.ACTION_DROPBOX_ENTRY_ADDED);
             dropboxIntent.putExtra(DropBoxManager.EXTRA_TAG, tag);
             dropboxIntent.putExtra(DropBoxManager.EXTRA_TIME, time);
             if (!mBooted) {
                 dropboxIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
             }
-            mContext.sendBroadcast(dropboxIntent, android.Manifest.permission.READ_LOGS);
-
+            // Call sendBroadcast after returning from this call to avoid deadlock. In particular
+            // the caller may be holding the WindowManagerService lock but sendBroadcast requires a
+            // lock in ActivityManagerService. ActivityManagerService has been caught holding that
+            // very lock while waiting for the WindowManagerService lock.
+            mHandler.sendMessage(mHandler.obtainMessage(MSG_SEND_BROADCAST, dropboxIntent));
         } catch (IOException e) {
             Slog.e(TAG, "Can't write: " + tag, e);
         } finally {
diff --git a/services/java/com/android/server/NativeDaemonConnector.java b/services/java/com/android/server/NativeDaemonConnector.java
index 308661f..6593a0f 100644
--- a/services/java/com/android/server/NativeDaemonConnector.java
+++ b/services/java/com/android/server/NativeDaemonConnector.java
@@ -34,8 +34,8 @@
 import java.io.OutputStream;
 import java.io.PrintWriter;
 import java.util.ArrayList;
-import java.util.concurrent.BlockingQueue;
-import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.LinkedList;
 
 /**
  * Generic connector class for interfacing with a native daemon which uses the
@@ -50,11 +50,15 @@
     private OutputStream mOutputStream;
     private LocalLog mLocalLog;
 
-    private final BlockingQueue<NativeDaemonEvent> mResponseQueue;
+    private final ResponseQueue mResponseQueue;
 
     private INativeDaemonConnectorCallbacks mCallbacks;
     private Handler mCallbackHandler;
 
+    private AtomicInteger mSequenceNumber;
+
+    private static final int DEFAULT_TIMEOUT = 1 * 60 * 1000; /* 1 minute */
+
     /** Lock held whenever communicating with native daemon. */
     private final Object mDaemonLock = new Object();
 
@@ -64,7 +68,8 @@
             int responseQueueSize, String logTag, int maxLogSize) {
         mCallbacks = callbacks;
         mSocket = socket;
-        mResponseQueue = new LinkedBlockingQueue<NativeDaemonEvent>(responseQueueSize);
+        mResponseQueue = new ResponseQueue(responseQueueSize);
+        mSequenceNumber = new AtomicInteger(0);
         TAG = logTag != null ? logTag : "NativeDaemonConnector";
         mLocalLog = new LocalLog(maxLogSize);
     }
@@ -79,7 +84,7 @@
             try {
                 listenToSocket();
             } catch (Exception e) {
-                Slog.e(TAG, "Error in NativeDaemonConnector", e);
+                loge("Error in NativeDaemonConnector: " + e);
                 SystemClock.sleep(5000);
             }
         }
@@ -90,12 +95,10 @@
         String event = (String) msg.obj;
         try {
             if (!mCallbacks.onEvent(msg.what, event, event.split(" "))) {
-                Slog.w(TAG, String.format(
-                        "Unhandled event '%s'", event));
+                log(String.format("Unhandled event '%s'", event));
             }
         } catch (Exception e) {
-            Slog.e(TAG, String.format(
-                    "Error handling '%s'", event), e);
+            loge("Error handling '" + event + "': " + e);
         }
         return true;
     }
@@ -111,7 +114,9 @@
             socket.connect(address);
 
             InputStream inputStream = socket.getInputStream();
-            mOutputStream = socket.getOutputStream();
+            synchronized (mDaemonLock) {
+                mOutputStream = socket.getOutputStream();
+            }
 
             mCallbacks.onDaemonConnected();
 
@@ -120,7 +125,10 @@
 
             while (true) {
                 int count = inputStream.read(buffer, start, BUFFER_SIZE - start);
-                if (count < 0) break;
+                if (count < 0) {
+                    loge("got " + count + " reading with start = " + start);
+                    break;
+                }
 
                 // Add our starting point to the count and reset the start.
                 count += start;
@@ -140,14 +148,10 @@
                                 mCallbackHandler.sendMessage(mCallbackHandler.obtainMessage(
                                         event.getCode(), event.getRawEvent()));
                             } else {
-                                try {
-                                    mResponseQueue.put(event);
-                                } catch (InterruptedException ex) {
-                                    Slog.e(TAG, "Failed to put response onto queue: " + ex);
-                                }
+                                mResponseQueue.add(event.getCmdNumber(), event);
                             }
                         } catch (IllegalArgumentException e) {
-                            Slog.w(TAG, "Problem parsing message: " + rawEvent, e);
+                            log("Problem parsing message: " + rawEvent + " - " + e);
                         }
 
                         start = i + 1;
@@ -169,15 +173,16 @@
                 }
             }
         } catch (IOException ex) {
-            Slog.e(TAG, "Communications error", ex);
+            loge("Communications error: " + ex);
             throw ex;
         } finally {
             synchronized (mDaemonLock) {
                 if (mOutputStream != null) {
                     try {
+                        loge("closing stream for " + mSocket);
                         mOutputStream.close();
                     } catch (IOException e) {
-                        Slog.w(TAG, "Failed closing output stream", e);
+                        loge("Failed closing output stream: " + e);
                     }
                     mOutputStream = null;
                 }
@@ -188,17 +193,17 @@
                     socket.close();
                 }
             } catch (IOException ex) {
-                Slog.w(TAG, "Failed closing socket", ex);
+                loge("Failed closing socket: " + ex);
             }
         }
     }
 
     /**
-     * Send command to daemon, escaping arguments as needed.
+     * Make command for daemon, escaping arguments as needed.
      *
-     * @return the final command issued.
+     * @return the final command.
      */
-    private String sendCommandLocked(String cmd, Object... args)
+    private StringBuilder makeCommand(String cmd, Object... args)
             throws NativeDaemonConnectorException {
         // TODO: eventually enforce that cmd doesn't contain arguments
         if (cmd.indexOf('\0') >= 0) {
@@ -216,22 +221,33 @@
             appendEscaped(builder, argString);
         }
 
-        final String unterminated = builder.toString();
-        log("SND -> {" + unterminated + "}");
+        return builder;
+    }
+
+    private int sendCommand(StringBuilder builder)
+            throws NativeDaemonConnectorException {
+
+        int sequenceNumber = mSequenceNumber.incrementAndGet();
+
+        builder.insert(0, Integer.toString(sequenceNumber) + " ");
+
+        log("SND -> {" + builder.toString() + "}");
 
         builder.append('\0');
 
-        if (mOutputStream == null) {
-            throw new NativeDaemonConnectorException("missing output stream");
-        } else {
-            try {
-                mOutputStream.write(builder.toString().getBytes(Charsets.UTF_8));
-            } catch (IOException e) {
-                throw new NativeDaemonConnectorException("problem sending command", e);
+        synchronized (mDaemonLock) {
+            if (mOutputStream == null) {
+                throw new NativeDaemonConnectorException("missing output stream");
+            } else {
+                try {
+                    mOutputStream.write(builder.toString().getBytes(Charsets.UTF_8));
+                } catch (IOException e) {
+                    throw new NativeDaemonConnectorException("problem sending command", e);
+                }
             }
         }
 
-        return unterminated;
+        return sequenceNumber;
     }
 
     /**
@@ -292,39 +308,42 @@
      */
     public NativeDaemonEvent[] executeForList(String cmd, Object... args)
             throws NativeDaemonConnectorException {
-        synchronized (mDaemonLock) {
-            return executeLocked(cmd, args);
-        }
+            return execute(DEFAULT_TIMEOUT, cmd, args);
     }
 
-    private NativeDaemonEvent[] executeLocked(String cmd, Object... args)
+    /**
+     * Issue the given command to the native daemon and return any
+     * {@linke NativeDaemonEvent@isClassContinue()} responses, including the
+     * final terminal response.  Note that the timeout does not count time in
+     * deep sleep.
+     *
+     * @throws NativeDaemonConnectorException when problem communicating with
+     *             native daemon, or if the response matches
+     *             {@link NativeDaemonEvent#isClassClientError()} or
+     *             {@link NativeDaemonEvent#isClassServerError()}.
+     */
+    public NativeDaemonEvent[] execute(int timeout, String cmd, Object... args)
             throws NativeDaemonConnectorException {
         final ArrayList<NativeDaemonEvent> events = Lists.newArrayList();
-
-        while (mResponseQueue.size() > 0) {
-            try {
-                log("ignoring {" + mResponseQueue.take() + "}");
-            } catch (Exception e) {}
-        }
-
-        final String sentCommand = sendCommandLocked(cmd, args);
+        final StringBuilder sentCommand = makeCommand(cmd, args);
+        final int cmdNumber = sendCommand(sentCommand);
 
         NativeDaemonEvent event = null;
+        cmd = sentCommand.toString();
         do {
-            try {
-                event = mResponseQueue.take();
-            } catch (InterruptedException e) {
-                Slog.w(TAG, "interrupted waiting for event line");
-                continue;
+            event = mResponseQueue.remove(cmdNumber, timeout, cmd);
+            if (event == null) {
+                loge("timed-out waiting for response to " + cmdNumber + " " + cmd);
+                throw new NativeDaemonFailureException(cmd, event);
             }
             events.add(event);
         } while (event.isClassContinue());
 
         if (event.isClassClientError()) {
-            throw new NativeDaemonArgumentException(sentCommand, event);
+            throw new NativeDaemonArgumentException(cmd, event);
         }
         if (event.isClassServerError()) {
-            throw new NativeDaemonFailureException(sentCommand, event);
+            throw new NativeDaemonFailureException(cmd, event);
         }
 
         return events.toArray(new NativeDaemonEvent[events.size()]);
@@ -448,10 +467,120 @@
 
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         mLocalLog.dump(fd, pw, args);
+        pw.println();
+        mResponseQueue.dump(fd, pw, args);
     }
 
     private void log(String logstring) {
         if (LOGD) Slog.d(TAG, logstring);
         mLocalLog.log(logstring);
     }
+
+    private void loge(String logstring) {
+        Slog.e(TAG, logstring);
+        mLocalLog.log(logstring);
+    }
+
+    private static class ResponseQueue {
+
+        private static class Response {
+            public int cmdNum;
+            public LinkedList<NativeDaemonEvent> responses = new LinkedList<NativeDaemonEvent>();
+            public String request;
+            public Response(int c, String r) {cmdNum = c; request = r;}
+        }
+
+        private final LinkedList<Response> mResponses;
+        private int mMaxCount;
+
+        ResponseQueue(int maxCount) {
+            mResponses = new LinkedList<Response>();
+            mMaxCount = maxCount;
+        }
+
+        public void add(int cmdNum, NativeDaemonEvent response) {
+            Response found = null;
+            synchronized (mResponses) {
+                for (Response r : mResponses) {
+                    if (r.cmdNum == cmdNum) {
+                        found = r;
+                        break;
+                    }
+                }
+                if (found == null) {
+                    // didn't find it - make sure our queue isn't too big before adding
+                    // another..
+                    while (mResponses.size() >= mMaxCount) {
+                        Slog.e("NativeDaemonConnector.ResponseQueue",
+                                "more buffered than allowed: " + mResponses.size() +
+                                " >= " + mMaxCount);
+                        // let any waiter timeout waiting for this
+                        Response r = mResponses.remove();
+                        Slog.e("NativeDaemonConnector.ResponseQueue",
+                                "Removing request: " + r.request + " (" + r.cmdNum + ")");
+                    }
+                    found = new Response(cmdNum, null);
+                    mResponses.add(found);
+                }
+                found.responses.add(response);
+            }
+            synchronized (found) {
+                found.notify();
+            }
+        }
+
+        // note that the timeout does not count time in deep sleep.  If you don't want
+        // the device to sleep, hold a wakelock
+        public NativeDaemonEvent remove(int cmdNum, int timeoutMs, String origCmd) {
+            long endTime = SystemClock.uptimeMillis() + timeoutMs;
+            long nowTime;
+            Response found = null;
+            while (true) {
+                synchronized (mResponses) {
+                    for (Response response : mResponses) {
+                        if (response.cmdNum == cmdNum) {
+                            found = response;
+                            // how many response fragments are left
+                            switch (response.responses.size()) {
+                            case 0:  // haven't got any - must wait
+                                break;
+                            case 1:  // last one - remove this from the master list
+                                mResponses.remove(response); // fall through
+                            default: // take one and move on
+                                response.request = origCmd;
+                                return response.responses.remove();
+                            }
+                        }
+                    }
+                    nowTime = SystemClock.uptimeMillis();
+                    if (endTime <= nowTime) {
+                        Slog.e("NativeDaemonConnector.ResponseQueue",
+                                "Timeout waiting for response");
+                        return null;
+                    }
+                    /* pre-allocate so we have something unique to wait on */
+                    if (found == null) {
+                        found = new Response(cmdNum, origCmd);
+                        mResponses.add(found);
+                    }
+                }
+                try {
+                    synchronized (found) {
+                        found.wait(endTime - nowTime);
+                    }
+                } catch (InterruptedException e) {
+                    // loop around to check if we're done or if it's time to stop waiting
+                }
+            }
+        }
+
+        public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+            pw.println("Pending requests:");
+            synchronized (mResponses) {
+                for (Response response : mResponses) {
+                    pw.println("  Cmd " + response.cmdNum + " - " + response.request);
+                }
+            }
+        }
+    }
 }
diff --git a/services/java/com/android/server/NativeDaemonEvent.java b/services/java/com/android/server/NativeDaemonEvent.java
index 62084c0..d5e9f66 100644
--- a/services/java/com/android/server/NativeDaemonEvent.java
+++ b/services/java/com/android/server/NativeDaemonEvent.java
@@ -28,16 +28,22 @@
     // TODO: keep class ranges in sync with ResponseCode.h
     // TODO: swap client and server error ranges to roughly mirror HTTP spec
 
+    private final int mCmdNumber;
     private final int mCode;
     private final String mMessage;
     private final String mRawEvent;
 
-    private NativeDaemonEvent(int code, String message, String rawEvent) {
+    private NativeDaemonEvent(int cmdNumber, int code, String message, String rawEvent) {
+        mCmdNumber = cmdNumber;
         mCode = code;
         mMessage = message;
         mRawEvent = rawEvent;
     }
 
+    public int getCmdNumber() {
+        return mCmdNumber;
+    }
+
     public int getCode() {
         return mCode;
     }
@@ -89,7 +95,11 @@
      * Test if event represents an unsolicited event from native daemon.
      */
     public boolean isClassUnsolicited() {
-        return mCode >= 600 && mCode < 700;
+        return isClassUnsolicited(mCode);
+    }
+
+    private static boolean isClassUnsolicited(int code) {
+        return code >= 600 && code < 700;
     }
 
     /**
@@ -110,20 +120,37 @@
      *             from native side.
      */
     public static NativeDaemonEvent parseRawEvent(String rawEvent) {
-        final int splitIndex = rawEvent.indexOf(' ');
-        if (splitIndex == -1) {
-            throw new IllegalArgumentException("unable to find ' ' separator");
+        final String[] parsed = rawEvent.split(" ");
+        if (parsed.length < 2) {
+            throw new IllegalArgumentException("Insufficient arguments");
         }
 
+        int skiplength = 0;
+
         final int code;
         try {
-            code = Integer.parseInt(rawEvent.substring(0, splitIndex));
+            code = Integer.parseInt(parsed[0]);
+            skiplength = parsed[0].length() + 1;
         } catch (NumberFormatException e) {
             throw new IllegalArgumentException("problem parsing code", e);
         }
 
-        final String message = rawEvent.substring(splitIndex + 1);
-        return new NativeDaemonEvent(code, message, rawEvent);
+        int cmdNumber = -1;
+        if (isClassUnsolicited(code) == false) {
+            if (parsed.length < 3) {
+                throw new IllegalArgumentException("Insufficient arguemnts");
+            }
+            try {
+                cmdNumber = Integer.parseInt(parsed[1]);
+                skiplength += parsed[1].length() + 1;
+            } catch (NumberFormatException e) {
+                throw new IllegalArgumentException("problem parsing cmdNumber", e);
+            }
+        }
+
+        final String message = rawEvent.substring(skiplength);
+
+        return new NativeDaemonEvent(cmdNumber, code, message, rawEvent);
     }
 
     /**
diff --git a/services/java/com/android/server/NetworkManagementService.java b/services/java/com/android/server/NetworkManagementService.java
index 7bb7938..720b5fe 100644
--- a/services/java/com/android/server/NetworkManagementService.java
+++ b/services/java/com/android/server/NetworkManagementService.java
@@ -117,6 +117,7 @@
         public static final int InterfaceTxThrottleResult = 219;
         public static final int QuotaCounterResult        = 220;
         public static final int TetheringStatsResult      = 221;
+        public static final int DnsProxyQueryResult       = 222;
 
         public static final int InterfaceChange           = 600;
         public static final int BandwidthControl          = 601;
diff --git a/services/java/com/android/server/PowerManagerService.java b/services/java/com/android/server/PowerManagerService.java
index c8f49ee..63418db 100644
--- a/services/java/com/android/server/PowerManagerService.java
+++ b/services/java/com/android/server/PowerManagerService.java
@@ -2234,14 +2234,18 @@
                 }
 
                 if (target != currentValue) {
+                    final boolean doScreenAnim = (mask & (SCREEN_BRIGHT_BIT | SCREEN_ON_BIT)) != 0;
                     final boolean turningOff = endValue == Power.BRIGHTNESS_OFF;
-                    if (turningOff) {
+                    if (turningOff && doScreenAnim) {
                         // Cancel all pending animations since we're turning off
                         mScreenBrightnessHandler.removeCallbacksAndMessages(null);
                         screenOffFinishedAnimatingLocked(mScreenOffReason);
                         duration = 200; // TODO: how long should this be?
                     }
-                    animateInternal(mask, turningOff, 0);
+                    if (doScreenAnim) {
+                        animateInternal(mask, turningOff, 0);
+                    }
+                    // TODO: Handle keyboard light animation when we have devices that support it
                 }
             }
         }
diff --git a/services/java/com/android/server/WifiService.java b/services/java/com/android/server/WifiService.java
index 6b4c895..8363e6e 100644
--- a/services/java/com/android/server/WifiService.java
+++ b/services/java/com/android/server/WifiService.java
@@ -297,6 +297,10 @@
                     mWifiStateMachine.sendMessage(Message.obtain(msg));
                     break;
                 }
+                case WifiManager.CANCEL_WPS: {
+                    mWifiStateMachine.sendMessage(Message.obtain(msg));
+                    break;
+                }
                 case WifiManager.DISABLE_NETWORK: {
                     mWifiStateMachine.sendMessage(Message.obtain(msg));
                     break;
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 3ac446c..4ea2f04 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -7952,6 +7952,22 @@
         }
     }
 
+    private void fillInProcMemInfo(ProcessRecord app,
+            ActivityManager.RunningAppProcessInfo outInfo) {
+        outInfo.pid = app.pid;
+        outInfo.uid = app.info.uid;
+        if (mHeavyWeightProcess == app) {
+            outInfo.flags |= ActivityManager.RunningAppProcessInfo.FLAG_CANT_SAVE_STATE;
+        }
+        if (app.persistent) {
+            outInfo.flags |= ActivityManager.RunningAppProcessInfo.FLAG_PERSISTENT;
+        }
+        outInfo.lastTrimLevel = app.trimMemoryLevel;
+        int adj = app.curAdj;
+        outInfo.importance = oomAdjToImportance(adj, outInfo);
+        outInfo.importanceReasonCode = app.adjTypeCode;
+    }
+
     public List<ActivityManager.RunningAppProcessInfo> getRunningAppProcesses() {
         enforceNotIsolatedCaller("getRunningAppProcesses");
         // Lazy instantiation of list
@@ -7965,16 +7981,7 @@
                     ActivityManager.RunningAppProcessInfo currApp = 
                         new ActivityManager.RunningAppProcessInfo(app.processName,
                                 app.pid, app.getPackageList());
-                    currApp.uid = app.info.uid;
-                    if (mHeavyWeightProcess == app) {
-                        currApp.flags |= ActivityManager.RunningAppProcessInfo.FLAG_CANT_SAVE_STATE;
-                    }
-                    if (app.persistent) {
-                        currApp.flags |= ActivityManager.RunningAppProcessInfo.FLAG_PERSISTENT;
-                    }
-                    int adj = app.curAdj;
-                    currApp.importance = oomAdjToImportance(adj, currApp);
-                    currApp.importanceReasonCode = app.adjTypeCode;
+                    fillInProcMemInfo(app, currApp);
                     if (app.adjSource instanceof ProcessRecord) {
                         currApp.importanceReasonPid = ((ProcessRecord)app.adjSource).pid;
                         currApp.importanceReasonImportance = oomAdjToImportance(
@@ -8026,6 +8033,18 @@
     }
 
     @Override
+    public void getMyMemoryState(ActivityManager.RunningAppProcessInfo outInfo) {
+        enforceNotIsolatedCaller("getMyMemoryState");
+        synchronized (this) {
+            ProcessRecord proc;
+            synchronized (mPidsSelfLocked) {
+                proc = mPidsSelfLocked.get(Binder.getCallingPid());
+            }
+            fillInProcMemInfo(proc, outInfo);
+        }
+    }
+
+    @Override
     protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         if (checkCallingPermission(android.Manifest.permission.DUMP)
                 != PackageManager.PERMISSION_GRANTED) {
@@ -8479,8 +8498,8 @@
                     pw.print("    Process "); pw.print(pname);
                             pw.print(" uid "); pw.print(puid);
                             pw.print(": last crashed ");
-                            pw.print((now-uids.valueAt(i)));
-                            pw.println(" ms ago");
+                            TimeUtils.formatDuration(now-uids.valueAt(i), pw);
+                            pw.println(" ago");
                 }
             }
         }
@@ -13982,6 +14001,14 @@
             if (mPreviousProcess != null) minFactor++;
             if (factor < minFactor) factor = minFactor;
             step = 0;
+            int fgTrimLevel;
+            if (numHidden <= (ProcessList.MAX_HIDDEN_APPS/5)) {
+                fgTrimLevel = ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL;
+            } else if (numHidden <= (ProcessList.MAX_HIDDEN_APPS/3)) {
+                fgTrimLevel = ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW;
+            } else {
+                fgTrimLevel = ComponentCallbacks2.TRIM_MEMORY_RUNNING_MODERATE;
+            }
             int curLevel = ComponentCallbacks2.TRIM_MEMORY_COMPLETE;
             for (i=0; i<N; i++) {
                 ProcessRecord app = mLruProcesses.get(i);
@@ -14008,6 +14035,7 @@
                     app.trimMemoryLevel = curLevel;
                     step++;
                     if (step >= factor) {
+                        step = 0;
                         switch (curLevel) {
                             case ComponentCallbacks2.TRIM_MEMORY_COMPLETE:
                                 curLevel = ComponentCallbacks2.TRIM_MEMORY_MODERATE;
@@ -14027,20 +14055,28 @@
                         }
                     }
                     app.trimMemoryLevel = ComponentCallbacks2.TRIM_MEMORY_BACKGROUND;
-                } else if ((app.curAdj > ProcessList.VISIBLE_APP_ADJ || app.systemNoUi)
-                        && app.pendingUiClean) {
-                    if (app.trimMemoryLevel < ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN
-                            && app.thread != null) {
+                } else {
+                    if ((app.curAdj > ProcessList.VISIBLE_APP_ADJ || app.systemNoUi)
+                            && app.pendingUiClean) {
+                        // If this application is now in the background and it
+                        // had done UI, then give it the special trim level to
+                        // have it free UI resources.
+                        final int level = ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN;
+                        if (app.trimMemoryLevel < level && app.thread != null) {
+                            try {
+                                app.thread.scheduleTrimMemory(level);
+                            } catch (RemoteException e) {
+                            }
+                        }
+                        app.pendingUiClean = false;
+                    }
+                    if (app.trimMemoryLevel < fgTrimLevel && app.thread != null) {
                         try {
-                            app.thread.scheduleTrimMemory(
-                                    ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN);
+                            app.thread.scheduleTrimMemory(fgTrimLevel);
                         } catch (RemoteException e) {
                         }
                     }
-                    app.trimMemoryLevel = ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN;
-                    app.pendingUiClean = false;
-                } else {
-                    app.trimMemoryLevel = 0;
+                    app.trimMemoryLevel = fgTrimLevel;
                 }
             }
         } else {
@@ -14057,11 +14093,9 @@
                         } catch (RemoteException e) {
                         }
                     }
-                    app.trimMemoryLevel = ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN;
                     app.pendingUiClean = false;
-                } else {
-                    app.trimMemoryLevel = 0;
                 }
+                app.trimMemoryLevel = 0;
             }
         }
 
diff --git a/services/java/com/android/server/net/NetworkStatsService.java b/services/java/com/android/server/net/NetworkStatsService.java
index 13c0640..fd8d411 100644
--- a/services/java/com/android/server/net/NetworkStatsService.java
+++ b/services/java/com/android/server/net/NetworkStatsService.java
@@ -212,6 +212,8 @@
     private final HandlerThread mHandlerThread;
     private final Handler mHandler;
 
+    private boolean mSystemReady;
+
     public NetworkStatsService(
             Context context, INetworkManagementService networkManager, IAlarmManager alarmManager) {
         this(context, networkManager, alarmManager, NtpTrustedTime.getInstance(context),
@@ -250,6 +252,8 @@
     }
 
     public void systemReady() {
+        mSystemReady = true;
+
         if (!isBandwidthControlEnabled()) {
             Slog.w(TAG, "bandwidth controls disabled, unable to track stats");
             return;
@@ -336,6 +340,8 @@
         mUidTagRecorder = null;
 
         mDevStatsCached = null;
+
+        mSystemReady = false;
     }
 
     private void maybeUpgradeLegacyStatsLocked() {
@@ -649,6 +655,7 @@
      * {@link NetworkIdentitySet}.
      */
     private void updateIfacesLocked() {
+        if (!mSystemReady) return;
         if (LOGV) Slog.v(TAG, "updateIfacesLocked()");
 
         // take one last stats snapshot before updating iface mapping. this
@@ -737,7 +744,9 @@
      * {@link NetworkStatsHistory}.
      */
     private void performPollLocked(int flags) {
+        if (!mSystemReady) return;
         if (LOGV) Slog.v(TAG, "performPollLocked(flags=0x" + Integer.toHexString(flags) + ")");
+
         final long startRealtime = SystemClock.elapsedRealtime();
 
         final boolean persistNetwork = (flags & FLAG_PERSIST_NETWORK) != 0;
diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java
index e471a3f..9f45eff 100644
--- a/services/java/com/android/server/pm/PackageManagerService.java
+++ b/services/java/com/android/server/pm/PackageManagerService.java
@@ -1132,6 +1132,27 @@
                             ? (UPDATE_PERMISSIONS_REPLACE_PKG|UPDATE_PERMISSIONS_REPLACE_ALL)
                             : 0));
 
+            // Verify that all of the preferred activity components actually
+            // exist.  It is possible for applications to be updated and at
+            // that point remove a previously declared activity component that
+            // had been set as a preferred activity.  We try to clean this up
+            // the next time we encounter that preferred activity, but it is
+            // possible for the user flow to never be able to return to that
+            // situation so here we do a sanity check to make sure we haven't
+            // left any junk around.
+            ArrayList<PreferredActivity> removed = new ArrayList<PreferredActivity>();
+            for (PreferredActivity pa : mSettings.mPreferredActivities.filterSet()) {
+                if (mActivities.mActivities.get(pa.mPref.mComponent) == null) {
+                    removed.add(pa);
+                }
+            }
+            for (int i=0; i<removed.size(); i++) {
+                PreferredActivity pa = removed.get(i);
+                Slog.w(TAG, "Removing dangling preferred activity: "
+                        + pa.mPref.mComponent);
+                mSettings.mPreferredActivities.removeFilter(pa);
+            }
+
             // can downgrade to reader
             mSettings.writeLPr();
 
@@ -2295,31 +2316,40 @@
                             Log.v(TAG, "  null");
                         }
                     }
-                    if (ai != null) {
-                        for (int j=0; j<N; j++) {
-                            final ResolveInfo ri = query.get(j);
-                            if (!ri.activityInfo.applicationInfo.packageName
-                                    .equals(ai.applicationInfo.packageName)) {
-                                continue;
-                            }
-                            if (!ri.activityInfo.name.equals(ai.name)) {
-                                continue;
-                            }
-
-                            // Okay we found a previously set preferred app.
-                            // If the result set is different from when this
-                            // was created, we need to clear it and re-ask the
-                            // user their preference.
-                            if (!pa.mPref.sameSet(query, priority)) {
-                                Slog.i(TAG, "Result set changed, dropping preferred activity for "
-                                        + intent + " type " + resolvedType);
-                                mSettings.mPreferredActivities.removeFilter(pa);
-                                return null;
-                            }
-
-                            // Yay!
-                            return ri;
+                    if (ai == null) {
+                        // This previously registered preferred activity
+                        // component is no longer known.  Most likely an update
+                        // to the app was installed and in the new version this
+                        // component no longer exists.  Clean it up by removing
+                        // it from the preferred activities list, and skip it.
+                        Slog.w(TAG, "Removing dangling preferred activity: "
+                                + pa.mPref.mComponent);
+                        mSettings.mPreferredActivities.removeFilter(pa);
+                        continue;
+                    }
+                    for (int j=0; j<N; j++) {
+                        final ResolveInfo ri = query.get(j);
+                        if (!ri.activityInfo.applicationInfo.packageName
+                                .equals(ai.applicationInfo.packageName)) {
+                            continue;
                         }
+                        if (!ri.activityInfo.name.equals(ai.name)) {
+                            continue;
+                        }
+
+                        // Okay we found a previously set preferred app.
+                        // If the result set is different from when this
+                        // was created, we need to clear it and re-ask the
+                        // user their preference.
+                        if (!pa.mPref.sameSet(query, priority)) {
+                            Slog.i(TAG, "Result set changed, dropping preferred activity for "
+                                    + intent + " type " + resolvedType);
+                            mSettings.mPreferredActivities.removeFilter(pa);
+                            return null;
+                        }
+
+                        // Yay!
+                        return ri;
                     }
                 }
             }
@@ -4036,8 +4066,6 @@
 
         // writer
         synchronized (mPackages) {
-            clearPackagePreferredActivitiesLPw(pkg.packageName);
-
             mPackages.remove(pkg.applicationInfo.packageName);
             if (pkg.mPath != null) {
                 mAppDirs.remove(pkg.mPath);
@@ -7118,16 +7146,7 @@
                             mSettings.updateSharedUserPermsLPw(deletedPs, mGlobalGids);
                         }
                     }
-                }
-                // remove from preferred activities.
-                ArrayList<PreferredActivity> removed = new ArrayList<PreferredActivity>();
-                for (PreferredActivity pa : mSettings.mPreferredActivities.filterSet()) {
-                    if (pa.mPref.mComponent.getPackageName().equals(deletedPs.name)) {
-                        removed.add(pa);
-                    }
-                }
-                for (PreferredActivity pa : removed) {
-                    mSettings.mPreferredActivities.removeFilter(pa);
+                    clearPackagePreferredActivitiesLPw(deletedPs.name);
                 }
             }
             // can downgrade to reader
@@ -7569,17 +7588,27 @@
                         android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
             }
             
+            ArrayList<PreferredActivity> removed = null;
             Iterator<PreferredActivity> it = mSettings.mPreferredActivities.filterIterator();
             String action = filter.getAction(0);
             String category = filter.getCategory(0);
             while (it.hasNext()) {
                 PreferredActivity pa = it.next();
                 if (pa.getAction(0).equals(action) && pa.getCategory(0).equals(category)) {
-                    it.remove();
-                    Log.i(TAG, "Removed preferred activity " + pa.mPref.mComponent + ":");
+                    if (removed == null) {
+                        removed = new ArrayList<PreferredActivity>();
+                    }
+                    removed.add(pa);
+                    Log.i(TAG, "Removing preferred activity " + pa.mPref.mComponent + ":");
                     filter.dump(new LogPrinter(Log.INFO, TAG), "  ");
                 }
             }
+            if (removed != null) {
+                for (int i=0; i<removed.size(); i++) {
+                    PreferredActivity pa = removed.get(i);
+                    mSettings.mPreferredActivities.removeFilter(pa);
+                }
+            }
             addPreferredActivity(filter, match, set, activity);
         }
     }
@@ -7611,16 +7640,25 @@
     }
 
     boolean clearPackagePreferredActivitiesLPw(String packageName) {
-        boolean changed = false;
+        ArrayList<PreferredActivity> removed = null;
         Iterator<PreferredActivity> it = mSettings.mPreferredActivities.filterIterator();
         while (it.hasNext()) {
             PreferredActivity pa = it.next();
             if (pa.mPref.mComponent.getPackageName().equals(packageName)) {
-                it.remove();
-                changed = true;
+                if (removed == null) {
+                    removed = new ArrayList<PreferredActivity>();
+                }
+                removed.add(pa);
             }
         }
-        return changed;
+        if (removed != null) {
+            for (int i=0; i<removed.size(); i++) {
+                PreferredActivity pa = removed.get(i);
+                mSettings.mPreferredActivities.removeFilter(pa);
+            }
+            return true;
+        }
+        return false;
     }
 
     public int getPreferredActivities(List<IntentFilter> outFilters,
@@ -7706,6 +7744,17 @@
                 pkgSetting.pkg.mSetEnabled = newState;
             } else {
                 // We're dealing with a component level state change
+                // First, verify that this is a valid class name.
+                PackageParser.Package pkg = pkgSetting.pkg;
+                if (pkg == null || !pkg.hasComponentClassName(className)) {
+                    if (pkg.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.JELLY_BEAN) {
+                        throw new IllegalArgumentException("Component class " + className
+                                + " does not exist in " + packageName);
+                    } else {
+                        Slog.w(TAG, "Failed setComponentEnabledSetting: component class "
+                                + className + " does not exist in " + packageName);
+                    }
+                }
                 switch (newState) {
                 case COMPONENT_ENABLED_STATE_ENABLED:
                     if (!pkgSetting.enableComponentLPw(className)) {
diff --git a/services/java/com/android/server/wm/AppWindowToken.java b/services/java/com/android/server/wm/AppWindowToken.java
index 0e3d20a..b84fbdb 100644
--- a/services/java/com/android/server/wm/AppWindowToken.java
+++ b/services/java/com/android/server/wm/AppWindowToken.java
@@ -37,7 +37,7 @@
  * Version of WindowToken that is specifically for a particular application (or
  * really activity) that is displaying windows.
  */
-class AppWindowToken extends WindowToken {
+class AppWindowToken extends WindowToken implements WindowManagerService.StepAnimator {
     // Non-null only for application tokens.
     final IApplicationToken appToken;
 
@@ -195,8 +195,28 @@
         }
     }
 
+    @Override
+    public boolean stepAnimation(long currentTime) {
+        if (animation == null) {
+            return false;
+        }
+        transformation.clear();
+        final boolean more = animation.getTransformation(currentTime, transformation);
+        if (WindowManagerService.DEBUG_ANIM) Slog.v(
+            WindowManagerService.TAG, "Stepped animation in " + this +
+            ": more=" + more + ", xform=" + transformation);
+        if (!more) {
+            animation = null;
+            if (WindowManagerService.DEBUG_ANIM) Slog.v(
+                WindowManagerService.TAG, "Finished animation in " + this +
+                " @ " + currentTime);
+        }
+        hasTransformation = more;
+        return more;
+    }
+
     // This must be called while inside a transaction.
-    boolean stepAnimationLocked(long currentTime, int dw, int dh) {
+    boolean startAndFinishAnimationLocked(long currentTime, int dw, int dh) {
         if (!service.mDisplayFrozen && service.mPolicy.isScreenOnFully()) {
             // We will run animations as long as the display isn't frozen.
 
@@ -219,21 +239,8 @@
                     animation.setStartTime(currentTime);
                     animating = true;
                 }
-                transformation.clear();
-                final boolean more = animation.getTransformation(
-                    currentTime, transformation);
-                if (WindowManagerService.DEBUG_ANIM) Slog.v(
-                    WindowManagerService.TAG, "Stepped animation in " + this +
-                    ": more=" + more + ", xform=" + transformation);
-                if (more) {
-                    // we're done!
-                    hasTransformation = true;
-                    return true;
-                }
-                if (WindowManagerService.DEBUG_ANIM) Slog.v(
-                    WindowManagerService.TAG, "Finished animation in " + this +
-                    " @ " + currentTime);
-                animation = null;
+                // we're done!
+                return true;
             }
         } else if (animation != null) {
             // If the display is frozen, and there is a pending animation,
@@ -369,6 +376,7 @@
         return null;
     }
 
+    @Override
     void dump(PrintWriter pw, String prefix) {
         super.dump(pw, prefix);
         if (appToken != null) {
diff --git a/services/java/com/android/server/wm/BlackFrame.java b/services/java/com/android/server/wm/BlackFrame.java
index 10e294b..26289c9 100644
--- a/services/java/com/android/server/wm/BlackFrame.java
+++ b/services/java/com/android/server/wm/BlackFrame.java
@@ -16,6 +16,8 @@
 
 package com.android.server.wm;
 
+import java.io.PrintWriter;
+
 import android.graphics.Matrix;
 import android.graphics.PixelFormat;
 import android.graphics.Rect;
@@ -72,14 +74,31 @@
         }
     }
 
+    final Rect mOuterRect;
+    final Rect mInnerRect;
     final Matrix mTmpMatrix = new Matrix();
     final float[] mTmpFloats = new float[9];
     final BlackSurface[] mBlackSurfaces = new BlackSurface[4];
 
+    public void printTo(String prefix, PrintWriter pw) {
+        pw.print(prefix); pw.print("Outer: "); mOuterRect.printShortString(pw);
+                pw.print(" / Inner: "); mInnerRect.printShortString(pw);
+                pw.println();
+        for (int i=0; i<mBlackSurfaces.length; i++) {
+            BlackSurface bs = mBlackSurfaces[i];
+            pw.print(prefix); pw.print("#"); pw.print(i);
+                    pw.print(": "); pw.print(bs.surface);
+                    pw.print(" left="); pw.print(bs.left);
+                    pw.print(" top="); pw.println(bs.top);
+        }
+    }
+
     public BlackFrame(SurfaceSession session, Rect outer, Rect inner,
             int layer) throws Surface.OutOfResourcesException {
         boolean success = false;
 
+        mOuterRect = new Rect(outer);
+        mInnerRect = new Rect(inner);
         try {
             if (outer.top < inner.top) {
                 mBlackSurfaces[0] = new BlackSurface(session, layer,
diff --git a/services/java/com/android/server/wm/ScreenRotationAnimation.java b/services/java/com/android/server/wm/ScreenRotationAnimation.java
index 04a039f..7ac67b6 100644
--- a/services/java/com/android/server/wm/ScreenRotationAnimation.java
+++ b/services/java/com/android/server/wm/ScreenRotationAnimation.java
@@ -29,7 +29,7 @@
 import android.view.animation.AnimationUtils;
 import android.view.animation.Transformation;
 
-class ScreenRotationAnimation {
+class ScreenRotationAnimation implements WindowManagerService.StepAnimator {
     static final String TAG = "ScreenRotationAnimation";
     static final boolean DEBUG_STATE = false;
     static final boolean DEBUG_TRANSFORMS = false;
@@ -59,6 +59,8 @@
     final Transformation mStartExitTransformation = new Transformation();
     Animation mStartEnterAnimation;
     final Transformation mStartEnterTransformation = new Transformation();
+    Animation mStartFrameAnimation;
+    final Transformation mStartFrameTransformation = new Transformation();
 
     // The finishing animation for the exiting and entering elements.  This
     // animation needs to undo the transformation of the starting animation.
@@ -68,6 +70,8 @@
     final Transformation mFinishExitTransformation = new Transformation();
     Animation mFinishEnterAnimation;
     final Transformation mFinishEnterTransformation = new Transformation();
+    Animation mFinishFrameAnimation;
+    final Transformation mFinishFrameTransformation = new Transformation();
 
     // The current active animation to move from the old to the new rotated
     // state.  Which animation is run here will depend on the old and new
@@ -76,6 +80,8 @@
     final Transformation mRotateExitTransformation = new Transformation();
     Animation mRotateEnterAnimation;
     final Transformation mRotateEnterTransformation = new Transformation();
+    Animation mRotateFrameAnimation;
+    final Transformation mRotateFrameTransformation = new Transformation();
 
     // A previously running rotate animation.  This will be used if we need
     // to switch to a new rotation before finishing the previous one.
@@ -83,26 +89,42 @@
     final Transformation mLastRotateExitTransformation = new Transformation();
     Animation mLastRotateEnterAnimation;
     final Transformation mLastRotateEnterTransformation = new Transformation();
+    Animation mLastRotateFrameAnimation;
+    final Transformation mLastRotateFrameTransformation = new Transformation();
 
     // Complete transformations being applied.
     final Transformation mExitTransformation = new Transformation();
     final Transformation mEnterTransformation = new Transformation();
+    final Transformation mFrameTransformation = new Transformation();
 
     boolean mStarted;
     boolean mAnimRunning;
     boolean mFinishAnimReady;
     long mFinishAnimStartTime;
 
+    final Matrix mFrameInitialMatrix = new Matrix();
     final Matrix mSnapshotInitialMatrix = new Matrix();
     final Matrix mSnapshotFinalMatrix = new Matrix();
     final Matrix mTmpMatrix = new Matrix();
     final float[] mTmpFloats = new float[9];
+    private boolean mMoreRotateEnter;
+    private boolean mMoreRotateExit;
+    private boolean mMoreRotateFrame;
+    private boolean mMoreFinishEnter;
+    private boolean mMoreFinishExit;
+    private boolean mMoreFinishFrame;
+    private boolean mMoreStartEnter;
+    private boolean mMoreStartExit;
+    private boolean mMoreStartFrame;
 
     public void printTo(String prefix, PrintWriter pw) {
         pw.print(prefix); pw.print("mSurface="); pw.print(mSurface);
                 pw.print(" mWidth="); pw.print(mWidth);
                 pw.print(" mHeight="); pw.println(mHeight);
         pw.print(prefix); pw.print("mBlackFrame="); pw.println(mBlackFrame);
+        if (mBlackFrame != null) {
+            mBlackFrame.printTo(prefix + "  ", pw);
+        }
         pw.print(prefix); pw.print("mSnapshotRotation="); pw.print(mSnapshotRotation);
                 pw.print(" mSnapshotDeltaRotation="); pw.print(mSnapshotDeltaRotation);
                 pw.print(" mCurRotation="); pw.println(mCurRotation);
@@ -117,21 +139,29 @@
                 pw.print(" "); mStartExitTransformation.printShortString(pw); pw.println();
         pw.print(prefix); pw.print("mStartEnterAnimation="); pw.print(mStartEnterAnimation);
                 pw.print(" "); mStartEnterTransformation.printShortString(pw); pw.println();
+        pw.print(prefix); pw.print("mStartFrameAnimation="); pw.print(mStartFrameAnimation);
+                pw.print(" "); mStartFrameTransformation.printShortString(pw); pw.println();
         pw.print(prefix); pw.print("mFinishExitAnimation="); pw.print(mFinishExitAnimation);
                 pw.print(" "); mFinishExitTransformation.printShortString(pw); pw.println();
         pw.print(prefix); pw.print("mFinishEnterAnimation="); pw.print(mFinishEnterAnimation);
                 pw.print(" "); mFinishEnterTransformation.printShortString(pw); pw.println();
+        pw.print(prefix); pw.print("mFinishFrameAnimation="); pw.print(mFinishFrameAnimation);
+                pw.print(" "); mFinishFrameTransformation.printShortString(pw); pw.println();
         pw.print(prefix); pw.print("mRotateExitAnimation="); pw.print(mRotateExitAnimation);
                 pw.print(" "); mRotateExitTransformation.printShortString(pw); pw.println();
         pw.print(prefix); pw.print("mRotateEnterAnimation="); pw.print(mRotateEnterAnimation);
                 pw.print(" "); mRotateEnterTransformation.printShortString(pw); pw.println();
-        pw.print(prefix); pw.print("mLastRotateExitAnimation=");
-                pw.print(mLastRotateExitAnimation);
-                pw.print(" "); mLastRotateExitTransformation.printShortString(pw); pw.println();
+        pw.print(prefix); pw.print("mRotateFrameAnimation="); pw.print(mRotateFrameAnimation);
+                pw.print(" "); mRotateFrameTransformation.printShortString(pw); pw.println();
         pw.print(prefix); pw.print("mExitTransformation=");
                 mExitTransformation.printShortString(pw); pw.println();
         pw.print(prefix); pw.print("mEnterTransformation=");
                 mEnterTransformation.printShortString(pw); pw.println();
+        pw.print(prefix); pw.print("mFrameTransformation=");
+                mEnterTransformation.printShortString(pw); pw.println();
+        pw.print(prefix); pw.print("mFrameInitialMatrix=");
+                mFrameInitialMatrix.printShortString(pw);
+                pw.println();
         pw.print(prefix); pw.print("mSnapshotInitialMatrix=");
                 mSnapshotInitialMatrix.printShortString(pw);
                 pw.print(" mSnapshotFinalMatrix="); mSnapshotFinalMatrix.printShortString(pw);
@@ -172,7 +202,7 @@
                     mSurface = null;
                     return;
                 }
-                mSurface.setLayer(FREEZE_LAYER + 1);
+                mSurface.setLayer(FREEZE_LAYER);
                 mSurface.show();
             } catch (Surface.OutOfResourcesException e) {
                 Slog.w(TAG, "Unable to allocate freeze surface", e);
@@ -293,10 +323,14 @@
                     com.android.internal.R.anim.screen_rotate_start_exit);
             mStartEnterAnimation = AnimationUtils.loadAnimation(mContext,
                     com.android.internal.R.anim.screen_rotate_start_enter);
+            mStartFrameAnimation = AnimationUtils.loadAnimation(mContext,
+                    com.android.internal.R.anim.screen_rotate_start_frame);
             mFinishExitAnimation = AnimationUtils.loadAnimation(mContext,
                     com.android.internal.R.anim.screen_rotate_finish_exit);
             mFinishEnterAnimation = AnimationUtils.loadAnimation(mContext,
                     com.android.internal.R.anim.screen_rotate_finish_enter);
+            mFinishFrameAnimation = AnimationUtils.loadAnimation(mContext,
+                    com.android.internal.R.anim.screen_rotate_finish_frame);
         }
 
         if (DEBUG_STATE) Slog.v(TAG, "Rotation delta: " + delta + " finalWidth="
@@ -309,24 +343,32 @@
                         com.android.internal.R.anim.screen_rotate_0_exit);
                 mRotateEnterAnimation = AnimationUtils.loadAnimation(mContext,
                         com.android.internal.R.anim.screen_rotate_0_enter);
+                mRotateFrameAnimation = AnimationUtils.loadAnimation(mContext,
+                        com.android.internal.R.anim.screen_rotate_0_frame);
                 break;
             case Surface.ROTATION_90:
                 mRotateExitAnimation = AnimationUtils.loadAnimation(mContext,
                         com.android.internal.R.anim.screen_rotate_plus_90_exit);
                 mRotateEnterAnimation = AnimationUtils.loadAnimation(mContext,
                         com.android.internal.R.anim.screen_rotate_plus_90_enter);
+                mRotateFrameAnimation = AnimationUtils.loadAnimation(mContext,
+                        com.android.internal.R.anim.screen_rotate_plus_90_frame);
                 break;
             case Surface.ROTATION_180:
                 mRotateExitAnimation = AnimationUtils.loadAnimation(mContext,
                         com.android.internal.R.anim.screen_rotate_180_exit);
                 mRotateEnterAnimation = AnimationUtils.loadAnimation(mContext,
                         com.android.internal.R.anim.screen_rotate_180_enter);
+                mRotateFrameAnimation = AnimationUtils.loadAnimation(mContext,
+                        com.android.internal.R.anim.screen_rotate_180_frame);
                 break;
             case Surface.ROTATION_270:
                 mRotateExitAnimation = AnimationUtils.loadAnimation(mContext,
                         com.android.internal.R.anim.screen_rotate_minus_90_exit);
                 mRotateEnterAnimation = AnimationUtils.loadAnimation(mContext,
                         com.android.internal.R.anim.screen_rotate_minus_90_enter);
+                mRotateFrameAnimation = AnimationUtils.loadAnimation(mContext,
+                        com.android.internal.R.anim.screen_rotate_minus_90_frame);
                 break;
         }
 
@@ -340,13 +382,18 @@
                     mOriginalWidth, mOriginalHeight);
             mStartExitAnimation.initialize(finalWidth, finalHeight,
                     mOriginalWidth, mOriginalHeight);
+            mStartFrameAnimation.initialize(finalWidth, finalHeight,
+                    mOriginalWidth, mOriginalHeight);
             mFinishEnterAnimation.initialize(finalWidth, finalHeight,
                     mOriginalWidth, mOriginalHeight);
             mFinishExitAnimation.initialize(finalWidth, finalHeight,
                     mOriginalWidth, mOriginalHeight);
+            mFinishFrameAnimation.initialize(finalWidth, finalHeight,
+                    mOriginalWidth, mOriginalHeight);
         }
         mRotateEnterAnimation.initialize(finalWidth, finalHeight, mOriginalWidth, mOriginalHeight);
         mRotateExitAnimation.initialize(finalWidth, finalHeight, mOriginalWidth, mOriginalHeight);
+        mRotateFrameAnimation.initialize(finalWidth, finalHeight, mOriginalWidth, mOriginalHeight);
         mAnimRunning = false;
         mFinishAnimReady = false;
         mFinishAnimStartTime = -1;
@@ -356,15 +403,21 @@
             mStartExitAnimation.scaleCurrentDuration(animationScale);
             mStartEnterAnimation.restrictDuration(maxAnimationDuration);
             mStartEnterAnimation.scaleCurrentDuration(animationScale);
+            mStartFrameAnimation.restrictDuration(maxAnimationDuration);
+            mStartFrameAnimation.scaleCurrentDuration(animationScale);
             mFinishExitAnimation.restrictDuration(maxAnimationDuration);
             mFinishExitAnimation.scaleCurrentDuration(animationScale);
             mFinishEnterAnimation.restrictDuration(maxAnimationDuration);
             mFinishEnterAnimation.scaleCurrentDuration(animationScale);
+            mFinishFrameAnimation.restrictDuration(maxAnimationDuration);
+            mFinishFrameAnimation.scaleCurrentDuration(animationScale);
         }
         mRotateExitAnimation.restrictDuration(maxAnimationDuration);
         mRotateExitAnimation.scaleCurrentDuration(animationScale);
         mRotateEnterAnimation.restrictDuration(maxAnimationDuration);
         mRotateEnterAnimation.scaleCurrentDuration(animationScale);
+        mRotateFrameAnimation.restrictDuration(maxAnimationDuration);
+        mRotateFrameAnimation.scaleCurrentDuration(animationScale);
 
         if (mBlackFrame == null) {
             if (WindowManagerService.SHOW_LIGHT_TRANSACTIONS || DEBUG_STATE) Slog.i(
@@ -372,10 +425,20 @@
                     ">>> OPEN TRANSACTION ScreenRotationAnimation.startAnimation");
             Surface.openTransaction();
 
+            // Compute the transformation matrix that must be applied
+            // the the black frame to make it stay in the initial position
+            // before the new screen rotation.  This is different than the
+            // snapshot transformation because the snapshot is always based
+            // of the native orientation of the screen, not the orientation
+            // we were last in.
+            createRotationMatrix(delta, mOriginalWidth, mOriginalHeight, mFrameInitialMatrix);
+
             try {
-                Rect outer = new Rect(-finalWidth*1, -finalHeight*1, finalWidth*2, finalHeight*2);
-                Rect inner = new Rect(0, 0, finalWidth, finalHeight);
-                mBlackFrame = new BlackFrame(session, outer, inner, FREEZE_LAYER);
+                Rect outer = new Rect(-mOriginalWidth*1, -mOriginalHeight*1,
+                        mOriginalWidth*2, mOriginalHeight*2);
+                Rect inner = new Rect(0, 0, mOriginalWidth, mOriginalHeight);
+                mBlackFrame = new BlackFrame(session, outer, inner, FREEZE_LAYER + 1);
+                mBlackFrame.setMatrix(mFrameInitialMatrix);
             } catch (Surface.OutOfResourcesException e) {
                 Slog.w(TAG, "Unable to allocate black surface", e);
             } finally {
@@ -432,13 +495,21 @@
             mStartEnterAnimation.cancel();
             mStartEnterAnimation = null;
         }
+        if (mStartFrameAnimation != null) {
+            mStartFrameAnimation.cancel();
+            mStartFrameAnimation = null;
+        }
         if (mFinishExitAnimation != null) {
             mFinishExitAnimation.cancel();
             mFinishExitAnimation = null;
         }
-        if (mStartEnterAnimation != null) {
-            mStartEnterAnimation.cancel();
-            mStartEnterAnimation = null;
+        if (mFinishEnterAnimation != null) {
+            mFinishEnterAnimation.cancel();
+            mFinishEnterAnimation = null;
+        }
+        if (mFinishFrameAnimation != null) {
+            mFinishFrameAnimation.cancel();
+            mFinishFrameAnimation = null;
         }
         if (mRotateExitAnimation != null) {
             mRotateExitAnimation.cancel();
@@ -448,17 +519,210 @@
             mRotateEnterAnimation.cancel();
             mRotateEnterAnimation = null;
         }
+        if (mRotateFrameAnimation != null) {
+            mRotateFrameAnimation.cancel();
+            mRotateFrameAnimation = null;
+        }
     }
 
     public boolean isAnimating() {
         return mStartEnterAnimation != null || mStartExitAnimation != null
-                && mFinishEnterAnimation != null || mFinishExitAnimation != null
-                && mRotateEnterAnimation != null || mRotateExitAnimation != null;
+                || mStartFrameAnimation != null
+                || mFinishEnterAnimation != null || mFinishExitAnimation != null
+                || mFinishFrameAnimation != null
+                || mRotateEnterAnimation != null || mRotateExitAnimation != null
+                || mRotateFrameAnimation != null;
     }
 
+    @Override
     public boolean stepAnimation(long now) {
+
+        if (mFinishAnimReady && mFinishAnimStartTime < 0) {
+            if (DEBUG_STATE) Slog.v(TAG, "Step: finish anim now ready");
+            mFinishAnimStartTime = now;
+        }
+
+        // If the start animation is no longer running, we want to keep its
+        // transformation intact until the finish animation also completes.
+
+        mMoreStartExit = false;
+        if (mStartExitAnimation != null) {
+            mStartExitTransformation.clear();
+            mMoreStartExit = mStartExitAnimation.getTransformation(now, mStartExitTransformation);
+            if (DEBUG_TRANSFORMS) Slog.v(TAG, "Stepped start exit: " + mStartExitTransformation);
+            if (!mMoreStartExit) {
+                if (DEBUG_STATE) Slog.v(TAG, "Start exit animation done!");
+                mStartExitAnimation.cancel();
+                mStartExitAnimation = null;
+            }
+        }
+
+        mMoreStartEnter = false;
+        if (mStartEnterAnimation != null) {
+            mStartEnterTransformation.clear();
+            mMoreStartEnter = mStartEnterAnimation.getTransformation(now, mStartEnterTransformation);
+            if (DEBUG_TRANSFORMS) Slog.v(TAG, "Stepped start enter: " + mStartEnterTransformation);
+            if (!mMoreStartEnter) {
+                if (DEBUG_STATE) Slog.v(TAG, "Start enter animation done!");
+                mStartEnterAnimation.cancel();
+                mStartEnterAnimation = null;
+            }
+        }
+
+        mMoreStartFrame = false;
+        if (mStartFrameAnimation != null) {
+            mStartFrameTransformation.clear();
+            mMoreStartFrame = mStartFrameAnimation.getTransformation(now, mStartFrameTransformation);
+            if (DEBUG_TRANSFORMS) Slog.v(TAG, "Stepped start frame: " + mStartFrameTransformation);
+            if (!mMoreStartFrame) {
+                if (DEBUG_STATE) Slog.v(TAG, "Start frame animation done!");
+                mStartFrameAnimation.cancel();
+                mStartFrameAnimation = null;
+            }
+        }
+
+        long finishNow = mFinishAnimReady ? (now - mFinishAnimStartTime) : 0;
+        if (DEBUG_STATE) Slog.v(TAG, "Step: finishNow=" + finishNow);
+
+        mFinishExitTransformation.clear();
+        mMoreFinishExit = false;
+        if (mFinishExitAnimation != null) {
+            mMoreFinishExit = mFinishExitAnimation.getTransformation(finishNow, mFinishExitTransformation);
+            if (DEBUG_TRANSFORMS) Slog.v(TAG, "Stepped finish exit: " + mFinishExitTransformation);
+            if (!mMoreStartExit && !mMoreFinishExit) {
+                if (DEBUG_STATE) Slog.v(TAG, "Finish exit animation done, clearing start/finish anims!");
+                mStartExitTransformation.clear();
+                mFinishExitAnimation.cancel();
+                mFinishExitAnimation = null;
+                mFinishExitTransformation.clear();
+            }
+        }
+
+        mFinishEnterTransformation.clear();
+        mMoreFinishEnter = false;
+        if (mFinishEnterAnimation != null) {
+            mMoreFinishEnter = mFinishEnterAnimation.getTransformation(finishNow, mFinishEnterTransformation);
+            if (DEBUG_TRANSFORMS) Slog.v(TAG, "Stepped finish enter: " + mFinishEnterTransformation);
+            if (!mMoreStartEnter && !mMoreFinishEnter) {
+                if (DEBUG_STATE) Slog.v(TAG, "Finish enter animation done, clearing start/finish anims!");
+                mStartEnterTransformation.clear();
+                mFinishEnterAnimation.cancel();
+                mFinishEnterAnimation = null;
+                mFinishEnterTransformation.clear();
+            }
+        }
+
+        mFinishFrameTransformation.clear();
+        mMoreFinishFrame = false;
+        if (mFinishFrameAnimation != null) {
+            mMoreFinishFrame = mFinishFrameAnimation.getTransformation(finishNow, mFinishFrameTransformation);
+            if (DEBUG_TRANSFORMS) Slog.v(TAG, "Stepped finish frame: " + mFinishFrameTransformation);
+            if (!mMoreStartFrame && !mMoreFinishFrame) {
+                if (DEBUG_STATE) Slog.v(TAG, "Finish frame animation done, clearing start/finish anims!");
+                mStartFrameTransformation.clear();
+                mFinishFrameAnimation.cancel();
+                mFinishFrameAnimation = null;
+                mFinishFrameTransformation.clear();
+            }
+        }
+
+        mRotateExitTransformation.clear();
+        mMoreRotateExit = false;
+        if (mRotateExitAnimation != null) {
+            mMoreRotateExit = mRotateExitAnimation.getTransformation(now, mRotateExitTransformation);
+            if (DEBUG_TRANSFORMS) Slog.v(TAG, "Stepped rotate exit: " + mRotateExitTransformation);
+            if (!mMoreFinishExit && !mMoreRotateExit) {
+                if (DEBUG_STATE) Slog.v(TAG, "Rotate exit animation done!");
+                mRotateExitAnimation.cancel();
+                mRotateExitAnimation = null;
+                mRotateExitTransformation.clear();
+            }
+        }
+
+        mRotateEnterTransformation.clear();
+        mMoreRotateEnter = false;
+        if (mRotateEnterAnimation != null) {
+            mMoreRotateEnter = mRotateEnterAnimation.getTransformation(now, mRotateEnterTransformation);
+            if (DEBUG_TRANSFORMS) Slog.v(TAG, "Stepped rotate enter: " + mRotateEnterTransformation);
+            if (!mMoreFinishEnter && !mMoreRotateEnter) {
+                if (DEBUG_STATE) Slog.v(TAG, "Rotate enter animation done!");
+                mRotateEnterAnimation.cancel();
+                mRotateEnterAnimation = null;
+                mRotateEnterTransformation.clear();
+            }
+        }
+
+        mRotateFrameTransformation.clear();
+        mMoreRotateFrame = false;
+        if (mRotateFrameAnimation != null) {
+            mMoreRotateFrame = mRotateFrameAnimation.getTransformation(now, mRotateFrameTransformation);
+            if (DEBUG_TRANSFORMS) Slog.v(TAG, "Stepped rotate frame: " + mRotateFrameTransformation);
+            if (!mMoreFinishFrame && !mMoreRotateFrame) {
+                if (DEBUG_STATE) Slog.v(TAG, "Rotate frame animation done!");
+                mRotateFrameAnimation.cancel();
+                mRotateFrameAnimation = null;
+                mRotateFrameTransformation.clear();
+            }
+        }
+
+        mExitTransformation.set(mRotateExitTransformation);
+        mExitTransformation.compose(mStartExitTransformation);
+        mExitTransformation.compose(mFinishExitTransformation);
+
+        mEnterTransformation.set(mRotateEnterTransformation);
+        mEnterTransformation.compose(mStartEnterTransformation);
+        mEnterTransformation.compose(mFinishEnterTransformation);
+
+        //mFrameTransformation.set(mRotateExitTransformation);
+        //mFrameTransformation.compose(mStartExitTransformation);
+        //mFrameTransformation.compose(mFinishExitTransformation);
+        mFrameTransformation.set(mRotateFrameTransformation);
+        mFrameTransformation.compose(mStartFrameTransformation);
+        mFrameTransformation.compose(mFinishFrameTransformation);
+        mFrameTransformation.getMatrix().preConcat(mFrameInitialMatrix);
+
+        if (DEBUG_TRANSFORMS) Slog.v(TAG, "Final exit: " + mExitTransformation);
+        if (DEBUG_TRANSFORMS) Slog.v(TAG, "Final enter: " + mEnterTransformation);
+        if (DEBUG_TRANSFORMS) Slog.v(TAG, "Final frame: " + mFrameTransformation);
+
+        final boolean more = mMoreStartEnter || mMoreStartExit || mMoreStartFrame
+                || mMoreFinishEnter || mMoreFinishExit || mMoreFinishFrame
+                || mMoreRotateEnter || mMoreRotateExit || mMoreRotateFrame
+                || !mFinishAnimReady;
+
+        mSnapshotFinalMatrix.setConcat(mExitTransformation.getMatrix(), mSnapshotInitialMatrix);
+
+        if (DEBUG_STATE) Slog.v(TAG, "Step: more=" + more);
+
+        return more;
+    }
+
+    void updateSurfaces() {
+        if (!mMoreStartExit && !mMoreFinishExit && !mMoreRotateExit) {
+            if (mSurface != null) {
+                if (DEBUG_STATE) Slog.v(TAG, "Exit animations done, hiding screenshot surface");
+                mSurface.hide();
+            }
+        }
+
+        if (!mMoreStartFrame && !mMoreFinishFrame && !mMoreRotateFrame) {
+            if (mBlackFrame != null) {
+                if (DEBUG_STATE) Slog.v(TAG, "Frame animations done, hiding black frame");
+                mBlackFrame.hide();
+            }
+        } else {
+            if (mBlackFrame != null) {
+                mBlackFrame.setMatrix(mFrameTransformation.getMatrix());
+            }
+        }
+
+        setSnapshotTransform(mSnapshotFinalMatrix, mExitTransformation.getAlpha());
+    }
+    
+    public boolean startAndFinishAnimationLocked(long now) {
         if (!isAnimating()) {
             if (DEBUG_STATE) Slog.v(TAG, "Step: no animations running");
+            mFinishAnimReady = false;
             return false;
         }
 
@@ -470,150 +734,31 @@
             if (mStartExitAnimation != null) {
                 mStartExitAnimation.setStartTime(now);
             }
+            if (mStartFrameAnimation != null) {
+                mStartFrameAnimation.setStartTime(now);
+            }
             if (mFinishEnterAnimation != null) {
                 mFinishEnterAnimation.setStartTime(0);
             }
             if (mFinishExitAnimation != null) {
                 mFinishExitAnimation.setStartTime(0);
             }
+            if (mFinishFrameAnimation != null) {
+                mFinishFrameAnimation.setStartTime(0);
+            }
             if (mRotateEnterAnimation != null) {
                 mRotateEnterAnimation.setStartTime(now);
             }
             if (mRotateExitAnimation != null) {
                 mRotateExitAnimation.setStartTime(now);
             }
+            if (mRotateFrameAnimation != null) {
+                mRotateFrameAnimation.setStartTime(now);
+            }
             mAnimRunning = true;
         }
-
-        if (mFinishAnimReady && mFinishAnimStartTime < 0) {
-            if (DEBUG_STATE) Slog.v(TAG, "Step: finish anim now ready");
-            mFinishAnimStartTime = now;
-        }
-
-        // If the start animation is no longer running, we want to keep its
-        // transformation intact until the finish animation also completes.
-
-        boolean moreStartExit = false;
-        if (mStartExitAnimation != null) {
-            mStartExitTransformation.clear();
-            moreStartExit = mStartExitAnimation.getTransformation(now, mStartExitTransformation);
-            if (DEBUG_TRANSFORMS) Slog.v(TAG, "Stepped start exit: " + mStartExitTransformation);
-            if (!moreStartExit) {
-                if (DEBUG_STATE) Slog.v(TAG, "Start exit animation done!");
-                mStartExitAnimation.cancel();
-                mStartExitAnimation = null;
-            }
-        }
-
-        boolean moreStartEnter = false;
-        if (mStartEnterAnimation != null) {
-            mStartEnterTransformation.clear();
-            moreStartEnter = mStartEnterAnimation.getTransformation(now, mStartEnterTransformation);
-            if (DEBUG_TRANSFORMS) Slog.v(TAG, "Stepped start enter: " + mStartEnterTransformation);
-            if (!moreStartEnter) {
-                if (DEBUG_STATE) Slog.v(TAG, "Start enter animation done!");
-                mStartEnterAnimation.cancel();
-                mStartEnterAnimation = null;
-            }
-        }
-
-        long finishNow = mFinishAnimReady ? (now - mFinishAnimStartTime) : 0;
-        if (DEBUG_STATE) Slog.v(TAG, "Step: finishNow=" + finishNow);
-
-        mFinishExitTransformation.clear();
-        boolean moreFinishExit = false;
-        if (mFinishExitAnimation != null) {
-            moreFinishExit = mFinishExitAnimation.getTransformation(finishNow, mFinishExitTransformation);
-            if (DEBUG_TRANSFORMS) Slog.v(TAG, "Stepped finish exit: " + mFinishExitTransformation);
-            if (!moreStartExit && !moreFinishExit) {
-                if (DEBUG_STATE) Slog.v(TAG, "Finish exit animation done, clearing start/finish anims!");
-                mStartExitTransformation.clear();
-                mFinishExitAnimation.cancel();
-                mFinishExitAnimation = null;
-                mFinishExitTransformation.clear();
-            }
-        }
-
-        mFinishEnterTransformation.clear();
-        boolean moreFinishEnter = false;
-        if (mFinishEnterAnimation != null) {
-            moreFinishEnter = mFinishEnterAnimation.getTransformation(finishNow, mFinishEnterTransformation);
-            if (DEBUG_TRANSFORMS) Slog.v(TAG, "Stepped finish enter: " + mFinishEnterTransformation);
-            if (!moreStartEnter && !moreFinishEnter) {
-                if (DEBUG_STATE) Slog.v(TAG, "Finish enter animation done, clearing start/finish anims!");
-                mStartEnterTransformation.clear();
-                mFinishEnterAnimation.cancel();
-                mFinishEnterAnimation = null;
-                mFinishEnterTransformation.clear();
-            }
-        }
-
-        mRotateExitTransformation.clear();
-        boolean moreRotateExit = false;
-        if (mRotateExitAnimation != null) {
-            moreRotateExit = mRotateExitAnimation.getTransformation(now, mRotateExitTransformation);
-            if (DEBUG_TRANSFORMS) Slog.v(TAG, "Stepped rotate exit: " + mRotateExitTransformation);
-        }
-
-        if (!moreFinishExit && !moreRotateExit) {
-            if (DEBUG_STATE) Slog.v(TAG, "Rotate exit animation done!");
-            mRotateExitAnimation.cancel();
-            mRotateExitAnimation = null;
-            mRotateExitTransformation.clear();
-        }
-
-        mRotateEnterTransformation.clear();
-        boolean moreRotateEnter = false;
-        if (mRotateEnterAnimation != null) {
-            moreRotateEnter = mRotateEnterAnimation.getTransformation(now, mRotateEnterTransformation);
-            if (DEBUG_TRANSFORMS) Slog.v(TAG, "Stepped rotate enter: " + mRotateEnterTransformation);
-        }
-
-        if (!moreFinishEnter && !moreRotateEnter) {
-            if (DEBUG_STATE) Slog.v(TAG, "Rotate enter animation done!");
-            mRotateEnterAnimation.cancel();
-            mRotateEnterAnimation = null;
-            mRotateEnterTransformation.clear();
-        }
-
-        mExitTransformation.set(mRotateExitTransformation);
-        mExitTransformation.compose(mStartExitTransformation);
-        mExitTransformation.compose(mFinishExitTransformation);
-
-        mEnterTransformation.set(mRotateEnterTransformation);
-        mEnterTransformation.compose(mStartEnterTransformation);
-        mEnterTransformation.compose(mFinishEnterTransformation);
-
-        if (DEBUG_TRANSFORMS) Slog.v(TAG, "Final exit: " + mExitTransformation);
-        if (DEBUG_TRANSFORMS) Slog.v(TAG, "Final enter: " + mEnterTransformation);
-
-        if (!moreStartExit && !moreFinishExit && !moreRotateExit) {
-            if (mSurface != null) {
-                if (DEBUG_STATE) Slog.v(TAG, "Exit animations done, hiding screenshot surface");
-                mSurface.hide();
-            }
-        }
-
-        if (!moreStartEnter && !moreFinishEnter && !moreRotateEnter) {
-            if (mBlackFrame != null) {
-                if (DEBUG_STATE) Slog.v(TAG, "Enter animations done, hiding black frame");
-                mBlackFrame.hide();
-            }
-        } else {
-            if (mBlackFrame != null) {
-                mBlackFrame.setMatrix(mEnterTransformation.getMatrix());
-            }
-        }
-
-        mSnapshotFinalMatrix.setConcat(mExitTransformation.getMatrix(), mSnapshotInitialMatrix);
-        setSnapshotTransform(mSnapshotFinalMatrix, mExitTransformation.getAlpha());
-
-        final boolean more = moreStartEnter || moreStartExit || moreFinishEnter || moreFinishExit
-                || moreRotateEnter || moreRotateExit || !mFinishAnimReady;
-
-        if (DEBUG_STATE) Slog.v(TAG, "Step: more=" + more);
-
-        return more;
+        
+        return true;
     }
 
     public Transformation getEnterTransformation() {
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index 008793c..023f97d 100644
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -617,6 +617,18 @@
     final AnimationRunnable mAnimationRunnable = new AnimationRunnable();
     boolean mAnimationScheduled;
 
+    interface StepAnimator {
+        /**
+         * Continue the stepping of an ongoing animation. When the animation completes this method
+         * must disable the animation on the StepAnimator. 
+         * @param currentTime Animation time in milliseconds. Use SystemClock.uptimeMillis().
+         * @return True if the animation is still going on, false if the animation has completed
+         *      and stepAnimation has cleared the animation locally.
+         */
+        boolean stepAnimation(long currentTime);
+    }
+    final ArrayList<StepAnimator> mStepAnimators = new ArrayList<StepAnimator>();
+    
     final class DragInputEventReceiver extends InputEventReceiver {
         public DragInputEventReceiver(InputChannel inputChannel, Looper looper) {
             super(inputChannel, looper);
@@ -6335,6 +6347,8 @@
         synchronized (mWindowMap) {
             mInputMonitor.setEventDispatchingLw(enabled);
         }
+
+        sendScreenStatusToClients();
     }
 
     /**
@@ -6558,6 +6572,20 @@
         mPolicy.systemReady();
     }
 
+    private void sendScreenStatusToClients() {
+        final ArrayList<WindowState> windows = mWindows;
+        final int count = windows.size();
+        boolean on = mPowerManager.isScreenOn();
+        for (int i = count - 1; i >= 0; i--) {
+            WindowState win = mWindows.get(i);
+            try {
+                win.mClient.dispatchScreenStatus(on);
+            } catch (RemoteException e) {
+                // Ignored
+            }
+        }
+    }
+
     // This is an animation that does nothing: it just immediately finishes
     // itself every time it is called.  It is used as a stub animation in cases
     // where we want to synchronize multiple things that may be animating.
@@ -7615,37 +7643,54 @@
     }
 
     /**
+     * Run through each of the animating objects saved in mStepAnimators.
+     */
+    private void stepAnimations() {
+        final long currentTime = SystemClock.uptimeMillis();
+        for (final StepAnimator stepAnimator : mStepAnimators) {
+            final boolean more = stepAnimator.stepAnimation(currentTime);
+            if (DEBUG_ANIM) {
+                Slog.v(TAG, "stepAnimations: " + currentTime + ": Stepped " + stepAnimator
+                        + (more ? " more" : " done"));
+            }
+        }
+    }
+    
+    /**
      * Extracted from {@link #performLayoutAndPlaceSurfacesLockedInner} to reduce size of method.
      * Update animations of all applications, including those associated with exiting/removed apps.
      *
      * @param currentTime The time which animations use for calculating transitions.
      * @param innerDw Width of app window.
      * @param innerDh Height of app window.
-     * @return true if rotation has stopped, false otherwise
      */
     private void updateWindowsAppsAndRotationAnimationsLocked(long currentTime,
                                                           int innerDw, int innerDh) {
         int i;
-        for (i = mWindows.size() - 1; i >= 0; i--) {
-            mInnerFields.mAnimating |= mWindows.get(i).stepAnimationLocked(currentTime);
-        }
-
         final int NAT = mAppTokens.size();
         for (i=0; i<NAT; i++) {
-            mInnerFields.mAnimating |=
-                    mAppTokens.get(i).stepAnimationLocked(currentTime, innerDw, innerDh);
+            final AppWindowToken appToken = mAppTokens.get(i);
+            if (appToken.startAndFinishAnimationLocked(currentTime, innerDw, innerDh)) {
+                mStepAnimators.add(appToken);
+                mInnerFields.mAnimating = true;
+            }
         }
         final int NEAT = mExitingAppTokens.size();
         for (i=0; i<NEAT; i++) {
-            mInnerFields.mAnimating |=
-                    mExitingAppTokens.get(i).stepAnimationLocked(currentTime, innerDw, innerDh);
+            final AppWindowToken appToken = mExitingAppTokens.get(i);
+            if (appToken.startAndFinishAnimationLocked(currentTime, innerDw, innerDh)) {
+                mStepAnimators.add(appToken);
+                mInnerFields.mAnimating = true;
+            }
         }
 
         if (mScreenRotationAnimation != null) {
-            if (mScreenRotationAnimation.isAnimating()) {
-                if (mScreenRotationAnimation.stepAnimation(currentTime)) {
+            if (mScreenRotationAnimation.isAnimating() ||
+                    mScreenRotationAnimation.mFinishAnimReady) {
+                if (mScreenRotationAnimation.startAndFinishAnimationLocked(currentTime)) {
                     mInnerFields.mUpdateRotation = false;
                     mInnerFields.mAnimating = true;
+                    mStepAnimators.add(mScreenRotationAnimation);
                 } else {
                     mInnerFields.mUpdateRotation = true;
                     mScreenRotationAnimation.kill();
@@ -7704,7 +7749,13 @@
                 }
 
                 final boolean wasAnimating = w.mWasAnimating;
-                final boolean nowAnimating = w.mLocalAnimating;
+                
+                
+                final boolean nowAnimating = w.startAndFinishAnimationLocked(currentTime);
+                if (nowAnimating) {
+                    mStepAnimators.add(w);
+                    mInnerFields.mAnimating = true;
+                }
 
                 if (DEBUG_WALLPAPER) {
                     Slog.v(TAG, w + ": wasAnimating=" + wasAnimating +
@@ -8290,6 +8341,10 @@
         // difficult because we do need to resize surfaces in some
         // cases while they are hidden such as when first showing a
         // window.
+        
+        if (mScreenRotationAnimation != null) {
+            mScreenRotationAnimation.updateSurfaces();
+        }
         boolean displayed = false;
 
         w.computeShownFrameLocked();
@@ -8562,7 +8617,7 @@
             // so we want to leave all of them as unblurred (for
             // performance reasons).
             mInnerFields.mObscured = true;
-        } else if (canBeSeen && (attrFlags & FLAG_BLUR_BEHIND | FLAG_DIM_BEHIND) != 0) {
+        } else if (canBeSeen && (attrFlags & (FLAG_BLUR_BEHIND | FLAG_DIM_BEHIND)) != 0) {
             if (localLOGV) Slog.v(TAG, "Win " + w
                     + ": blurring=" + mInnerFields.mBlurring
                     + " obscured=" + mInnerFields.mObscured);
@@ -8735,6 +8790,7 @@
                 mInnerFields.mWindowAnimationBackground = null;
                 mInnerFields.mWindowAnimationBackgroundColor = 0;
 
+                mStepAnimators.clear();
                 changes = updateWindowsAndWallpaperLocked(currentTime, dw, dh, innerDw, innerDh);
 
                 if (mInnerFields.mTokenMayBeDrawn) {
@@ -8782,9 +8838,10 @@
 
             // Update animations of all applications, including those
             // associated with exiting/removed apps
-            mInnerFields.mAnimating = false;
 
             updateWindowsAppsAndRotationAnimationsLocked(currentTime, innerDw, innerDh);
+            
+            stepAnimations();
 
             // THIRD LOOP: Update the surfaces of all windows.
 
@@ -9667,8 +9724,8 @@
             pw.println();
             pw.println("  Application tokens in Z order:");
             for (int i=mAppTokens.size()-1; i>=0; i--) {
-                pw.print("  App #"); pw.print(i); pw.print(": ");
-                        pw.println(mAppTokens.get(i));
+                pw.print("  App #"); pw.print(i); pw.println(": ");
+                        mAppTokens.get(i).dump(pw, "    ");
             }
         }
         if (mFinishedStarting.size() > 0) {
diff --git a/services/java/com/android/server/wm/WindowState.java b/services/java/com/android/server/wm/WindowState.java
index eeecad1..b9ee660 100644
--- a/services/java/com/android/server/wm/WindowState.java
+++ b/services/java/com/android/server/wm/WindowState.java
@@ -54,7 +54,8 @@
 /**
  * A window in the window manager.
  */
-final class WindowState implements WindowManagerPolicy.WindowState {
+final class WindowState implements WindowManagerPolicy.WindowState,
+        WindowManagerService.StepAnimator {
     static final boolean DEBUG_VISIBILITY = WindowManagerService.DEBUG_VISIBILITY;
     static final boolean SHOW_TRANSACTIONS = WindowManagerService.SHOW_TRANSACTIONS;
     static final boolean SHOW_LIGHT_TRANSACTIONS = WindowManagerService.SHOW_LIGHT_TRANSACTIONS;
@@ -977,9 +978,26 @@
         return true;
     }
 
+    @Override
+    public boolean stepAnimation(long currentTime) {
+        if ((mAnimation == null) || !mLocalAnimating) {
+            return false;
+        }
+        mTransformation.clear();
+        final boolean more = mAnimation.getTransformation(currentTime, mTransformation);
+        if (WindowManagerService.DEBUG_ANIM) Slog.v(
+            WindowManagerService.TAG, "Stepped animation in " + this +
+            ": more=" + more + ", xform=" + mTransformation);
+        if (!more) {
+            mAnimation.cancel();
+            mAnimation = null;
+        }
+        return more;
+    }
+
     // This must be called while inside a transaction.  Returns true if
     // there is more animation to run.
-    boolean stepAnimationLocked(long currentTime) {
+    boolean startAndFinishAnimationLocked(long currentTime) {
         // Save the animation state as it was before this step so WindowManagerService can tell if
         // we just started or just stopped animating by comparing mWasAnimating with isAnimating().
         mWasAnimating = mAnimating;
@@ -1001,24 +1019,12 @@
                     mLocalAnimating = true;
                     mAnimating = true;
                 }
-                mTransformation.clear();
-                final boolean more = mAnimation.getTransformation(
-                    currentTime, mTransformation);
-                if (WindowManagerService.DEBUG_ANIM) Slog.v(
-                    WindowManagerService.TAG, "Stepped animation in " + this +
-                    ": more=" + more + ", xform=" + mTransformation);
-                if (more) {
-                    // we're not done!
+                if ((mAnimation != null) && mLocalAnimating) {
                     return true;
                 }
                 if (WindowManagerService.DEBUG_ANIM) Slog.v(
                     WindowManagerService.TAG, "Finished animation in " + this +
                     " @ " + currentTime);
-
-                if (mAnimation != null) {
-                    mAnimation.cancel();
-                    mAnimation = null;
-                }
                 //WindowManagerService.this.dump();
             }
             mHasLocalTransformation = false;
diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk
index 42e280f..aa1e426 100644
--- a/services/surfaceflinger/Android.mk
+++ b/services/surfaceflinger/Android.mk
@@ -51,11 +51,6 @@
 # this is only needed for DDMS debugging
 LOCAL_SHARED_LIBRARIES += libdvm libandroid_runtime
 
-LOCAL_C_INCLUDES := \
-	$(call include-path-for, corecg graphics)
-
-LOCAL_C_INCLUDES += hardware/libhardware/modules/gralloc
-
 LOCAL_MODULE:= libsurfaceflinger
 
 include $(BUILD_SHARED_LIBRARY)
diff --git a/services/surfaceflinger/EventThread.cpp b/services/surfaceflinger/EventThread.cpp
index af0da0b..3c045d7 100644
--- a/services/surfaceflinger/EventThread.cpp
+++ b/services/surfaceflinger/EventThread.cpp
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+#define ATRACE_TAG ATRACE_TAG_GRAPHICS
+
 #include <stdint.h>
 #include <sys/types.h>
 
@@ -21,6 +23,7 @@
 #include <gui/DisplayEventReceiver.h>
 
 #include <utils/Errors.h>
+#include <utils/Trace.h>
 
 #include "DisplayHardware/DisplayHardware.h"
 #include "DisplayEventConnection.h"
@@ -146,6 +149,7 @@
             // at least one listener requested VSYNC
             mLock.unlock();
             timestamp = mHw.waitForRefresh();
+            ATRACE_INT("VSYNC", mDeliveredEvents&1);
             mLock.lock();
             mDeliveredEvents++;
             mLastVSyncTimestamp = timestamp;
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 42ed4fa..7f61fe4 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -460,6 +460,7 @@
 
 void SurfaceFlinger::postFramebuffer()
 {
+    ATRACE_CALL();
     // mSwapRegion can be empty here is some cases, for instance if a hidden
     // or fully transparent window is updating.
     // in that case, we need to flip anyways to not risk a deadlock with
@@ -504,6 +505,8 @@
 
 void SurfaceFlinger::handleTransaction(uint32_t transactionFlags)
 {
+    ATRACE_CALL();
+
     Mutex::Autolock _l(mStateLock);
     const nsecs_t now = systemTime();
     mDebugInTransaction = now;
@@ -601,6 +604,8 @@
 void SurfaceFlinger::computeVisibleRegions(
     const LayerVector& currentLayers, Region& dirtyRegion, Region& opaqueRegion)
 {
+    ATRACE_CALL();
+
     const GraphicPlane& plane(graphicPlane(0));
     const Transform& planeTransform(plane.transform());
     const DisplayHardware& hw(plane.displayHardware());
@@ -841,6 +846,8 @@
 
 void SurfaceFlinger::handleRepaint()
 {
+    ATRACE_CALL();
+
     // compute the invalid region
     mSwapRegion.orSelf(mDirtyRegion);
 
diff --git a/telephony/java/com/android/internal/telephony/IccCard.java b/telephony/java/com/android/internal/telephony/IccCard.java
index 530a8dc..fe80fdf 100644
--- a/telephony/java/com/android/internal/telephony/IccCard.java
+++ b/telephony/java/com/android/internal/telephony/IccCard.java
@@ -35,8 +35,15 @@
 
 import com.android.internal.telephony.PhoneBase;
 import com.android.internal.telephony.CommandsInterface.RadioState;
+import com.android.internal.telephony.gsm.SIMFileHandler;
 import com.android.internal.telephony.gsm.SIMRecords;
+import com.android.internal.telephony.cdma.CDMALTEPhone;
+import com.android.internal.telephony.cdma.CdmaLteUiccFileHandler;
+import com.android.internal.telephony.cdma.CdmaLteUiccRecords;
 import com.android.internal.telephony.cdma.CdmaSubscriptionSourceManager;
+import com.android.internal.telephony.cdma.RuimFileHandler;
+import com.android.internal.telephony.cdma.RuimRecords;
+
 import android.os.SystemProperties;
 
 import com.android.internal.R;
@@ -56,6 +63,8 @@
     protected boolean isSubscriptionFromIccCard = true;
     protected CdmaSubscriptionSourceManager mCdmaSSM = null;
     protected PhoneBase mPhone;
+    private IccRecords mIccRecords;
+    private IccFileHandler mIccFileHandler;
     private RegistrantList mAbsentRegistrants = new RegistrantList();
     private RegistrantList mPinLockedRegistrants = new RegistrantList();
     private RegistrantList mNetworkLockedRegistrants = new RegistrantList();
@@ -167,26 +176,46 @@
     }
 
     public IccCard(PhoneBase phone, String logTag, Boolean is3gpp, Boolean dbg) {
+        mLogTag = logTag;
+        mDbg = dbg;
+        if (mDbg) log("[IccCard] Creating card type " + (is3gpp ? "3gpp" : "3gpp2"));
         mPhone = phone;
         this.is3gpp = is3gpp;
         mCdmaSSM = CdmaSubscriptionSourceManager.getInstance(mPhone.getContext(),
                 mPhone.mCM, mHandler, EVENT_CDMA_SUBSCRIPTION_SOURCE_CHANGED, null);
+        if (phone.mCM.getLteOnCdmaMode() == Phone.LTE_ON_CDMA_TRUE
+                && phone instanceof CDMALTEPhone) {
+            mIccRecords = new CdmaLteUiccRecords(phone);
+            mIccFileHandler = new CdmaLteUiccFileHandler((CDMALTEPhone)phone);
+        } else {
+            mIccRecords = is3gpp ? new SIMRecords(phone) : new RuimRecords(phone);
+            mIccFileHandler = is3gpp ? new SIMFileHandler(phone) : new RuimFileHandler(phone);
+        }
         mPhone.mCM.registerForOffOrNotAvailable(mHandler, EVENT_RADIO_OFF_OR_NOT_AVAILABLE, null);
         mPhone.mCM.registerForOn(mHandler, EVENT_RADIO_ON, null);
         mPhone.mCM.registerForIccStatusChanged(mHandler, EVENT_ICC_STATUS_CHANGED, null);
-        mLogTag = logTag;
-        mDbg = dbg;
     }
 
     public void dispose() {
+        if (mDbg) log("[IccCard] Disposing card type " + (is3gpp ? "3gpp" : "3gpp2"));
         mPhone.mCM.unregisterForIccStatusChanged(mHandler);
         mPhone.mCM.unregisterForOffOrNotAvailable(mHandler);
         mPhone.mCM.unregisterForOn(mHandler);
         mCdmaSSM.dispose(mHandler);
+        mIccRecords.dispose();
+        mIccFileHandler.dispose();
     }
 
     protected void finalize() {
-        if(mDbg) Log.d(mLogTag, "IccCard finalized");
+        if (mDbg) log("[IccCard] Finalized card type " + (is3gpp ? "3gpp" : "3gpp2"));
+    }
+
+    public IccRecords getIccRecords() {
+        return mIccRecords;
+    }
+
+    public IccFileHandler getIccFileHandler() {
+        return mIccFileHandler;
     }
 
     /**
@@ -541,6 +570,10 @@
         } else if (isIccCardAdded) {
             mHandler.sendMessage(mHandler.obtainMessage(EVENT_CARD_ADDED, null));
         }
+
+        if (oldState != State.READY && newState == State.READY) {
+            mIccRecords.onReady();
+        }
     }
 
     private void onIccSwap(boolean isAdded) {
@@ -932,6 +965,10 @@
 
     public String getAid() {
         String aid = "";
+        if (mIccCardStatus == null) {
+            return aid;
+        }
+
         int appIndex = getCurrentApplicationIndex();
 
         if (appIndex >= 0 && appIndex < IccCardStatus.CARD_MAX_APPS) {
diff --git a/telephony/java/com/android/internal/telephony/IccRecords.java b/telephony/java/com/android/internal/telephony/IccRecords.java
index fc011c0..6e82903 100644
--- a/telephony/java/com/android/internal/telephony/IccRecords.java
+++ b/telephony/java/com/android/internal/telephony/IccRecords.java
@@ -102,6 +102,7 @@
     public abstract void dispose();
 
     protected abstract void onRadioOffOrNotAvailable();
+    public abstract void onReady();
 
     //***** Public Methods
     public AdnRecordCache getAdnCache() {
diff --git a/telephony/java/com/android/internal/telephony/cdma/CDMALTEPhone.java b/telephony/java/com/android/internal/telephony/cdma/CDMALTEPhone.java
index 3084c14..14a4b46 100644
--- a/telephony/java/com/android/internal/telephony/cdma/CDMALTEPhone.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CDMALTEPhone.java
@@ -36,6 +36,7 @@
 import com.android.internal.telephony.SMSDispatcher;
 import com.android.internal.telephony.gsm.GsmSMSDispatcher;
 import com.android.internal.telephony.ims.IsimRecords;
+import com.android.internal.telephony.uicc.UiccController;
 
 public class CDMALTEPhone extends CDMAPhone {
     static final String LOG_TAG = "CDMA";
@@ -79,9 +80,9 @@
 
     @Override
     protected void initSstIcc() {
-        mIccCard = new IccCard(this, LOG_TAG, IccCard.CARD_IS_3GPP, DBG);
-        mIccRecords = new CdmaLteUiccRecords(this);
-        mIccFileHandler = new CdmaLteUiccFileHandler(this);
+        mIccCard = UiccController.getInstance(this).getIccCard();
+        mIccRecords = mIccCard.getIccRecords();
+        mIccFileHandler = mIccCard.getIccFileHandler();
         // CdmaLteServiceStateTracker registers with IccCard to know
         // when the card is ready. So create mIccCard before the ServiceStateTracker
         mSST = new CdmaLteServiceStateTracker(this);
@@ -164,7 +165,7 @@
         // look for our wrapper within the asyncresult, skip the rest if it
         // is null.
         if (!(ar.userObj instanceof NetworkSelectMessage)) {
-            if (DBG) Log.d(LOG_TAG, "unexpected result from user object.");
+            Log.e(LOG_TAG, "unexpected result from user object.");
             return;
         }
 
@@ -173,7 +174,7 @@
         // found the object, now we send off the message we had originally
         // attached to the request.
         if (nsm.message != null) {
-            if (DBG) Log.d(LOG_TAG, "sending original message to recipient");
+            if (DBG) log("sending original message to recipient");
             AsyncResult.forMessage(nsm.message, ar.result, ar.exception);
             nsm.message.sendToTarget();
         }
@@ -200,14 +201,15 @@
                 ContentValues map = new ContentValues();
                 String operatorNumeric = mIccRecords.getOperatorNumeric();
                 map.put(Telephony.Carriers.NUMERIC, operatorNumeric);
-                log("updateCurrentCarrierInProvider from UICC: numeric=" + operatorNumeric);
+                if (DBG) log("updateCurrentCarrierInProvider from UICC: numeric=" +
+                        operatorNumeric);
                 mContext.getContentResolver().insert(uri, map);
                 return true;
             } catch (SQLException e) {
                 Log.e(LOG_TAG, "[CDMALTEPhone] Can't store current operator ret false", e);
             }
         } else {
-            log("updateCurrentCarrierInProvider mIccRecords == null ret false");
+            if (DBG) log("updateCurrentCarrierInProvider mIccRecords == null ret false");
         }
         return false;
     }
@@ -259,7 +261,6 @@
 
     @Override
     protected void log(String s) {
-        if (DBG)
             Log.d(LOG_TAG, "[CDMALTEPhone] " + s);
     }
 }
diff --git a/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java b/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java
index b5dca65..e86e441 100755
--- a/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java
@@ -64,6 +64,7 @@
 import com.android.internal.telephony.TelephonyProperties;
 import com.android.internal.telephony.UUSInfo;
 import com.android.internal.telephony.cat.CatService;
+import com.android.internal.telephony.uicc.UiccController;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -149,9 +150,9 @@
     }
 
     protected void initSstIcc() {
-        mIccCard = new IccCard(this, LOG_TAG, IccCard.CARD_IS_NOT_3GPP, DBG);
-        mIccRecords = new RuimRecords(this);
-        mIccFileHandler = new RuimFileHandler(this);
+        mIccCard = UiccController.getInstance(this).getIccCard();
+        mIccRecords = mIccCard.getIccRecords();
+        mIccFileHandler = mIccCard.getIccFileHandler();
         // CdmaServiceStateTracker registers with IccCard to know
         // when the Ruim card is ready. So create mIccCard before the ServiceStateTracker
         mSST = new CdmaServiceStateTracker(this);
@@ -242,7 +243,6 @@
             mSMS.dispose();
             mIccFileHandler.dispose(); // instance of RuimFileHandler
             mIccRecords.dispose();
-            mIccCard.dispose();
             mRuimPhoneBookInterfaceManager.dispose();
             mRuimSmsInterfaceManager.dispose();
             mSubInfo.dispose();
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaLteUiccFileHandler.java b/telephony/java/com/android/internal/telephony/cdma/CdmaLteUiccFileHandler.java
index 8375fd0..e195ff2 100644
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaLteUiccFileHandler.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaLteUiccFileHandler.java
@@ -27,7 +27,7 @@
 public final class CdmaLteUiccFileHandler extends IccFileHandler {
     static final String LOG_TAG = "CDMA";
 
-    CdmaLteUiccFileHandler(CDMALTEPhone phone) {
+    public CdmaLteUiccFileHandler(CDMALTEPhone phone) {
         super(phone);
     }
 
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaLteUiccRecords.java b/telephony/java/com/android/internal/telephony/cdma/CdmaLteUiccRecords.java
index 0a285b9..ca1e96d 100755
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaLteUiccRecords.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaLteUiccRecords.java
@@ -436,6 +436,10 @@
             return true;
         }
 
+        if (phone == null || phone.mIccCard == null) {
+            return false;
+        }
+
         if (phone.mIccCard.isApplicationOnIcc(AppType.APPTYPE_CSIM) &&
             ((mMdn == null) || (mMin == null))) {
             return false;
diff --git a/telephony/java/com/android/internal/telephony/cdma/RuimFileHandler.java b/telephony/java/com/android/internal/telephony/cdma/RuimFileHandler.java
index 375cc07..e854d7f 100644
--- a/telephony/java/com/android/internal/telephony/cdma/RuimFileHandler.java
+++ b/telephony/java/com/android/internal/telephony/cdma/RuimFileHandler.java
@@ -25,6 +25,7 @@
 import com.android.internal.telephony.IccFileTypeMismatch;
 import com.android.internal.telephony.IccIoResult;
 import com.android.internal.telephony.IccUtils;
+import com.android.internal.telephony.PhoneBase;
 import com.android.internal.telephony.PhoneProxy;
 
 import java.util.ArrayList;
@@ -38,7 +39,7 @@
     //***** Instance Variables
 
     //***** Constructor
-    RuimFileHandler(CDMAPhone phone) {
+    public RuimFileHandler(PhoneBase phone) {
         super(phone);
     }
 
diff --git a/telephony/java/com/android/internal/telephony/cdma/RuimRecords.java b/telephony/java/com/android/internal/telephony/cdma/RuimRecords.java
index e518c4c..265dff7 100755
--- a/telephony/java/com/android/internal/telephony/cdma/RuimRecords.java
+++ b/telephony/java/com/android/internal/telephony/cdma/RuimRecords.java
@@ -31,6 +31,7 @@
 import com.android.internal.telephony.CommandsInterface;
 import com.android.internal.telephony.IccRefreshResponse;
 import com.android.internal.telephony.IccCard;
+import com.android.internal.telephony.PhoneBase;
 import com.android.internal.telephony.TelephonyProperties;
 import com.android.internal.telephony.MccTable;
 
@@ -61,7 +62,6 @@
 
     // ***** Event Constants
 
-    private static final int EVENT_RUIM_READY = 1;
     private static final int EVENT_RADIO_OFF_OR_NOT_AVAILABLE = 2;
     private static final int EVENT_GET_IMSI_DONE = 3;
     private static final int EVENT_GET_DEVICE_IDENTITY_DONE = 4;
@@ -78,7 +78,7 @@
     private static final int EVENT_RUIM_REFRESH = 31;
 
 
-    RuimRecords(CDMAPhone p) {
+    public RuimRecords(PhoneBase p) {
         super(p);
 
         adnCache = new AdnRecordCache(phone);
@@ -88,8 +88,6 @@
         // recordsToLoad is set to 0 because no requests are made yet
         recordsToLoad = 0;
 
-
-        p.mIccCard.registerForRuimReady(this, EVENT_RUIM_READY, null);
         p.mCM.registerForOffOrNotAvailable(this, EVENT_RADIO_OFF_OR_NOT_AVAILABLE, null);
         // NOTE the EVENT_SMS_ON_RUIM is not registered
         p.mCM.registerForIccRefresh(this, EVENT_RUIM_REFRESH, null);
@@ -102,7 +100,6 @@
     @Override
     public void dispose() {
         //Unregister for all events
-        phone.mIccCard.unregisterForRuimReady(this);
         phone.mCM.unregisterForOffOrNotAvailable( this);
         phone.mCM.unregisterForIccRefresh(this);
     }
@@ -206,10 +203,6 @@
         }
 
         try { switch (msg.what) {
-            case EVENT_RUIM_READY:
-                onRuimReady();
-            break;
-
             case EVENT_RADIO_OFF_OR_NOT_AVAILABLE:
                 onRadioOffOrNotAvailable();
             break;
@@ -349,7 +342,8 @@
                 IccCard.INTENT_VALUE_ICC_LOADED, null);
     }
 
-    private void onRuimReady() {
+    @Override
+    public void onReady() {
         /* broadcast intent ICC_READY here so that we can make sure
           READY is sent before IMSI ready
         */
diff --git a/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java b/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java
index 4c846f1..5e9a4f2 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java
@@ -70,6 +70,7 @@
 import com.android.internal.telephony.TelephonyProperties;
 import com.android.internal.telephony.UUSInfo;
 import com.android.internal.telephony.test.SimulatedRadioControl;
+import com.android.internal.telephony.uicc.UiccController;
 import com.android.internal.telephony.IccVmNotSupportedException;
 import com.android.internal.telephony.ServiceStateTracker;
 
@@ -136,12 +137,12 @@
         }
 
         mCM.setPhoneType(Phone.PHONE_TYPE_GSM);
-        mIccCard = new IccCard(this, LOG_TAG, IccCard.CARD_IS_3GPP, true);
+        mIccCard = UiccController.getInstance(this).getIccCard();
         mCT = new GsmCallTracker(this);
         mSST = new GsmServiceStateTracker (this);
         mSMS = new GsmSMSDispatcher(this, mSmsStorageMonitor, mSmsUsageMonitor);
-        mIccFileHandler = new SIMFileHandler(this);
-        mIccRecords = new SIMRecords(this);
+        mIccFileHandler = mIccCard.getIccFileHandler();
+        mIccRecords = mIccCard.getIccRecords();
         mDataConnectionTracker = new GsmDataConnectionTracker (this);
         if (!unitTestMode) {
             mSimPhoneBookIntManager = new SimPhoneBookInterfaceManager(this);
@@ -220,7 +221,6 @@
             mSST.dispose();
             mIccFileHandler.dispose(); // instance of SimFileHandler
             mIccRecords.dispose();
-            mIccCard.dispose();
             mSimPhoneBookIntManager.dispose();
             mSimSmsIntManager.dispose();
             mSubInfo.dispose();
diff --git a/telephony/java/com/android/internal/telephony/gsm/SIMFileHandler.java b/telephony/java/com/android/internal/telephony/gsm/SIMFileHandler.java
index e8d10f9..8c3bc0e 100644
--- a/telephony/java/com/android/internal/telephony/gsm/SIMFileHandler.java
+++ b/telephony/java/com/android/internal/telephony/gsm/SIMFileHandler.java
@@ -23,22 +23,20 @@
 import com.android.internal.telephony.IccCardApplication;
 import com.android.internal.telephony.IccConstants;
 import com.android.internal.telephony.IccFileHandler;
-import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.PhoneBase;
 
 /**
  * {@hide}
  */
 public final class SIMFileHandler extends IccFileHandler implements IccConstants {
     static final String LOG_TAG = "GSM";
-    private Phone mPhone;
 
     //***** Instance Variables
 
     //***** Constructor
 
-    SIMFileHandler(GSMPhone phone) {
+    public SIMFileHandler(PhoneBase phone) {
         super(phone);
-        mPhone = phone;
     }
 
     public void dispose() {
diff --git a/telephony/java/com/android/internal/telephony/gsm/SIMRecords.java b/telephony/java/com/android/internal/telephony/gsm/SIMRecords.java
index 1fb99e3..68d3b2a 100755
--- a/telephony/java/com/android/internal/telephony/gsm/SIMRecords.java
+++ b/telephony/java/com/android/internal/telephony/gsm/SIMRecords.java
@@ -123,7 +123,6 @@
 
     // ***** Event Constants
 
-    private static final int EVENT_SIM_READY = 1;
     private static final int EVENT_RADIO_OFF_OR_NOT_AVAILABLE = 2;
     protected static final int EVENT_GET_IMSI_DONE = 3;
     protected static final int EVENT_GET_ICCID_DONE = 4;
@@ -188,7 +187,6 @@
         // recordsToLoad is set to 0 because no requests are made yet
         recordsToLoad = 0;
 
-        p.mIccCard.registerForReady(this, EVENT_SIM_READY, null);
         p.mCM.registerForOffOrNotAvailable(
                         this, EVENT_RADIO_OFF_OR_NOT_AVAILABLE, null);
         p.mCM.setOnSmsOnSim(this, EVENT_SMS_ON_SIM, null);
@@ -202,7 +200,6 @@
     @Override
     public void dispose() {
         //Unregister for all events
-        phone.mIccCard.unregisterForReady(this);
         phone.mCM.unregisterForOffOrNotAvailable( this);
         phone.mCM.unregisterForIccRefresh(this);
     }
@@ -526,10 +523,6 @@
         }
 
         try { switch (msg.what) {
-            case EVENT_SIM_READY:
-                onSimReady();
-            break;
-
             case EVENT_RADIO_OFF_OR_NOT_AVAILABLE:
                 onRadioOffOrNotAvailable();
             break;
@@ -1296,7 +1289,8 @@
         }
     }
 
-    public void onSimReady() {
+    @Override
+    public void onReady() {
         /* broadcast intent SIM_READY here so that we can make sure
           READY is sent before IMSI ready
         */
diff --git a/telephony/java/com/android/internal/telephony/uicc/UiccController.java b/telephony/java/com/android/internal/telephony/uicc/UiccController.java
new file mode 100644
index 0000000..5961efd
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/uicc/UiccController.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2011 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.internal.telephony.uicc;
+
+import com.android.internal.telephony.IccCard;
+import com.android.internal.telephony.PhoneBase;
+import com.android.internal.telephony.cdma.CDMALTEPhone;
+import com.android.internal.telephony.cdma.CDMAPhone;
+import com.android.internal.telephony.gsm.GSMPhone;
+
+import android.util.Log;
+
+/* This class is responsible for keeping all knowledge about
+ * ICCs in the system. It is also used as API to get appropriate
+ * applications to pass them to phone and service trackers.
+ */
+public class UiccController {
+    private static final boolean DBG = true;
+    private static final String LOG_TAG = "RIL_UiccController";
+
+    private static UiccController mInstance;
+
+    private PhoneBase mCurrentPhone;
+    private boolean mIsCurrentCard3gpp;
+    private IccCard mIccCard;
+
+    public static synchronized UiccController getInstance(PhoneBase phone) {
+        if (mInstance == null) {
+            mInstance = new UiccController(phone);
+        } else {
+            mInstance.setNewPhone(phone);
+        }
+        return mInstance;
+    }
+
+    public IccCard getIccCard() {
+        return mIccCard;
+    }
+
+    private UiccController(PhoneBase phone) {
+        if (DBG) log("Creating UiccController");
+        setNewPhone(phone);
+    }
+
+    private void setNewPhone(PhoneBase phone) {
+        mCurrentPhone = phone;
+        if (phone instanceof GSMPhone) {
+            if (DBG) log("New phone is GSMPhone");
+            updateCurrentCard(IccCard.CARD_IS_3GPP);
+        } else if (phone instanceof CDMALTEPhone){
+            if (DBG) log("New phone type is CDMALTEPhone");
+            updateCurrentCard(IccCard.CARD_IS_3GPP);
+        } else if (phone instanceof CDMAPhone){
+            if (DBG) log("New phone type is CDMAPhone");
+            updateCurrentCard(IccCard.CARD_IS_NOT_3GPP);
+        } else {
+            Log.e(LOG_TAG, "Unhandled phone type. Critical error!");
+        }
+    }
+
+    private void updateCurrentCard(boolean isNewCard3gpp) {
+        if (mIsCurrentCard3gpp == isNewCard3gpp && mIccCard != null) {
+            return;
+        }
+
+        if (mIccCard != null) {
+            mIccCard.dispose();
+            mIccCard = null;
+        }
+
+        mIsCurrentCard3gpp = isNewCard3gpp;
+        mIccCard = new IccCard(mCurrentPhone, mCurrentPhone.getPhoneName(),
+                isNewCard3gpp, DBG);
+    }
+
+    private void log(String string) {
+        Log.d(LOG_TAG, string);
+    }
+}
\ No newline at end of file
diff --git a/tests/BiDiTests/Android-private.mk b/tests/BiDiTests/Android.mk
similarity index 100%
rename from tests/BiDiTests/Android-private.mk
rename to tests/BiDiTests/Android.mk
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestsAutoRunner.java b/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestsAutoRunner.java
index 3ba3488..fb2a1f4 100755
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestsAutoRunner.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestsAutoRunner.java
@@ -58,27 +58,9 @@
             }
         }
 
-        String delay_str = (String) icicle.get("delay");
-        if(delay_str != null) {
-            try {
-                this.mDelay = Integer.parseInt(delay_str);
-            } catch (Exception e) {
-            }
-        }
-
         String r = icicle.getString("rebaseline");
         this.mRebaseline = (r != null && r.toLowerCase().equals("true"));
 
-        String logtime = icicle.getString("logtime");
-        this.mLogtime = (logtime != null
-                && logtime.toLowerCase().equals("true"));
-
-        String drawTime = icicle.getString("drawtime");
-        this.mGetDrawTime = (drawTime != null
-                && drawTime.toLowerCase().equals("true"));
-
-        mSaveImagePath = icicle.getString("saveimage");
-
         mJsEngine = icicle.getString("jsengine");
 
         mPageCyclerSuite = icicle.getString("suite");
@@ -92,11 +74,7 @@
     String mPageCyclerForwardHost;
     String mPageCyclerIteration;
     String mTestPath;
-    String mSaveImagePath;
-    int mTimeoutInMillis;
-    int mDelay;
+    int mTimeoutInMillis = 0;
     boolean mRebaseline;
-    boolean mLogtime;
-    boolean mGetDrawTime;
     String mJsEngine;
 }
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestsAutoTest.java b/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestsAutoTest.java
index 7ac0665..3fe4e70 100644
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestsAutoTest.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestsAutoTest.java
@@ -314,6 +314,10 @@
             public void timedOut(String url) {
                 Log.v(LOGTAG, "layout timeout: " + url);
             }
+
+            @Override
+            public void dumpResult(String webViewDump) {
+            }
         });
 
         String resultFile = getResultFile(test);
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/LoadTestsAutoTest.java b/tests/DumpRenderTree/src/com/android/dumprendertree/LoadTestsAutoTest.java
index d883a32..4b86a0b 100644
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/LoadTestsAutoTest.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/LoadTestsAutoTest.java
@@ -19,6 +19,7 @@
 import com.android.dumprendertree.forwarder.AdbUtils;
 import com.android.dumprendertree.forwarder.ForwardServer;
 
+import android.app.Activity;
 import android.app.Instrumentation;
 import android.content.Context;
 import android.content.Intent;
@@ -106,8 +107,7 @@
         freeMem();
 
         // Run tests
-        runTestAndWaitUntilDone(activity, runner.mTestPath, runner.mTimeoutInMillis,
-                runner.mGetDrawTime, runner.mSaveImagePath);
+        runTestAndWaitUntilDone(activity, runner.mTestPath, runner.mTimeoutInMillis);
 
         getInstrumentation().runOnMainSync(new Runnable() {
 
@@ -215,9 +215,9 @@
     }
 
     // A convenient method to be called by another activity.
-    private void runTestAndWaitUntilDone(TestShellActivity activity, String url, int timeout,
-            boolean getDrawTime, String saveImagePath) {
+    private void runTestAndWaitUntilDone(TestShellActivity activity, String url, int timeout) {
         activity.setCallback(new TestShellCallback() {
+            @Override
             public void finished() {
                 synchronized (LoadTestsAutoTest.this) {
                     mFinished = true;
@@ -225,8 +225,29 @@
                 }
             }
 
+            @Override
             public void timedOut(String url) {
             }
+
+            @Override
+            public void dumpResult(String webViewDump) {
+                String lines[] = webViewDump.split("\\r?\\n");
+                for (String line : lines) {
+                    line = line.trim();
+                    // parse for a line like this:
+                    // totals:   9620.00 11947.00    10099.75    380.38
+                    // and return the 3rd number, which is mean
+                    if (line.startsWith("totals:")) {
+                        line = line.substring(7).trim(); // strip "totals:"
+                        String[] numbers = line.split("\\s+");
+                        if (numbers.length == 4) {
+                            Bundle b = new Bundle();
+                            b.putString("mean", numbers[2]);
+                            getInstrumentation().sendStatus(Activity.RESULT_FIRST_USER, b);
+                        }
+                    }
+                }
+            }
         });
 
         mFinished = false;
@@ -236,9 +257,6 @@
         intent.putExtra(TestShellActivity.TEST_URL, url);
         intent.putExtra(TestShellActivity.TIMEOUT_IN_MILLIS, timeout);
         intent.putExtra(TestShellActivity.RESULT_FILE, LOAD_TEST_RESULT);
-        intent.putExtra(TestShellActivity.GET_DRAW_TIME, getDrawTime);
-        if (saveImagePath != null)
-            intent.putExtra(TestShellActivity.SAVE_IMAGE, saveImagePath);
         activity.startActivity(intent);
 
         // Wait until done.
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/ReliabilityTest.java b/tests/DumpRenderTree/src/com/android/dumprendertree/ReliabilityTest.java
deleted file mode 100644
index d146fc7..0000000
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/ReliabilityTest.java
+++ /dev/null
@@ -1,196 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.dumprendertree;
-
-import android.app.Activity;
-import android.content.Intent;
-import android.os.Environment;
-import android.os.Handler;
-import android.os.Message;
-import android.test.ActivityInstrumentationTestCase2;
-import android.util.Log;
-
-import java.io.BufferedOutputStream;
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.FileReader;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-
-public class ReliabilityTest extends ActivityInstrumentationTestCase2<ReliabilityTestActivity> {
-
-    private static final String LOGTAG = "ReliabilityTest";
-    private static final String PKG_NAME = "com.android.dumprendertree";
-    private static final String EXTERNAL_DIR =
-        Environment.getExternalStorageDirectory().toString();
-    private static final String TEST_LIST_FILE = EXTERNAL_DIR +
-        "/android/reliability_tests_list.txt";
-    private static final String TEST_STATUS_FILE = EXTERNAL_DIR +
-        "/android/reliability_running_test.txt";
-    private static final String TEST_TIMEOUT_FILE = EXTERNAL_DIR +
-        "/android/reliability_timeout_test.txt";
-    private static final String TEST_LOAD_TIME_FILE = EXTERNAL_DIR +
-        "/android/reliability_load_time.txt";
-    private static final String TEST_DONE = "#DONE";
-    static final String RELIABILITY_TEST_RUNNER_FILES[] = {
-        "run_reliability_tests.py"
-    };
-
-    public ReliabilityTest() {
-        super(PKG_NAME, ReliabilityTestActivity.class);
-    }
-
-    public void runReliabilityTest() throws Throwable {
-//        ReliabilityTestActivity activity = getActivity();
-        LayoutTestsAutoRunner runner = (LayoutTestsAutoRunner)getInstrumentation();
-
-        File testListFile = new File(TEST_LIST_FILE);
-        if(!testListFile.exists())
-            throw new FileNotFoundException("test list file not found.");
-
-        BufferedReader listReader = new BufferedReader(
-                new FileReader(testListFile));
-
-        //always try to resume first, hence cleaning up status will be the
-        //responsibility of driver scripts
-        String lastUrl = FsUtils.readTestStatus(TEST_STATUS_FILE);
-        if(lastUrl != null && !TEST_DONE.equals(lastUrl))
-            fastForward(listReader, lastUrl);
-
-        String url = null;
-        Handler handler = null;
-        boolean timeoutFlag = false;
-        long start, elapsed;
-
-        Intent intent = new Intent(runner.getContext(), ReliabilityTestActivity.class);
-        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-        ReliabilityTestActivity activity = (ReliabilityTestActivity)runner.startActivitySync(
-            intent);
-        //read from BufferedReader instead of populating a list in advance,
-        //this will avoid excessive memory usage in case of a large list
-        while((url = listReader.readLine()) != null) {
-            url = url.trim();
-            if(url.length() == 0)
-                continue;
-            start = System.currentTimeMillis();
-            Log.v(LOGTAG, "Testing URL: " + url);
-            FsUtils.updateTestStatus(TEST_STATUS_FILE, url);
-            activity.reset();
-            //use message to send new URL to avoid interacting with
-            //WebView in non-UI thread
-            handler = activity.getHandler();
-            Message msg = handler.obtainMessage(
-                    ReliabilityTestActivity.MSG_NAVIGATE,
-                    runner.mTimeoutInMillis, runner.mDelay);
-            msg.getData().putString(ReliabilityTestActivity.MSG_NAV_URL, url);
-            msg.getData().putBoolean(ReliabilityTestActivity.MSG_NAV_LOGTIME,
-                    runner.mLogtime);
-            handler.sendMessage(msg);
-            timeoutFlag = activity.waitUntilDone();
-            elapsed = System.currentTimeMillis() - start;
-            if(elapsed < 1000) {
-                Log.w(LOGTAG, "Page load finished in " + elapsed
-                        + "ms, too soon?");
-            } else {
-                Log.v(LOGTAG, "Page load finished in " + elapsed + "ms");
-            }
-            if(timeoutFlag) {
-                writeTimeoutFile(url);
-            }
-            if(runner.mLogtime) {
-                writeLoadTime(url, activity.getPageLoadTime());
-            }
-            System.runFinalization();
-            System.gc();
-            System.gc();
-        }
-        activity.finish();
-        FsUtils.updateTestStatus(TEST_STATUS_FILE, TEST_DONE);
-//        activity.finish();
-        listReader.close();
-    }
-
-    public void copyRunnerAssetsToCache() {
-        try {
-            String out_dir = getActivity().getApplicationContext()
-            .getCacheDir().getPath() + "/";
-
-            for( int i=0; i< RELIABILITY_TEST_RUNNER_FILES.length; i++) {
-                InputStream in = getActivity().getAssets().open(
-                        RELIABILITY_TEST_RUNNER_FILES[i]);
-                OutputStream out = new FileOutputStream(
-                        out_dir + RELIABILITY_TEST_RUNNER_FILES[i]);
-
-                byte[] buf = new byte[2048];
-                int len;
-
-                while ((len = in.read(buf)) >= 0 ) {
-                    out.write(buf, 0, len);
-                }
-                out.close();
-                in.close();
-            }
-        }catch (IOException e) {
-            Log.e(LOGTAG, "Cannot extract scripts for testing.", e);
-        }
-    }
-
-    private void fastForward(BufferedReader testListReader, String lastUrl) {
-        //fastforward the BufferedReader to the position right after last url
-        if(lastUrl == null)
-            return;
-
-        String line = null;
-        try {
-            while((line = testListReader.readLine()) != null) {
-                if(lastUrl.equals(line))
-                    return;
-            }
-        } catch (IOException ioe) {
-            Log.e(LOGTAG, "Error while reading test list.", ioe);
-            return;
-        }
-    }
-
-    private void writeTimeoutFile(String s) {
-        //append to the file containing the list of timeout urls
-        try {
-            BufferedOutputStream bos = new BufferedOutputStream(
-                    new FileOutputStream(TEST_TIMEOUT_FILE, true));
-            bos.write(s.getBytes());
-            bos.write('\n');
-            bos.close();
-        } catch (Exception e) {
-            Log.e(LOGTAG, "Cannot update file " + TEST_TIMEOUT_FILE, e);
-        }
-    }
-
-    private void writeLoadTime(String s, long time) {
-        //append to the file containing the list of timeout urls
-        try {
-            BufferedOutputStream bos = new BufferedOutputStream(
-                    new FileOutputStream(TEST_LOAD_TIME_FILE, true));
-            bos.write((s + '|' + time + '\n').getBytes());
-            bos.close();
-        } catch (Exception e) {
-            Log.e(LOGTAG, "Cannot update file " + TEST_LOAD_TIME_FILE, e);
-        }
-    }
-}
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java b/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java
index 83c9c3d..d151d9e 100644
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java
@@ -25,9 +25,6 @@
 import android.content.DialogInterface.OnClickListener;
 import android.content.Intent;
 import android.graphics.Bitmap;
-import android.graphics.Bitmap.CompressFormat;
-import android.graphics.Bitmap.Config;
-import android.graphics.Canvas;
 import android.net.http.SslError;
 import android.os.Bundle;
 import android.os.Environment;
@@ -45,8 +42,10 @@
 import android.webkit.SslErrorHandler;
 import android.webkit.WebChromeClient;
 import android.webkit.WebSettings;
+import android.webkit.WebSettingsClassic;
 import android.webkit.WebStorage;
 import android.webkit.WebView;
+import android.webkit.WebViewClassic;
 import android.webkit.WebViewClient;
 import android.widget.LinearLayout;
 
@@ -112,10 +111,10 @@
             case DUMP_AS_TEXT:
                 callback.arg1 = mDumpTopFrameAsText ? 1 : 0;
                 callback.arg2 = mDumpChildFramesAsText ? 1 : 0;
-                mWebView.documentAsText(callback);
+                mWebViewClassic.documentAsText(callback);
                 break;
             case EXT_REPR:
-                mWebView.externalRepresentation(callback);
+                mWebViewClassic.externalRepresentation(callback);
                 break;
             default:
                 finished();
@@ -144,6 +143,7 @@
 
         CookieManager.setAcceptFileSchemeCookies(true);
         mWebView = new WebView(this);
+        mWebViewClassic = WebViewClassic.fromWebView(mWebView);
         mEventSender = new WebViewEventSender(mWebView);
         mCallbackProxy = new CallbackProxy(mEventSender, this);
 
@@ -158,7 +158,7 @@
         // Expose window.gc function to JavaScript. JSC build exposes
         // this function by default, but V8 requires the flag to turn it on.
         // WebView::setJsFlags is noop in JSC build.
-        mWebView.setJsFlags("--expose_gc");
+        mWebViewClassic.setJsFlags("--expose_gc");
 
         mHandler = new AsyncHandler();
 
@@ -168,7 +168,7 @@
         }
 
         // This is asynchronous, but it gets processed by WebCore before it starts loading pages.
-        mWebView.useMockDeviceOrientation();
+        mWebViewClassic.useMockDeviceOrientation();
     }
 
     @Override
@@ -197,8 +197,6 @@
 
         mResultFile = intent.getStringExtra(RESULT_FILE);
         mTimeoutInMillis = intent.getIntExtra(TIMEOUT_IN_MILLIS, 0);
-        mGetDrawtime = intent.getBooleanExtra(GET_DRAW_TIME, false);
-        mSaveImagePath = intent.getStringExtra(SAVE_IMAGE);
         mStopOnRefError = intent.getBooleanExtra(STOP_ON_REF_ERROR, false);
         setTitle("Test " + mCurrentTestNumber + " of " + mTotalTestCount);
         float ratio = (float)mCurrentTestNumber / mTotalTestCount;
@@ -290,6 +288,7 @@
         super.onDestroy();
         mWebView.destroy();
         mWebView = null;
+        mWebViewClassic = null;
     }
 
     @Override
@@ -307,6 +306,10 @@
             return;
         }
 
+        if (mCallback != null) {
+            mCallback.dumpResult(webkitData);
+        }
+
         try {
             File parentDir = new File(mResultFile).getParentFile();
             if (!parentDir.exists()) {
@@ -531,8 +534,8 @@
 
     public void setMockDeviceOrientation(boolean canProvideAlpha, double alpha,
             boolean canProvideBeta, double beta, boolean canProvideGamma, double gamma) {
-        mWebView.setMockDeviceOrientation(canProvideAlpha, alpha, canProvideBeta, beta,
-                canProvideGamma, gamma);
+        WebViewClassic.fromWebView(mWebView).setMockDeviceOrientation(canProvideAlpha, alpha,
+                canProvideBeta, beta, canProvideGamma, gamma);
     }
 
     public void overridePreference(String key, boolean value) {
@@ -541,10 +544,10 @@
         // WebView for the main frame. EventSender suffers from the same
         // problem.
         if (WEBKIT_OFFLINE_WEB_APPLICATION_CACHE_ENABLED.equals(key)) {
-            mWebView.getSettings().setAppCacheEnabled(value);
+            mWebViewClassic.getSettings().setAppCacheEnabled(value);
         } else if (WEBKIT_USES_PAGE_CACHE_PREFERENCE_KEY.equals(key)) {
             // Cache the maximum possible number of pages.
-            mWebView.getSettings().setPageCacheCapacity(Integer.MAX_VALUE);
+            mWebViewClassic.getSettings().setPageCacheCapacity(Integer.MAX_VALUE);
         } else {
             Log.w(LOGTAG, "LayoutTestController.overridePreference(): " +
                   "Unsupported preference '" + key + "'");
@@ -552,7 +555,7 @@
     }
 
     public void setXSSAuditorEnabled (boolean flag) {
-        mWebView.getSettings().setXSSAuditorEnabled(flag);
+        mWebViewClassic.getSettings().setXSSAuditorEnabled(flag);
     }
 
     private final WebViewClient mViewClient = new WebViewClient(){
@@ -560,18 +563,6 @@
         public void onPageFinished(WebView view, String url) {
             Log.v(LOGTAG, "onPageFinished, url=" + url);
             mPageFinished = true;
-            // get page draw time
-            if (FsUtils.isTestPageUrl(url)) {
-                if (mGetDrawtime) {
-                    long[] times = new long[DRAW_RUNS];
-                    times = getDrawWebViewTime(mWebView, DRAW_RUNS);
-                    FsUtils.writeDrawTime(DRAW_TIME_LOG, url, times);
-                }
-                if (mSaveImagePath != null) {
-                    String name = FsUtils.getLastSegmentInPath(url);
-                    drawPageToFile(mSaveImagePath + "/" + name + ".png", mWebView);
-                }
-            }
 
             // Calling finished() will check if we've met all the conditions for completing
             // this test and move to the next one if we are ready. Otherwise we ask WebCore to
@@ -826,47 +817,12 @@
         mEventSender.clearTouchMetaState();
         mPageFinished = false;
         mDumpWebKitData = false;
-        mGetDrawtime = false;
-        mSaveImagePath = null;
         setDefaultWebSettings(mWebView);
         mIsGeolocationPermissionSet = false;
         mPendingGeolocationPermissionCallbacks = null;
         CookieManager.getInstance().removeAllCookie();
     }
 
-    private long[] getDrawWebViewTime(WebView view, int count) {
-        if (count == 0)
-            return null;
-        long[] ret = new long[count];
-        long start;
-        Canvas canvas = new Canvas();
-        Bitmap bitmap = Bitmap.createBitmap(view.getWidth(), view.getHeight(), Config.ARGB_8888);
-        canvas.setBitmap(bitmap);
-        for (int i = 0; i < count; i++) {
-            start = System.currentTimeMillis();
-            view.draw(canvas);
-            ret[i] = System.currentTimeMillis() - start;
-        }
-        return ret;
-    }
-
-    private void drawPageToFile(String fileName, WebView view) {
-        Canvas canvas = new Canvas();
-        Bitmap bitmap = Bitmap.createBitmap(view.getContentWidth(), view.getContentHeight(),
-                Config.ARGB_8888);
-        canvas.setBitmap(bitmap);
-        view.drawPage(canvas);
-        try {
-            FileOutputStream fos = new FileOutputStream(fileName);
-            if(!bitmap.compress(CompressFormat.PNG, 90, fos)) {
-                Log.w(LOGTAG, "Failed to compress and save image.");
-            }
-        } catch (IOException ioe) {
-            Log.e(LOGTAG, "", ioe);
-        }
-        bitmap.recycle();
-    }
-
     private boolean canMoveToNextTest() {
         return (mDumpWebKitData && mPageFinished && !mWaitUntilDone) || mTimedOut;
     }
@@ -885,11 +841,11 @@
         // single event rather than a stream of events (like what would generally happen in
         // a real use of touch events in a WebView)  and so if the WebView drops the event,
         // the test will fail as the test expects one callback for every touch it synthesizes.
-        webview.setTouchInterval(-1);
+        WebViewClassic.fromWebView(webview).setTouchInterval(-1);
     }
 
     public void setDefaultWebSettings(WebView webview) {
-        WebSettings settings = webview.getSettings();
+        WebSettingsClassic settings = WebViewClassic.fromWebView(webview).getSettings();
         settings.setAppCacheEnabled(true);
         settings.setAppCachePath(getApplicationContext().getCacheDir().getPath());
         settings.setAppCacheMaxSize(Long.MAX_VALUE);
@@ -906,6 +862,7 @@
         settings.setProperty("use_minimal_memory", "false");
     }
 
+    private WebViewClassic mWebViewClassic;
     private WebView mWebView;
     private WebViewEventSender mEventSender;
     private AsyncHandler mHandler;
@@ -917,9 +874,7 @@
     private String mResultFile;
     private int mTimeoutInMillis;
     private String mUiAutoTestPath;
-    private String mSaveImagePath;
     private BufferedReader mTestListReader;
-    private boolean mGetDrawtime;
     private int mTotalTestCount;
     private int mCurrentTestNumber;
     private boolean mStopOnRefError;
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellCallback.java b/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellCallback.java
index 55bf947..5220d579 100644
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellCallback.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellCallback.java
@@ -18,5 +18,6 @@
 
 public interface TestShellCallback {
     public void finished();
+    public void dumpResult(String webViewDump);
     public void timedOut(String url);
 }
diff --git a/tests/DumpRenderTree2/src/com/android/dumprendertree2/LayoutTestsExecutor.java b/tests/DumpRenderTree2/src/com/android/dumprendertree2/LayoutTestsExecutor.java
index f59da37..fc22472 100644
--- a/tests/DumpRenderTree2/src/com/android/dumprendertree2/LayoutTestsExecutor.java
+++ b/tests/DumpRenderTree2/src/com/android/dumprendertree2/LayoutTestsExecutor.java
@@ -41,9 +41,11 @@
 import android.webkit.SslErrorHandler;
 import android.webkit.WebChromeClient;
 import android.webkit.WebSettings;
+import android.webkit.WebSettingsClassic;
 import android.webkit.WebStorage;
 import android.webkit.WebStorage.QuotaUpdater;
 import android.webkit.WebView;
+import android.webkit.WebViewClassic;
 import android.webkit.WebViewClient;
 
 import java.lang.Thread.UncaughtExceptionHandler;
@@ -369,11 +371,12 @@
          * a real use of touch events in a WebView)  and so if the WebView drops the event,
          * the test will fail as the test expects one callback for every touch it synthesizes.
          */
-        webView.setTouchInterval(-1);
+        WebViewClassic webViewClassic = WebViewClassic.fromWebView(webView);
+        webViewClassic.setTouchInterval(-1);
 
-        webView.clearCache(true);
+        webViewClassic.clearCache(true);
 
-        WebSettings webViewSettings = webView.getSettings();
+        WebSettingsClassic webViewSettings = webViewClassic.getSettings();
         webViewSettings.setAppCacheEnabled(true);
         webViewSettings.setAppCachePath(getApplicationContext().getCacheDir().getPath());
         // Use of larger values causes unexplained AppCache database corruption.
@@ -391,7 +394,7 @@
         webViewSettings.setPageCacheCapacity(0);
 
         // This is asynchronous, but it gets processed by WebCore before it starts loading pages.
-        mCurrentWebView.useMockDeviceOrientation();
+        WebViewClassic.fromWebView(mCurrentWebView).useMockDeviceOrientation();
 
         // Must do this after setting the AppCache path.
         WebStorage.getInstance().deleteAllData();
@@ -625,10 +628,12 @@
                     String key = msg.getData().getString("key");
                     boolean value = msg.getData().getBoolean("value");
                     if (WEBKIT_OFFLINE_WEB_APPLICATION_CACHE_ENABLED.equals(key)) {
-                        mCurrentWebView.getSettings().setAppCacheEnabled(value);
+                        WebViewClassic.fromWebView(mCurrentWebView).getSettings().
+                                setAppCacheEnabled(value);
                     } else if (WEBKIT_USES_PAGE_CACHE_PREFERENCE_KEY.equals(key)) {
                         // Cache the maximum possible number of pages.
-                        mCurrentWebView.getSettings().setPageCacheCapacity(Integer.MAX_VALUE);
+                        WebViewClassic.fromWebView(mCurrentWebView).getSettings().
+                                setPageCacheCapacity(Integer.MAX_VALUE);
                     } else {
                         Log.w(LOG_TAG, "LayoutTestController.overridePreference(): " +
                               "Unsupported preference '" + key + "'");
@@ -656,7 +661,8 @@
                     break;
 
                 case MSG_SET_XSS_AUDITOR_ENABLED:
-                    mCurrentWebView.getSettings().setXSSAuditorEnabled(msg.arg1 == 1);
+                    WebViewClassic.fromWebView(mCurrentWebView).getSettings().
+                            setXSSAuditorEnabled(msg.arg1 == 1);
                     break;
 
                 case MSG_WAIT_UNTIL_DONE:
@@ -728,8 +734,8 @@
         Log.i(LOG_TAG, mCurrentTestRelativePath + ": setMockDeviceOrientation(" + canProvideAlpha +
                 ", " + alpha + ", " + canProvideBeta + ", " + beta + ", " + canProvideGamma +
                 ", " + gamma + ")");
-        mCurrentWebView.setMockDeviceOrientation(canProvideAlpha, alpha, canProvideBeta, beta,
-                canProvideGamma, gamma);
+        WebViewClassic.fromWebView(mCurrentWebView).setMockDeviceOrientation(canProvideAlpha,
+                alpha, canProvideBeta, beta, canProvideGamma, gamma);
     }
 
     public void setXSSAuditorEnabled(boolean flag) {
diff --git a/tests/DumpRenderTree2/src/com/android/dumprendertree2/TextResult.java b/tests/DumpRenderTree2/src/com/android/dumprendertree2/TextResult.java
index 3d2b98b..fd1c0ad 100644
--- a/tests/DumpRenderTree2/src/com/android/dumprendertree2/TextResult.java
+++ b/tests/DumpRenderTree2/src/com/android/dumprendertree2/TextResult.java
@@ -20,6 +20,7 @@
 import android.os.Handler;
 import android.os.Message;
 import android.webkit.WebView;
+import android.webkit.WebViewClassic;
 
 import name.fraser.neil.plaintext.diff_match_patch;
 
@@ -233,7 +234,7 @@
          */
         msg.arg1 = 1;
         msg.arg2 = mDumpChildFramesAsText ? 1 : 0;
-        webview.documentAsText(msg);
+        WebViewClassic.fromWebView(webview).documentAsText(msg);
     }
 
     @Override
diff --git a/tests/RenderScriptTests/SampleTest/Android.mk b/tests/RenderScriptTests/SampleTest/Android.mk
new file mode 100644
index 0000000..7d74c55
--- /dev/null
+++ b/tests/RenderScriptTests/SampleTest/Android.mk
@@ -0,0 +1,26 @@
+#
+# Copyright (C) 2012 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-renderscript-files-under, src)
+
+LOCAL_PACKAGE_NAME := SampleRS
+
+include $(BUILD_PACKAGE)
diff --git a/tests/RenderScriptTests/SampleTest/AndroidManifest.xml b/tests/RenderScriptTests/SampleTest/AndroidManifest.xml
new file mode 100644
index 0000000..ec115f7
--- /dev/null
+++ b/tests/RenderScriptTests/SampleTest/AndroidManifest.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+* Copyright (C) 2012 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.rs.sample">
+    <uses-sdk android:minSdkVersion="14" />
+    <application android:label="Sample Test"
+                 android:hardwareAccelerated="true">
+
+        <activity android:name="SampleRSActivity"
+                  android:label="Sample Test">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+    </application>
+</manifest>
diff --git a/tests/RenderScriptTests/SampleTest/res/drawable-nodpi/twobytwo.png b/tests/RenderScriptTests/SampleTest/res/drawable-nodpi/twobytwo.png
new file mode 100644
index 0000000..98cf963
--- /dev/null
+++ b/tests/RenderScriptTests/SampleTest/res/drawable-nodpi/twobytwo.png
Binary files differ
diff --git a/tests/RenderScriptTests/SampleTest/res/layout/rs.xml b/tests/RenderScriptTests/SampleTest/res/layout/rs.xml
new file mode 100644
index 0000000..f2a356f
--- /dev/null
+++ b/tests/RenderScriptTests/SampleTest/res/layout/rs.xml
@@ -0,0 +1,84 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2012 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+            android:orientation="vertical"
+            android:layout_width="fill_parent"
+            android:layout_height="fill_parent"
+            android:id="@+id/toplevel">
+    <ScrollView
+        android:layout_width="fill_parent"
+        android:layout_height="fill_parent">
+            <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+                android:orientation="vertical"
+                android:layout_width="fill_parent"
+                android:layout_height="fill_parent">
+            <TextView
+                        android:layout_width="match_parent"
+                        android:layout_height="wrap_content"
+                        android:textSize="8pt"
+                        android:text="@string/wraplinear"/>
+            <TextureView
+                android:id="@+id/display"
+                android:layout_width="256sp"
+                android:layout_height="256sp" />
+            <TextView
+                        android:layout_width="match_parent"
+                        android:layout_height="wrap_content"
+                        android:textSize="8pt"
+                        android:text="@string/clamplinear"/>
+            <TextureView
+                android:id="@+id/display2"
+                android:layout_width="256sp"
+                android:layout_height="256sp" />
+            <TextView
+                        android:layout_width="match_parent"
+                        android:layout_height="wrap_content"
+                        android:textSize="8pt"
+                        android:text="@string/wrapnearest"/>
+            <TextureView
+                android:id="@+id/display3"
+                android:layout_width="256sp"
+                android:layout_height="256sp" />
+            <TextView
+                        android:layout_width="match_parent"
+                        android:layout_height="wrap_content"
+                        android:textSize="8pt"
+                        android:text="@string/clampnearest"/>
+            <TextureView
+                android:id="@+id/display4"
+                android:layout_width="256sp"
+                android:layout_height="256sp" />
+            <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+                android:orientation="horizontal"
+                android:layout_width="fill_parent"
+                android:layout_height="wrap_content">
+                    <Button
+                        android:layout_width="wrap_content"
+                        android:layout_height="wrap_content"
+                        android:text="@string/benchmark"
+                        android:onClick="benchmark"/>
+                    <TextView
+                        android:id="@+id/benchmarkText"
+                        android:layout_width="match_parent"
+                        android:layout_height="wrap_content"
+                        android:textSize="8pt"
+                        android:text="@string/benchmark"/>
+            </LinearLayout>
+            </LinearLayout>
+    </ScrollView>
+</LinearLayout>
+
diff --git a/tests/RenderScriptTests/SampleTest/res/values/strings.xml b/tests/RenderScriptTests/SampleTest/res/values/strings.xml
new file mode 100644
index 0000000..a0a2499
--- /dev/null
+++ b/tests/RenderScriptTests/SampleTest/res/values/strings.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+* Copyright (C) 2012 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.
+*/
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!-- General -->
+    <skip />
+    <string name="benchmark">Benchmark</string>
+    <string name="wraplinear">Wrap Linear</string>
+    <string name="clamplinear">Clamp Linear</string>
+    <string name="wrapnearest">Wrap Nearest</string>
+    <string name="clampnearest">Clamp Nearest</string>
+</resources>
diff --git a/tests/RenderScriptTests/SampleTest/src/com/android/rs/sample/SampleRSActivity.java b/tests/RenderScriptTests/SampleTest/src/com/android/rs/sample/SampleRSActivity.java
new file mode 100644
index 0000000..cd5d53f
--- /dev/null
+++ b/tests/RenderScriptTests/SampleTest/src/com/android/rs/sample/SampleRSActivity.java
@@ -0,0 +1,163 @@
+/*
+ * Copyright (C) 2012 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.rs.sample;
+
+import android.app.Activity;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Canvas;
+import android.graphics.SurfaceTexture;
+import android.os.Bundle;
+import android.renderscript.Allocation;
+import android.renderscript.Element;
+import android.renderscript.Matrix3f;
+import android.renderscript.RenderScript;
+import android.renderscript.Sampler;
+import android.renderscript.Type;
+import android.renderscript.Type.Builder;
+import android.util.Log;
+import android.view.TextureView;
+import android.view.TextureView.SurfaceTextureListener;
+import android.view.View;
+import android.widget.ImageView;
+import android.widget.SeekBar;
+import android.widget.TextView;
+
+public class SampleRSActivity extends Activity {
+    class TextureViewUpdater implements TextureView.SurfaceTextureListener {
+        private Allocation mOutPixelsAllocation;
+        private Sampler mSampler;
+
+        TextureViewUpdater(Allocation outAlloc, Sampler sampler) {
+            mOutPixelsAllocation = outAlloc;
+            mSampler = sampler;
+        }
+
+        public void onSurfaceTextureUpdated(SurfaceTexture surface) {
+        }
+
+        public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
+            mOutPixelsAllocation.setSurfaceTexture(surface);
+        }
+
+        public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
+            mOutPixelsAllocation.setSurfaceTexture(surface);
+            filterAlloc(mOutPixelsAllocation, mSampler);
+        }
+
+        public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
+            mOutPixelsAllocation.setSurfaceTexture(null);
+            return true;
+        }
+    }
+
+    private final String TAG = "Img";
+    private Bitmap mBitmapIn;
+    private TextureView mDisplayView;
+
+    private TextView mBenchmarkResult;
+
+    private RenderScript mRS;
+    private Allocation mInPixelsAllocation;
+    private ScriptC_sample mScript;
+
+    public void onStartTrackingTouch(SeekBar seekBar) {
+    }
+
+    public void onStopTrackingTouch(SeekBar seekBar) {
+    }
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.rs);
+
+        mBitmapIn = loadBitmap(R.drawable.twobytwo);
+        mDisplayView = (TextureView) findViewById(R.id.display);
+
+        mBenchmarkResult = (TextView) findViewById(R.id.benchmarkText);
+        mBenchmarkResult.setText("Result: not run");
+
+        mRS = RenderScript.create(this);
+        mInPixelsAllocation = Allocation.createFromBitmap(mRS, mBitmapIn,
+                                                          Allocation.MipmapControl.MIPMAP_NONE,
+                                                          Allocation.USAGE_SCRIPT);
+
+        Type.Builder b = new Type.Builder(mRS, Element.RGBA_8888(mRS));
+
+        int usage = Allocation.USAGE_SCRIPT | Allocation.USAGE_IO_OUTPUT;
+
+        int outX = 32;
+        int outY = 32;
+
+        // Wrap Linear
+        Allocation outAlloc = Allocation.createTyped(mRS, b.setX(outX).setY(outY).create(), usage);
+        TextureViewUpdater updater = new TextureViewUpdater(outAlloc, Sampler.WRAP_LINEAR(mRS));
+        TextureView displayView = (TextureView) findViewById(R.id.display);
+        displayView.setSurfaceTextureListener(updater);
+
+        // Clamp Linear
+        outAlloc = Allocation.createTyped(mRS, b.setX(outX).setY(outY).create(), usage);
+        updater = new TextureViewUpdater(outAlloc, Sampler.CLAMP_LINEAR(mRS));
+        displayView = (TextureView) findViewById(R.id.display2);
+        displayView.setSurfaceTextureListener(updater);
+
+        // Wrap Nearest
+        outAlloc = Allocation.createTyped(mRS, b.setX(outX).setY(outY).create(), usage);
+        updater = new TextureViewUpdater(outAlloc, Sampler.WRAP_NEAREST(mRS));
+        displayView = (TextureView) findViewById(R.id.display3);
+        displayView.setSurfaceTextureListener(updater);
+
+        // Clamp Nearest
+        outAlloc = Allocation.createTyped(mRS, b.setX(outX).setY(outY).create(), usage);
+        updater = new TextureViewUpdater(outAlloc, Sampler.CLAMP_NEAREST(mRS));
+        displayView = (TextureView) findViewById(R.id.display4);
+        displayView.setSurfaceTextureListener(updater);
+
+        mScript = new ScriptC_sample(mRS, getResources(), R.raw.sample);
+    }
+
+    private Bitmap loadBitmap(int resource) {
+        final BitmapFactory.Options options = new BitmapFactory.Options();
+        options.inPreferredConfig = Bitmap.Config.ARGB_8888;
+        Bitmap b = BitmapFactory.decodeResource(getResources(), resource, options);
+        Bitmap b2 = Bitmap.createBitmap(b.getWidth(), b.getHeight(), b.getConfig());
+        Canvas c = new Canvas(b2);
+        c.drawBitmap(b, 0, 0, null);
+        b.recycle();
+        return b2;
+    }
+
+    private synchronized void filterAlloc(Allocation alloc, Sampler sampler) {
+        long t = java.lang.System.currentTimeMillis();
+        mScript.invoke_setSampleData(alloc, mInPixelsAllocation, sampler);
+        mScript.forEach_root(alloc);
+        alloc.ioSendOutput();
+        mRS.finish();
+        t = java.lang.System.currentTimeMillis() - t;
+        Log.i(TAG, "Filter time is: " + t + " ms");
+    }
+
+    public void benchmark(View v) {
+        /*filterAlloc();
+        long t = java.lang.System.currentTimeMillis();
+        filterAlloc();
+        t = java.lang.System.currentTimeMillis() - t;
+        mDisplayView.invalidate();
+        mBenchmarkResult.setText("Result: " + t + " ms");*/
+    }
+}
diff --git a/tests/RenderScriptTests/SampleTest/src/com/android/rs/sample/sample.rs b/tests/RenderScriptTests/SampleTest/src/com/android/rs/sample/sample.rs
new file mode 100644
index 0000000..8a027b2
--- /dev/null
+++ b/tests/RenderScriptTests/SampleTest/src/com/android/rs/sample/sample.rs
@@ -0,0 +1,172 @@
+/*
+ * Copyright (C) 2012 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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(com.android.rs.sample)
+#include "rs_graphics.rsh"
+
+static rs_allocation sourceAlloc;
+static rs_allocation destAlloc;
+static rs_sampler allocSampler;
+
+void setSampleData(rs_allocation dest, rs_allocation source, rs_sampler sampler) {
+    destAlloc = dest;
+    sourceAlloc = source;
+    allocSampler = sampler;
+}
+
+static int32_t wrapI(rs_sampler_value wrap, int32_t coord, int32_t size) {
+    if (wrap == RS_SAMPLER_WRAP) {
+        coord = coord % size;
+        if (coord < 0) {
+            coord += size;
+        }
+    }
+    return max(0, min(coord, size - 1));
+}
+
+static float2 wrap(rs_sampler_value wrapS, rs_sampler_value wrapT, float2 coord) {
+    float2 wrappedCoord;
+    float temp;
+    if (wrapS == RS_SAMPLER_WRAP) {
+        wrappedCoord.x = fract(coord.x, &temp);
+        // Make sure that non zero integer uv's map to one
+        if (wrappedCoord.x == 0.0f && coord.x != 0.0f) {
+            wrappedCoord.x = 1.0f;
+        }
+        if (wrappedCoord.x < 0.0f) {
+            wrappedCoord.x += 1.0f;
+        }
+    } else {
+        wrappedCoord.x = max(0.0f, min(coord.x, 1.0f));
+    }
+
+    if (wrapT == RS_SAMPLER_WRAP) {
+        wrappedCoord.y = fract(coord.y, &temp);
+        // Make sure that non zero integer uv's map to one
+        if (wrappedCoord.y == 0.0f && coord.y != 0.0f) {
+            wrappedCoord.y = 1.0f;
+        }
+        if (wrappedCoord.y < 0.0f) {
+            wrappedCoord.y += 1.0f;
+        }
+    } else {
+        wrappedCoord.y = max(0.0f, min(coord.y, 1.0f));
+    }
+    return wrappedCoord;
+}
+
+// Naive implementation of texture filtering for prototyping purposes
+static float4 sample(rs_allocation a, rs_sampler s, float2 uv) {
+    //rsDebug("*****************************************", 0);
+    rs_sampler_value wrapS = rsgSamplerGetWrapS(s);
+    rs_sampler_value wrapT = rsgSamplerGetWrapT(s);
+
+    rs_sampler_value sampleMin = rsgSamplerGetMinification(s);
+    rs_sampler_value sampleMag = rsgSamplerGetMagnification(s);
+
+    uv = wrap(wrapS, wrapT, uv);
+
+    int32_t sourceW = rsAllocationGetDimX(a);
+    int32_t sourceH = rsAllocationGetDimY(a);
+
+    /*rsDebug("uv", uv);
+    rsDebug("sourceW", sourceW);
+    rsDebug("sourceH", sourceH);*/
+
+    float2 dimF;
+    dimF.x = (float)(sourceW);
+    dimF.y = (float)(sourceH);
+    float2 pixelUV = uv * dimF;
+    int2 iPixel = convert_int2(pixelUV);
+    /*rsDebug("iPixelX initial", iPixel.x);
+    rsDebug("iPixelY initial", iPixel.y);*/
+
+    if (sampleMin == RS_SAMPLER_NEAREST ||
+        sampleMag == RS_SAMPLER_NEAREST) {
+        iPixel.x = wrapI(wrapS, iPixel.x, sourceW);
+        iPixel.y = wrapI(wrapT, iPixel.y, sourceH);
+        uchar4 *nearestSample = (uchar4*)rsGetElementAt(a, iPixel.x, iPixel.y);
+        return convert_float4(*nearestSample);
+    }
+
+    float2 frac = pixelUV - convert_float2(iPixel);
+
+    if (frac.x < 0.5f) {
+        iPixel.x -= 1;
+        frac.x += 0.5f;
+    } else {
+        frac.x -= 0.5f;
+    }
+    if (frac.y < 0.5f) {
+        iPixel.y -= 1;
+        frac.y += 0.5f;
+    } else {
+        frac.y -= 0.5f;
+    }
+    float2 oneMinusFrac = 1.0f - frac;
+
+    float4 weights;
+    weights.x = oneMinusFrac.x * oneMinusFrac.y;
+    weights.y = frac.x * oneMinusFrac.y;
+    weights.z = oneMinusFrac.x * frac.y;
+    weights.w = frac.x * frac.y;
+
+    uint32_t nextX = wrapI(wrapS, iPixel.x + 1, sourceW);
+    uint32_t nextY = wrapI(wrapT, iPixel.y + 1, sourceH);
+    iPixel.x = wrapI(wrapS, iPixel.x, sourceW);
+    iPixel.y = wrapI(wrapT, iPixel.y, sourceH);
+    /*rsDebug("iPixelX wrapped", iPixel.x);
+    rsDebug("iPixelY wrapped", iPixel.y);*/
+
+    uchar4 *p0c = (uchar4*)rsGetElementAt(a, iPixel.x, iPixel.y);
+    uchar4 *p1c = (uchar4*)rsGetElementAt(a, nextX, iPixel.y);
+    uchar4 *p2c = (uchar4*)rsGetElementAt(a, iPixel.x, nextY);
+    uchar4 *p3c = (uchar4*)rsGetElementAt(a, nextX, nextY);
+
+    float4 p0 = convert_float4(*p0c);
+    float4 p1 = convert_float4(*p1c);
+    float4 p2 = convert_float4(*p2c);
+    float4 p3 = convert_float4(*p3c);
+
+    float4 result = p0 * weights.x + p1 * weights.y + p2 * weights.z + p3 * weights.w;
+
+    /*rsDebug("pixelUV", pixelUV);
+    rsDebug("frac", frac);
+    rsDebug("oneMinusFrac", oneMinusFrac);
+    rsDebug("p0", p0);
+    rsDebug("p1", p1);
+    rsDebug("p2", p2);
+    rsDebug("p3", p3);
+    rsDebug("w", weights);
+    rsDebug("result", result);*/
+
+    return result;
+}
+
+void root(uchar4 *out, uint32_t x, uint32_t y) {
+
+    float destX = (float)rsAllocationGetDimX(destAlloc) - 1.0f;
+    float destY = (float)rsAllocationGetDimY(destAlloc) - 1.0f;
+
+    float2 uv;
+    uv.x = (float)x / destX;
+    uv.y = (float)y / destY;
+
+    out->xyz = convert_uchar3(sample(sourceAlloc, allocSampler, uv*2.0f).xyz);
+    out->w = 0xff;
+}
+
diff --git a/tests/TileBenchmark/src/com/test/tilebenchmark/ProfiledWebView.java b/tests/TileBenchmark/src/com/test/tilebenchmark/ProfiledWebView.java
index a38ac25..87baf76 100644
--- a/tests/TileBenchmark/src/com/test/tilebenchmark/ProfiledWebView.java
+++ b/tests/TileBenchmark/src/com/test/tilebenchmark/ProfiledWebView.java
@@ -20,8 +20,9 @@
 import android.os.CountDownTimer;
 import android.util.AttributeSet;
 import android.util.Log;
-import android.webkit.WebSettings;
+import android.webkit.WebSettingsClassic;
 import android.webkit.WebView;
+import android.webkit.WebViewClassic;
 import android.widget.Toast;
 
 import java.util.ArrayList;
@@ -29,7 +30,7 @@
 import com.test.tilebenchmark.ProfileActivity.ProfileCallback;
 import com.test.tilebenchmark.RunData.TileData;
 
-public class ProfiledWebView extends WebView {
+public class ProfiledWebView extends WebView implements WebViewClassic.PageSwapDelegate {
     private static final String LOGTAG = "ProfiledWebView";
 
     private int mSpeed;
@@ -80,7 +81,7 @@
     }
 
     public void init(Context c) {
-        WebSettings settings = getSettings();
+        WebSettingsClassic settings = getWebViewClassic().getSettings();
         settings.setJavaScriptEnabled(true);
         settings.setSupportZoom(true);
         settings.setEnableSmoothTransition(true);
@@ -118,7 +119,7 @@
         mCallback = callback;
         mIsTesting = false;
         mIsScrolling = false;
-        WebSettings settings = getSettings();
+        WebSettingsClassic settings = getWebViewClassic().getSettings();
         settings.setProperty("tree_updates", "0");
 
 
@@ -134,7 +135,7 @@
                     // invalidate all content, and kick off redraw
                     Log.d("ProfiledWebView",
                             "kicking off test with callback registration, and tile discard...");
-                    discardAllTextures();
+                    getWebViewClassic().discardAllTextures();
                     invalidate();
                     mIsScrolling = true;
                     mContentInvalMillis = System.currentTimeMillis();
@@ -142,30 +143,29 @@
             }.start();
         } else {
             mIsTesting = true;
-            tileProfilingStart();
+            getWebViewClassic().tileProfilingStart();
         }
     }
 
     /*
      * Called after the manual contentInvalidateAll, after the tiles have all
      * been redrawn.
+     * From PageSwapDelegate.
      */
     @Override
-    protected void pageSwapCallback(boolean startAnim) {
-        super.pageSwapCallback(startAnim);
-
+    public void onPageSwapOccurred(boolean startAnim) {
         if (!mIsTesting && mIsScrolling) {
             // kick off testing
             mContentInvalMillis = System.currentTimeMillis() - mContentInvalMillis;
             Log.d("ProfiledWebView", "REDRAW TOOK " + mContentInvalMillis + "millis");
             mIsTesting = true;
             invalidate(); // ensure a redraw so that auto-scrolling can occur
-            tileProfilingStart();
+            getWebViewClassic().tileProfilingStart();
         }
     }
 
     private double animFramerate() {
-        WebSettings settings = getSettings();
+        WebSettingsClassic settings = getWebViewClassic().getSettings();
         String updatesString = settings.getProperty("tree_updates");
         int updates = (updatesString == null) ? -1 : Integer.parseInt(updatesString);
 
@@ -180,7 +180,7 @@
     }
 
     public void setDoubleBuffering(boolean useDoubleBuffering) {
-        WebSettings settings = getSettings();
+        WebSettingsClassic settings = getWebViewClassic().getSettings();
         settings.setProperty("use_double_buffering", useDoubleBuffering ? "true" : "false");
     }
 
@@ -188,15 +188,15 @@
      * Called once the page has stopped scrolling
      */
     public void stopScrollTest() {
-        tileProfilingStop();
+        getWebViewClassic().tileProfilingStop();
         mIsTesting = false;
 
         if (mCallback == null) {
-            tileProfilingClear();
+            getWebViewClassic().tileProfilingClear();
             return;
         }
 
-        RunData data = new RunData(super.tileProfilingNumFrames());
+        RunData data = new RunData(getWebViewClassic().tileProfilingNumFrames());
         // record the time spent (before scrolling) rendering the page
         data.singleStats.put(getResources().getString(R.string.render_millis),
                 (double)mContentInvalMillis);
@@ -209,24 +209,24 @@
 
         for (int frame = 0; frame < data.frames.length; frame++) {
             data.frames[frame] = new TileData[
-                    tileProfilingNumTilesInFrame(frame)];
+                    getWebViewClassic().tileProfilingNumTilesInFrame(frame)];
             for (int tile = 0; tile < data.frames[frame].length; tile++) {
-                int left = tileProfilingGetInt(frame, tile, "left");
-                int top = tileProfilingGetInt(frame, tile, "top");
-                int right = tileProfilingGetInt(frame, tile, "right");
-                int bottom = tileProfilingGetInt(frame, tile, "bottom");
+                int left = getWebViewClassic().tileProfilingGetInt(frame, tile, "left");
+                int top = getWebViewClassic().tileProfilingGetInt(frame, tile, "top");
+                int right = getWebViewClassic().tileProfilingGetInt(frame, tile, "right");
+                int bottom = getWebViewClassic().tileProfilingGetInt(frame, tile, "bottom");
 
-                boolean isReady = super.tileProfilingGetInt(
+                boolean isReady = getWebViewClassic().tileProfilingGetInt(
                         frame, tile, "isReady") == 1;
-                int level = tileProfilingGetInt(frame, tile, "level");
+                int level = getWebViewClassic().tileProfilingGetInt(frame, tile, "level");
 
-                float scale = tileProfilingGetFloat(frame, tile, "scale");
+                float scale = getWebViewClassic().tileProfilingGetFloat(frame, tile, "scale");
 
                 data.frames[frame][tile] = data.new TileData(left, top, right, bottom,
                         isReady, level, scale);
             }
         }
-        tileProfilingClear();
+        getWebViewClassic().tileProfilingClear();
 
         mCallback.profileCallback(data);
     }
@@ -244,4 +244,8 @@
     public void setAutoScrollSpeed(int speedInt) {
         mSpeed = speedInt;
     }
+
+    public WebViewClassic getWebViewClassic() {
+        return WebViewClassic.fromWebView(this);
+    }
 }
diff --git a/tools/aapt/ResourceTable.cpp b/tools/aapt/ResourceTable.cpp
index 0c0b2ea..df6abe8 100644
--- a/tools/aapt/ResourceTable.cpp
+++ b/tools/aapt/ResourceTable.cpp
@@ -2304,10 +2304,8 @@
 
         const char16_t* end = name + nameLen;
         const char16_t* pos = name;
-        bool failed = false;
-        while (pos < end && !failed) {
+        while (pos < end) {
             const char16_t* start = pos;
-            end++;
             while (pos < end && *pos != '|') {
                 pos++;
             }
@@ -2333,9 +2331,7 @@
                 // Didn't find this flag identifier.
                 return false;
             }
-            if (pos < end) {
-                pos++;
-            }
+            pos++;
         }
 
         return true;
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindow.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindow.java
index 79606a4..965f553 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindow.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindow.java
@@ -39,6 +39,7 @@
     public void dispatchGetNewSurface() throws RemoteException {
         // pass for now.
     }
+
     @Override
     public void executeCommand(String arg0, String arg1, ParcelFileDescriptor arg2)
             throws RemoteException {
@@ -52,6 +53,10 @@
     }
 
     @Override
+    public void dispatchScreenStatus(boolean on) throws RemoteException {
+    }
+
+    @Override
     public void windowFocusChanged(boolean arg0, boolean arg1) throws RemoteException {
         // pass for now.
     }
diff --git a/wifi/java/android/net/wifi/WifiConfigStore.java b/wifi/java/android/net/wifi/WifiConfigStore.java
index 8305714..46ad036 100644
--- a/wifi/java/android/net/wifi/WifiConfigStore.java
+++ b/wifi/java/android/net/wifi/WifiConfigStore.java
@@ -286,7 +286,10 @@
                     config.status = Status.CURRENT;
                     break;
                 case DISCONNECTED:
-                    config.status = Status.ENABLED;
+                    //If network is already disabled, keep the status
+                    if (config.status == Status.CURRENT) {
+                        config.status = Status.ENABLED;
+                    }
                     break;
                 default:
                     //do nothing, retain the existing state
@@ -906,7 +909,7 @@
                         }
                     }
                 } else {
-                    loge("Missing id while parsing configuration");
+                    if (DBG) log("Missing id while parsing configuration");
                 }
             }
         } catch (EOFException ignore) {
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index bdee12a..d746810 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -1069,15 +1069,22 @@
     public static final int START_WPS_SUCCEEDED             = BASE + 11;
     /** @hide */
     public static final int WPS_FAILED                      = BASE + 12;
-   /** @hide */
+    /** @hide */
     public static final int WPS_COMPLETED                   = BASE + 13;
 
     /** @hide */
-    public static final int DISABLE_NETWORK                 = BASE + 14;
+    public static final int CANCEL_WPS                      = BASE + 14;
     /** @hide */
-    public static final int DISABLE_NETWORK_FAILED          = BASE + 15;
+    public static final int CANCEL_WPS_FAILED               = BASE + 15;
     /** @hide */
-    public static final int DISABLE_NETWORK_SUCCEEDED       = BASE + 16;
+    public static final int CANCEL_WPS_SUCCEDED             = BASE + 16;
+
+    /** @hide */
+    public static final int DISABLE_NETWORK                 = BASE + 17;
+    /** @hide */
+    public static final int DISABLE_NETWORK_FAILED          = BASE + 18;
+    /** @hide */
+    public static final int DISABLE_NETWORK_SUCCEEDED       = BASE + 19;
 
     /* For system use only */
     /** @hide */
@@ -1091,14 +1098,14 @@
      * Indicates that the operation failed due to an internal error.
      * @hide
      */
-    public static final int ERROR               = 0;
+    public static final int ERROR                       = 0;
 
     /**
      * Passed with {@link ActionListener#onFailure}.
      * Indicates that the operation is already in progress
      * @hide
      */
-    public static final int IN_PROGRESS         = 1;
+    public static final int IN_PROGRESS                 = 1;
 
     /**
      * Passed with {@link ActionListener#onFailure}.
@@ -1106,11 +1113,19 @@
      * unable to service the request
      * @hide
      */
-    public static final int BUSY                = 2;
+    public static final int BUSY                        = 2;
 
     /* WPS specific errors */
     /** WPS overlap detected {@hide} */
-    public static final int WPS_OVERLAP_ERROR   = 3;
+    public static final int WPS_OVERLAP_ERROR           = 3;
+    /** WEP on WPS is prohibited {@hide} */
+    public static final int WPS_WEP_PROHIBITED          = 4;
+    /** TKIP only prohibited {@hide} */
+    public static final int WPS_TKIP_ONLY_PROHIBITED    = 5;
+    /** Authentication failure on WPS {@hide} */
+    public static final int WPS_AUTH_FAILURE            = 6;
+    /** WPS timed out {@hide} */
+    public static final int WPS_TIMED_OUT               = 7;
 
     /** Interface for callback invocation when framework channel is lost {@hide} */
     public interface ChannelListener {
@@ -1165,6 +1180,7 @@
         private SparseArray<Object> mListenerMap = new SparseArray<Object>();
         private Object mListenerMapLock = new Object();
         private int mListenerKey = 0;
+        private static final int INVALID_KEY = -1;
 
         AsyncChannel mAsyncChannel;
         WifiHandler mHandler;
@@ -1187,6 +1203,7 @@
                     case WifiManager.CONNECT_NETWORK_FAILED:
                     case WifiManager.FORGET_NETWORK_FAILED:
                     case WifiManager.SAVE_NETWORK_FAILED:
+                    case WifiManager.CANCEL_WPS_FAILED:
                     case WifiManager.DISABLE_NETWORK_FAILED:
                         if (listener != null) {
                             ((ActionListener) listener).onFailure(message.arg1);
@@ -1196,6 +1213,7 @@
                     case WifiManager.CONNECT_NETWORK_SUCCEEDED:
                     case WifiManager.FORGET_NETWORK_SUCCEEDED:
                     case WifiManager.SAVE_NETWORK_SUCCEEDED:
+                    case WifiManager.CANCEL_WPS_SUCCEDED:
                     case WifiManager.DISABLE_NETWORK_SUCCEEDED:
                         if (listener != null) {
                             ((ActionListener) listener).onSuccess();
@@ -1229,16 +1247,19 @@
         }
 
         int putListener(Object listener) {
-            if (listener == null) return 0;
+            if (listener == null) return INVALID_KEY;
             int key;
             synchronized (mListenerMapLock) {
-                key = mListenerKey++;
+                do {
+                    key = mListenerKey++;
+                } while (key == INVALID_KEY);
                 mListenerMap.put(key, listener);
             }
             return key;
         }
 
         Object removeListener(int key) {
+            if (key == INVALID_KEY) return null;
             synchronized (mListenerMapLock) {
                 Object listener = mListenerMap.get(key);
                 mListenerMap.remove(key);
@@ -1289,7 +1310,10 @@
         if (c == null) throw new IllegalArgumentException("Channel needs to be initialized");
         if (config == null) throw new IllegalArgumentException("config cannot be null");
 
-        c.mAsyncChannel.sendMessage(CONNECT_NETWORK, 0, c.putListener(listener), config);
+        // Use INVALID_NETWORK_ID for arg1 when passing a config object
+        // arg1 is used to pass network id when the network already exists
+        c.mAsyncChannel.sendMessage(CONNECT_NETWORK, WifiConfiguration.INVALID_NETWORK_ID,
+                c.putListener(listener), config);
     }
 
     /**
@@ -1385,6 +1409,21 @@
     }
 
     /**
+     * Cancel any ongoing Wi-fi Protected Setup
+     *
+     * @param c is the channel created at {@link #initialize}
+     * @param listener for callbacks on success or failure. Can be null.
+     * @hide
+     */
+    public void cancelWps(Channel c, ActionListener listener) {
+        if (c == null) throw new IllegalArgumentException("Channel needs to be initialized");
+
+        c.mAsyncChannel.sendMessage(CANCEL_WPS, 0, c.putListener(listener));
+    }
+
+
+
+    /**
      * Get a reference to WifiService handler. This is used by a client to establish
      * an AsyncChannel communication with WifiService
      *
diff --git a/wifi/java/android/net/wifi/WifiMonitor.java b/wifi/java/android/net/wifi/WifiMonitor.java
index e1cfba3..c406fa0 100644
--- a/wifi/java/android/net/wifi/WifiMonitor.java
+++ b/wifi/java/android/net/wifi/WifiMonitor.java
@@ -65,7 +65,20 @@
 
     /* WPS events */
     private static final String WPS_SUCCESS_STR = "WPS-SUCCESS";
+
+    /* Format: WPS-FAIL msg=%d [config_error=%d] [reason=%d (%s)] */
     private static final String WPS_FAIL_STR    = "WPS-FAIL";
+    private static final String WPS_FAIL_PATTERN =
+            "WPS-FAIL msg=\\d+(?: config_error=(\\d+))?(?: reason=(\\d+))?";
+
+    /* config error code values for config_error=%d */
+    private static final int CONFIG_MULTIPLE_PBC_DETECTED = 12;
+    private static final int CONFIG_AUTH_FAILURE = 18;
+
+    /* reason code values for reason=%d */
+    private static final int REASON_TKIP_ONLY_PROHIBITED = 1;
+    private static final int REASON_WEP_PROHIBITED = 2;
+
     private static final String WPS_OVERLAP_STR = "WPS-OVERLAP-DETECTED";
     private static final String WPS_TIMEOUT_STR = "WPS-TIMEOUT";
 
@@ -316,7 +329,7 @@
                     } else if (eventStr.startsWith(WPS_SUCCESS_STR)) {
                         mStateMachine.sendMessage(WPS_SUCCESS_EVENT);
                     } else if (eventStr.startsWith(WPS_FAIL_STR)) {
-                        mStateMachine.sendMessage(WPS_FAIL_EVENT);
+                        handleWpsFailEvent(eventStr);
                     } else if (eventStr.startsWith(WPS_OVERLAP_STR)) {
                         mStateMachine.sendMessage(WPS_OVERLAP_EVENT);
                     } else if (eventStr.startsWith(WPS_TIMEOUT_STR)) {
@@ -458,6 +471,43 @@
             }
         }
 
+        private void handleWpsFailEvent(String dataString) {
+            final Pattern p = Pattern.compile(WPS_FAIL_PATTERN);
+            Matcher match = p.matcher(dataString);
+            if (match.find()) {
+                String cfgErr = match.group(1);
+                String reason = match.group(2);
+
+                if (reason != null) {
+                    switch(Integer.parseInt(reason)) {
+                        case REASON_TKIP_ONLY_PROHIBITED:
+                            mStateMachine.sendMessage(mStateMachine.obtainMessage(WPS_FAIL_EVENT,
+                                    WifiManager.WPS_TKIP_ONLY_PROHIBITED, 0));
+                            return;
+                        case REASON_WEP_PROHIBITED:
+                            mStateMachine.sendMessage(mStateMachine.obtainMessage(WPS_FAIL_EVENT,
+                                    WifiManager.WPS_WEP_PROHIBITED, 0));
+                            return;
+                    }
+                }
+                if (cfgErr != null) {
+                    switch(Integer.parseInt(cfgErr)) {
+                        case CONFIG_AUTH_FAILURE:
+                            mStateMachine.sendMessage(mStateMachine.obtainMessage(WPS_FAIL_EVENT,
+                                    WifiManager.WPS_AUTH_FAILURE, 0));
+                            return;
+                        case CONFIG_MULTIPLE_PBC_DETECTED:
+                            mStateMachine.sendMessage(mStateMachine.obtainMessage(WPS_FAIL_EVENT,
+                                    WifiManager.WPS_OVERLAP_ERROR, 0));
+                            return;
+                    }
+                }
+            }
+            //For all other errors, return a generic internal error
+            mStateMachine.sendMessage(mStateMachine.obtainMessage(WPS_FAIL_EVENT,
+                    WifiManager.ERROR, 0));
+        }
+
         /**
          * Handle p2p events
          */
diff --git a/wifi/java/android/net/wifi/WifiNative.java b/wifi/java/android/net/wifi/WifiNative.java
index e3dd3a6..ecd4073 100644
--- a/wifi/java/android/net/wifi/WifiNative.java
+++ b/wifi/java/android/net/wifi/WifiNative.java
@@ -388,27 +388,37 @@
         return doStringCommand("SIGNAL_POLL");
     }
 
-    public boolean startWpsPbc() {
-        return doBooleanCommand("WPS_PBC");
-    }
-
     public boolean startWpsPbc(String bssid) {
-        return doBooleanCommand("WPS_PBC " + bssid);
+        if (TextUtils.isEmpty(bssid)) {
+            return doBooleanCommand("WPS_PBC");
+        } else {
+            return doBooleanCommand("WPS_PBC " + bssid);
+        }
     }
 
     public boolean startWpsPinKeypad(String pin) {
+        if (TextUtils.isEmpty(pin)) return false;
         return doBooleanCommand("WPS_PIN any " + pin);
     }
 
     public String startWpsPinDisplay(String bssid) {
-        return doStringCommand("WPS_PIN " + bssid);
+        if (TextUtils.isEmpty(bssid)) {
+            return doStringCommand("WPS_PIN any");
+        } else {
+            return doStringCommand("WPS_PIN " + bssid);
+        }
     }
 
     /* Configures an access point connection */
     public boolean startWpsRegistrar(String bssid, String pin) {
+        if (TextUtils.isEmpty(bssid) || TextUtils.isEmpty(pin)) return false;
         return doBooleanCommand("WPS_REG " + bssid + " " + pin);
     }
 
+    public boolean cancelWps() {
+        return doBooleanCommand("WPS_CANCEL");
+    }
+
     public boolean setPersistentReconnect(boolean enabled) {
         int value = (enabled == true) ? 1 : 0;
         return doBooleanCommand("SET persistent_reconnect " + value);
@@ -539,7 +549,7 @@
     }
 
     public boolean p2pGroupRemove(String iface) {
-        if (iface == null) return false;
+        if (TextUtils.isEmpty(iface)) return false;
         return doBooleanCommand("P2P_GROUP_REMOVE " + iface);
     }
 
@@ -549,7 +559,7 @@
 
     /* Invite a peer to a group */
     public boolean p2pInvite(WifiP2pGroup group, String deviceAddress) {
-        if (deviceAddress == null) return false;
+        if (TextUtils.isEmpty(deviceAddress)) return false;
 
         if (group == null) {
             return doBooleanCommand("P2P_INVITE peer=" + deviceAddress);
@@ -561,19 +571,19 @@
 
     /* Reinvoke a persistent connection */
     public boolean p2pReinvoke(int netId, String deviceAddress) {
-        if (deviceAddress == null || netId < 0) return false;
+        if (TextUtils.isEmpty(deviceAddress) || netId < 0) return false;
 
         return doBooleanCommand("P2P_INVITE persistent=" + netId + " peer=" + deviceAddress);
     }
 
 
     public String p2pGetInterfaceAddress(String deviceAddress) {
-        if (deviceAddress == null) return null;
+        if (TextUtils.isEmpty(deviceAddress)) return null;
 
         //  "p2p_peer deviceAddress" returns a multi-line result containing
         //      intended_addr=fa:7b:7a:42:82:13
         String peerInfo = p2pPeer(deviceAddress);
-        if (peerInfo == null) return null;
+        if (TextUtils.isEmpty(peerInfo)) return null;
         String[] tokens= peerInfo.split("\n");
 
         for (String token : tokens) {
diff --git a/wifi/java/android/net/wifi/WifiStateMachine.java b/wifi/java/android/net/wifi/WifiStateMachine.java
index d6988cd..843620c 100644
--- a/wifi/java/android/net/wifi/WifiStateMachine.java
+++ b/wifi/java/android/net/wifi/WifiStateMachine.java
@@ -1844,6 +1844,10 @@
                     replyToMessage(message, WifiManager.WPS_FAILED,
                             WifiManager.BUSY);
                     break;
+                case WifiManager.CANCEL_WPS:
+                    replyToMessage(message, WifiManager.CANCEL_WPS_FAILED,
+                            WifiManager.BUSY);
+                    break;
                 case WifiManager.DISABLE_NETWORK:
                     replyToMessage(message, WifiManager.DISABLE_NETWORK_FAILED,
                             WifiManager.BUSY);
@@ -3321,8 +3325,15 @@
                     transitionTo(mDisconnectedState);
                     break;
                 case WifiMonitor.WPS_FAIL_EVENT:
+                    //arg1 has the reason for the failure
+                    replyToMessage(mSourceMessage, WifiManager.WPS_FAILED, message.arg1);
+                    mSourceMessage.recycle();
+                    mSourceMessage = null;
+                    transitionTo(mDisconnectedState);
+                    break;
                 case WifiMonitor.WPS_TIMEOUT_EVENT:
-                    replyToMessage(mSourceMessage, WifiManager.WPS_FAILED, WifiManager.ERROR);
+                    replyToMessage(mSourceMessage, WifiManager.WPS_FAILED,
+                            WifiManager.WPS_TIMED_OUT);
                     mSourceMessage.recycle();
                     mSourceMessage = null;
                     transitionTo(mDisconnectedState);
@@ -3330,6 +3341,14 @@
                 case WifiManager.START_WPS:
                     replyToMessage(message, WifiManager.WPS_FAILED, WifiManager.IN_PROGRESS);
                     break;
+                case WifiManager.CANCEL_WPS:
+                    if (mWifiNative.cancelWps()) {
+                        replyToMessage(message, WifiManager.CANCEL_WPS_SUCCEDED);
+                    } else {
+                        replyToMessage(message, WifiManager.CANCEL_WPS_FAILED, WifiManager.ERROR);
+                    }
+                    transitionTo(mDisconnectedState);
+                    break;
                 /* Defer all commands that can cause connections to a different network
                  * or put the state machine out of connect mode
                  */
@@ -3346,6 +3365,11 @@
                     if (DBG) log("Network connection lost");
                     handleNetworkDisconnect();
                     break;
+                case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT:
+                    //Throw away supplicant state changes when WPS is running.
+                    //We will start getting supplicant state changes once we get
+                    //a WPS success or failure
+                    break;
                 default:
                     return NOT_HANDLED;
             }
@@ -3353,6 +3377,7 @@
             return HANDLED;
         }
 
+        @Override
         public void exit() {
             mWifiConfigStore.enableAllNetworks();
             mWifiConfigStore.loadConfiguredNetworks();
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pService.java b/wifi/java/android/net/wifi/p2p/WifiP2pService.java
index 5b0e424..399dc9d 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pService.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pService.java
@@ -996,7 +996,7 @@
                     break;
                 case PEER_CONNECTION_USER_ACCEPT:
                     if (mSavedPeerConfig.wps.setup == WpsInfo.PBC) {
-                        mWifiNative.startWpsPbc();
+                        mWifiNative.startWpsPbc(null);
                     } else {
                         mWifiNative.startWpsPinKeypad(mSavedPeerConfig.wps.pin);
                     }