am 17f9e778: (-s ours) am 5132d626: (-s ours) Merge jb-mr1-dev into aosp/master - do not merge

* commit '17f9e778a5f22bce8df9bed83b9b0d7abf72e9a9':
  Update the content shell command's usage instructions.
diff --git a/Android.mk b/Android.mk
index d38150f..c9bd4fd 100644
--- a/Android.mk
+++ b/Android.mk
@@ -607,7 +607,31 @@
 # $(gen), i.e. framework.aidl, is also needed while building against the current stub.
 $(full_target): $(framework_built) $(gen)
 
-droidcore: doc-comment-check-docs
+# Run this for checkbuild
+.PHONY: checkbuild
+checkbuild: doc-comment-check-docs
+
+# ====  static html in the pdk ==================================
+include $(CLEAR_VARS)
+
+LOCAL_INTERMEDIATE_SOURCES:=$(framework_docs_LOCAL_INTERMEDIATE_SOURCES)
+LOCAL_JAVA_LIBRARIES:=$(framework_docs_LOCAL_JAVA_LIBRARIES)
+LOCAL_MODULE_CLASS:=$(framework_docs_LOCAL_MODULE_CLASS)
+LOCAL_DROIDDOC_SOURCE_PATH:=$(framework_docs_LOCAL_DROIDDOC_SOURCE_PATH)
+LOCAL_DROIDDOC_HTML_DIR:=../../vendor/pdk/data/google/docs
+LOCAL_ADDITIONAL_JAVA_DIR:=$(framework_docs_LOCAL_ADDITIONAL_JAVA_DIR)
+LOCAL_ADDITIONAL_DEPENDENCIES:=$(framework_docs_LOCAL_ADDITIONAL_DEPENDENCIES)
+
+LOCAL_MODULE := offline-pdk
+
+LOCAL_DROIDDOC_OPTIONS:=\
+		-hdf android.whichdoc offline \
+		-hdf android.whichmodule $(LOCAL_MODULE)
+
+LOCAL_DROIDDOC_CUSTOM_TEMPLATE_DIR:=build/tools/droiddoc/templates-pdk
+
+include $(BUILD_DROIDDOC)
+
 
 # ====  static html in the sdk ==================================
 include $(CLEAR_VARS)
diff --git a/CleanSpec.mk b/CleanSpec.mk
index 14b3681..53345f9 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -137,6 +137,7 @@
 $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/ImageProcessing_intermediates)
 $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/ImageProcessing2_intermediates)
 $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/ImageProcessing_intermediates)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/media/audio/ui/*.ogg)
 # ************************************************
 # NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
 # ************************************************
diff --git a/api/current.txt b/api/current.txt
index 6b893d5..a0436c3 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -12575,7 +12575,7 @@
     method public int getUid();
   }
 
-  public class DhcpInfo implements android.os.Parcelable {
+  public deprecated class DhcpInfo implements android.os.Parcelable {
     ctor public DhcpInfo();
     method public int describeContents();
     method public void writeToParcel(android.os.Parcel, int);
@@ -13442,7 +13442,7 @@
     method public boolean enableNetwork(int, boolean);
     method public java.util.List<android.net.wifi.WifiConfiguration> getConfiguredNetworks();
     method public android.net.wifi.WifiInfo getConnectionInfo();
-    method public android.net.DhcpInfo getDhcpInfo();
+    method public deprecated android.net.DhcpInfo getDhcpInfo();
     method public java.util.List<android.net.wifi.ScanResult> getScanResults();
     method public int getWifiState();
     method public boolean isWifiEnabled();
@@ -19168,6 +19168,7 @@
     method public void copyFrom(byte[]);
     method public void copyFrom(float[]);
     method public void copyFrom(android.graphics.Bitmap);
+    method public void copyFrom(android.renderscript.Allocation);
     method public void copyFromUnchecked(int[]);
     method public void copyFromUnchecked(short[]);
     method public void copyFromUnchecked(byte[]);
@@ -19200,6 +19201,7 @@
     method public void ioReceive();
     method public void ioSend();
     method public synchronized void resize(int);
+    method public synchronized void resize(int, int);
     method public void setFromFieldPacker(int, android.renderscript.FieldPacker);
     method public void setFromFieldPacker(int, int, android.renderscript.FieldPacker);
     method public void setSurface(android.view.Surface);
@@ -20545,6 +20547,7 @@
     method public java.util.List<android.speech.tts.TextToSpeech.EngineInfo> getEngines();
     method public java.util.Set<java.lang.String> getFeatures(java.util.Locale);
     method public java.util.Locale getLanguage();
+    method public static int getMaxSpeechInputLength();
     method public int isLanguageAvailable(java.util.Locale);
     method public boolean isSpeaking();
     method public int playEarcon(java.lang.String, int, java.util.HashMap<java.lang.String, java.lang.String>);
@@ -23429,6 +23432,17 @@
     method public void set(T, V);
   }
 
+  public class PropertyValueModel extends android.util.ValueModel {
+    method public T get();
+    method public H getHost();
+    method public android.util.Property<H, T> getProperty();
+    method public java.lang.Class<T> getType();
+    method public static android.util.PropertyValueModel<H, T> of(H, android.util.Property<H, T>);
+    method public static android.util.PropertyValueModel<H, T> of(H, java.lang.Class<T>, java.lang.String);
+    method public static android.util.PropertyValueModel of(java.lang.Object, java.lang.String);
+    method public void set(T);
+  }
+
   public class SparseArray implements java.lang.Cloneable {
     ctor public SparseArray();
     ctor public SparseArray(int);
@@ -23484,6 +23498,24 @@
     method public int valueAt(int);
   }
 
+  public class SparseLongArray implements java.lang.Cloneable {
+    ctor public SparseLongArray();
+    ctor public SparseLongArray(int);
+    method public void append(int, long);
+    method public void clear();
+    method public android.util.SparseLongArray clone();
+    method public void delete(int);
+    method public long get(int);
+    method public long get(int, long);
+    method public int indexOfKey(int);
+    method public int indexOfValue(long);
+    method public int keyAt(int);
+    method public void put(int, long);
+    method public void removeAt(int);
+    method public int size();
+    method public long valueAt(int);
+  }
+
   public class StateSet {
     method public static java.lang.String dump(int[]);
     method public static boolean isWildCard(int[]);
@@ -23577,6 +23609,14 @@
     field public int type;
   }
 
+  public abstract class ValueModel {
+    ctor protected ValueModel();
+    method public abstract T get();
+    method public abstract java.lang.Class<T> getType();
+    method public abstract void set(T);
+    field public static final android.util.ValueModel EMPTY;
+  }
+
   public class Xml {
     method public static android.util.AttributeSet asAttributeSet(org.xmlpull.v1.XmlPullParser);
     method public static android.util.Xml.Encoding findEncodingByName(java.lang.String) throws java.io.UnsupportedEncodingException;
@@ -25028,6 +25068,7 @@
     method public boolean isHorizontalScrollBarEnabled();
     method public boolean isHovered();
     method public boolean isInEditMode();
+    method public boolean isInLayout();
     method public boolean isInTouchMode();
     method public boolean isLayoutRequested();
     method public boolean isLongClickable();
@@ -25574,6 +25615,7 @@
     method public android.view.View getFocusedChild();
     method public android.view.animation.LayoutAnimationController getLayoutAnimation();
     method public android.view.animation.Animation.AnimationListener getLayoutAnimationListener();
+    method public int getLayoutMode();
     method public android.animation.LayoutTransition getLayoutTransition();
     method public int getPersistentDrawingCache();
     method public int indexOfChild(android.view.View);
@@ -25621,6 +25663,7 @@
     method public void setDescendantFocusability(int);
     method public void setLayoutAnimation(android.view.animation.LayoutAnimationController);
     method public void setLayoutAnimationListener(android.view.animation.Animation.AnimationListener);
+    method public void setLayoutMode(int);
     method public void setLayoutTransition(android.animation.LayoutTransition);
     method public void setMotionEventSplittingEnabled(boolean);
     method public void setOnHierarchyChangeListener(android.view.ViewGroup.OnHierarchyChangeListener);
@@ -25636,6 +25679,8 @@
     field public static final int FOCUS_AFTER_DESCENDANTS = 262144; // 0x40000
     field public static final int FOCUS_BEFORE_DESCENDANTS = 131072; // 0x20000
     field public static final int FOCUS_BLOCK_DESCENDANTS = 393216; // 0x60000
+    field public static final int LAYOUT_MODE_CLIP_BOUNDS = 0; // 0x0
+    field public static final int LAYOUT_MODE_OPTICAL_BOUNDS = 1; // 0x1
     field public static final int PERSISTENT_ALL_CACHES = 3; // 0x3
     field public static final int PERSISTENT_ANIMATION_CACHE = 1; // 0x1
     field public static final int PERSISTENT_NO_CACHE = 0; // 0x0
@@ -27967,10 +28012,12 @@
     method public abstract void onSelectedDayChange(android.widget.CalendarView, int, int, int);
   }
 
-  public class CheckBox extends android.widget.CompoundButton {
+  public class CheckBox extends android.widget.CompoundButton implements android.widget.ValueEditor {
     ctor public CheckBox(android.content.Context);
     ctor public CheckBox(android.content.Context, android.util.AttributeSet);
     ctor public CheckBox(android.content.Context, android.util.AttributeSet, int);
+    method public android.util.ValueModel<java.lang.Boolean> getValueModel();
+    method public void setValueModel(android.util.ValueModel<java.lang.Boolean>);
   }
 
   public abstract interface Checkable {
@@ -28143,14 +28190,16 @@
     method public void setSize(int, int);
   }
 
-  public class EditText extends android.widget.TextView {
+  public class EditText extends android.widget.TextView implements android.widget.ValueEditor {
     ctor public EditText(android.content.Context);
     ctor public EditText(android.content.Context, android.util.AttributeSet);
     ctor public EditText(android.content.Context, android.util.AttributeSet, int);
     method public void extendSelection(int);
+    method public android.util.ValueModel<java.lang.CharSequence> getValueModel();
     method public void selectAll();
     method public void setSelection(int, int);
     method public void setSelection(int);
+    method public void setValueModel(android.util.ValueModel<java.lang.CharSequence>);
   }
 
   public abstract interface ExpandableListAdapter {
@@ -29175,11 +29224,13 @@
     method public abstract java.lang.Object[] getSections();
   }
 
-  public class SeekBar extends android.widget.AbsSeekBar {
+  public class SeekBar extends android.widget.AbsSeekBar implements android.widget.ValueEditor {
     ctor public SeekBar(android.content.Context);
     ctor public SeekBar(android.content.Context, android.util.AttributeSet);
     ctor public SeekBar(android.content.Context, android.util.AttributeSet, int);
+    method public android.util.ValueModel<java.lang.Integer> getValueModel();
     method public void setOnSeekBarChangeListener(android.widget.SeekBar.OnSeekBarChangeListener);
+    method public void setValueModel(android.util.ValueModel<java.lang.Integer>);
   }
 
   public static abstract interface SeekBar.OnSeekBarChangeListener {
@@ -29767,6 +29818,11 @@
     method public android.widget.TextView getText2();
   }
 
+  public abstract interface ValueEditor {
+    method public abstract android.util.ValueModel<T> getValueModel();
+    method public abstract void setValueModel(android.util.ValueModel<T>);
+  }
+
   public class VideoView extends android.view.SurfaceView implements android.widget.MediaController.MediaPlayerControl {
     ctor public VideoView(android.content.Context);
     ctor public VideoView(android.content.Context, android.util.AttributeSet);
diff --git a/cmds/bugreport/Android.mk b/cmds/bugreport/Android.mk
deleted file mode 100644
index f476f5e..0000000
--- a/cmds/bugreport/Android.mk
+++ /dev/null
@@ -1,10 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= bugreport.c
-
-LOCAL_MODULE:= bugreport
-
-LOCAL_SHARED_LIBRARIES := libcutils
-
-include $(BUILD_EXECUTABLE)
diff --git a/cmds/bugreport/bugreport.c b/cmds/bugreport/bugreport.c
deleted file mode 100644
index 4a0b511..0000000
--- a/cmds/bugreport/bugreport.c
+++ /dev/null
@@ -1,56 +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.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-
-#include <cutils/properties.h>
-#include <cutils/sockets.h>
-
-int main(int argc, char *argv[]) {
-    char buffer[65536];
-    int i, s;
-
-    /* start the dumpstate service */
-    property_set("ctl.start", "dumpstate");
-
-    /* socket will not be available until service starts */
-    for (i = 0; i < 10; i++) {
-        s = socket_local_client("dumpstate",
-                             ANDROID_SOCKET_NAMESPACE_RESERVED,
-                             SOCK_STREAM);
-        if (s >= 0)
-            break;
-        /* try again in 1 second */
-        sleep(1);
-    }
-
-    if (s < 0) {
-        fprintf(stderr, "Failed to connect to dumpstate service\n");
-        exit(1);
-    }
-
-    while (1) {
-        int length = read(s, buffer, sizeof(buffer));
-        if (length <= 0)
-            break;
-        fwrite(buffer, 1, length, stdout);
-    }
-
-    close(s);
-    return 0;
-}
diff --git a/cmds/content/src/com/android/commands/content/Content.java b/cmds/content/src/com/android/commands/content/Content.java
index 787fbdb..4baea77d 100644
--- a/cmds/content/src/com/android/commands/content/Content.java
+++ b/cmds/content/src/com/android/commands/content/Content.java
@@ -433,7 +433,7 @@
                         System.out.println(builder);
                     } while (cursor.moveToNext());
                 } else {
-                    System.out.println("No reuslt found.");
+                    System.out.println("No result found.");
                 }
             } finally {
                 cursor.close();
diff --git a/cmds/input/src/com/android/commands/input/Input.java b/cmds/input/src/com/android/commands/input/Input.java
index a21df0d..cdbc405 100644
--- a/cmds/input/src/com/android/commands/input/Input.java
+++ b/cmds/input/src/com/android/commands/input/Input.java
@@ -72,7 +72,7 @@
             } else if (command.equals("swipe")) {
                 if (args.length == 5) {
                     sendSwipe(InputDevice.SOURCE_TOUCHSCREEN, Float.parseFloat(args[1]), Float.parseFloat(args[2]),
-                            Float.parseFloat(args[3]), Float.parseFloat(args[4]));
+                            Float.parseFloat(args[3]), Float.parseFloat(args[4]), -1);
                     return;
                 }
             } else if (command.equals("touchscreen") || command.equals("touchpad")) {
@@ -94,7 +94,12 @@
                         if (args.length == 6) {
                             sendSwipe(inputSource, Float.parseFloat(args[2]),
                                     Float.parseFloat(args[3]), Float.parseFloat(args[4]),
-                                    Float.parseFloat(args[5]));
+                                    Float.parseFloat(args[5]), -1);
+                            return;
+                        } else if (args.length == 7) {
+                            sendSwipe(inputSource, Float.parseFloat(args[2]),
+                                    Float.parseFloat(args[3]), Float.parseFloat(args[4]),
+                                    Float.parseFloat(args[5]), Integer.parseInt(args[6]));
                             return;
                         }
                     }
@@ -172,14 +177,20 @@
         injectMotionEvent(inputSource, MotionEvent.ACTION_UP, now, x, y, 0.0f);
     }
 
-    private void sendSwipe(int inputSource, float x1, float y1, float x2, float y2) {
-        final int NUM_STEPS = 11;
+    private void sendSwipe(int inputSource, float x1, float y1, float x2, float y2, int duration) {
+        if (duration < 0) {
+            duration = 300;
+        }
         long now = SystemClock.uptimeMillis();
         injectMotionEvent(inputSource, MotionEvent.ACTION_DOWN, now, x1, y1, 1.0f);
-        for (int i = 1; i < NUM_STEPS; i++) {
-            float alpha = (float) i / NUM_STEPS;
+        long startTime = now;
+        long endTime = startTime + duration;
+        while (now < endTime) {
+            long elapsedTime = now - startTime;
+            float alpha = (float) elapsedTime / duration;
             injectMotionEvent(inputSource, MotionEvent.ACTION_MOVE, now, lerp(x1, x2, alpha),
                     lerp(y1, y2, alpha), 1.0f);
+            now = SystemClock.uptimeMillis();
         }
         injectMotionEvent(inputSource, MotionEvent.ACTION_UP, now, x1, y1, 0.0f);
     }
@@ -237,7 +248,7 @@
         System.err.println("       input text <string>");
         System.err.println("       input keyevent <key code number or name>");
         System.err.println("       input [touchscreen|touchpad] tap <x> <y>");
-        System.err.println("       input [touchscreen|touchpad] swipe <x1> <y1> <x2> <y2>");
+        System.err.println("       input [touchscreen|touchpad] swipe <x1> <y1> <x2> <y2> [duration(ms)]");
         System.err.println("       input trackball press");
         System.err.println("       input trackball roll <dx> <dy>");
     }
diff --git a/cmds/installd/Android.mk b/cmds/installd/Android.mk
deleted file mode 100644
index 1dd4ee5..0000000
--- a/cmds/installd/Android.mk
+++ /dev/null
@@ -1,42 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-
-common_src_files := \
-    commands.c utils.c
-
-#
-# Static library used in testing and executable
-#
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := \
-    $(common_src_files)
-
-LOCAL_MODULE := libinstalld
-
-LOCAL_MODULE_TAGS := eng tests
-
-include $(BUILD_STATIC_LIBRARY)
-
-#
-# Executable
-#
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := \
-    installd.c \
-    $(common_src_files)
-
-LOCAL_SHARED_LIBRARIES := \
-    libcutils \
-    libselinux
-
-LOCAL_STATIC_LIBRARIES := \
-    libdiskusage
-
-LOCAL_MODULE := installd
-
-LOCAL_MODULE_TAGS := optional
-
-include $(BUILD_EXECUTABLE)
diff --git a/cmds/installd/commands.c b/cmds/installd/commands.c
deleted file mode 100644
index 2a54710..0000000
--- a/cmds/installd/commands.c
+++ /dev/null
@@ -1,1122 +0,0 @@
-/*
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License"); 
-** you may not use this file except in compliance with the License. 
-** You may obtain a copy of the License at 
-**
-**     http://www.apache.org/licenses/LICENSE-2.0 
-**
-** Unless required by applicable law or agreed to in writing, software 
-** distributed under the License is distributed on an "AS IS" BASIS, 
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
-** See the License for the specific language governing permissions and 
-** limitations under the License.
-*/
-
-#include <linux/capability.h>
-#include "installd.h"
-#include <diskusage/dirsize.h>
-#include <selinux/android.h>
-
-/* Directory records that are used in execution of commands. */
-dir_rec_t android_data_dir;
-dir_rec_t android_asec_dir;
-dir_rec_t android_app_dir;
-dir_rec_t android_app_private_dir;
-dir_rec_t android_app_lib_dir;
-dir_rec_t android_media_dir;
-dir_rec_array_t android_system_dirs;
-
-int install(const char *pkgname, uid_t uid, gid_t gid)
-{
-    char pkgdir[PKG_PATH_MAX];
-    char libsymlink[PKG_PATH_MAX];
-    char applibdir[PKG_PATH_MAX];
-    struct stat libStat;
-
-    if ((uid < AID_SYSTEM) || (gid < AID_SYSTEM)) {
-        ALOGE("invalid uid/gid: %d %d\n", uid, gid);
-        return -1;
-    }
-
-    if (create_pkg_path(pkgdir, pkgname, PKG_DIR_POSTFIX, 0)) {
-        ALOGE("cannot create package path\n");
-        return -1;
-    }
-
-    if (create_pkg_path(libsymlink, pkgname, PKG_LIB_POSTFIX, 0)) {
-        ALOGE("cannot create package lib symlink origin path\n");
-        return -1;
-    }
-
-    if (create_pkg_path_in_dir(applibdir, &android_app_lib_dir, pkgname, PKG_DIR_POSTFIX)) {
-        ALOGE("cannot create package lib symlink dest path\n");
-        return -1;
-    }
-
-    if (mkdir(pkgdir, 0751) < 0) {
-        ALOGE("cannot create dir '%s': %s\n", pkgdir, strerror(errno));
-        return -1;
-    }
-    if (chmod(pkgdir, 0751) < 0) {
-        ALOGE("cannot chmod dir '%s': %s\n", pkgdir, strerror(errno));
-        unlink(pkgdir);
-        return -1;
-    }
-
-    if (lstat(libsymlink, &libStat) < 0) {
-        if (errno != ENOENT) {
-            ALOGE("couldn't stat lib dir: %s\n", strerror(errno));
-            return -1;
-        }
-    } else {
-        if (S_ISDIR(libStat.st_mode)) {
-            if (delete_dir_contents(libsymlink, 1, 0) < 0) {
-                ALOGE("couldn't delete lib directory during install for: %s", libsymlink);
-                return -1;
-            }
-        } else if (S_ISLNK(libStat.st_mode)) {
-            if (unlink(libsymlink) < 0) {
-                ALOGE("couldn't unlink lib directory during install for: %s", libsymlink);
-                return -1;
-            }
-        }
-    }
-
-    if (symlink(applibdir, libsymlink) < 0) {
-        ALOGE("couldn't symlink directory '%s' -> '%s': %s\n", libsymlink, applibdir,
-                strerror(errno));
-        unlink(pkgdir);
-        return -1;
-    }
-
-    if (selinux_android_setfilecon(pkgdir, pkgname, uid) < 0) {
-        ALOGE("cannot setfilecon dir '%s': %s\n", pkgdir, strerror(errno));
-        unlink(libsymlink);
-        unlink(pkgdir);
-        return -errno;
-    }
-
-    if (chown(pkgdir, uid, gid) < 0) {
-        ALOGE("cannot chown dir '%s': %s\n", pkgdir, strerror(errno));
-        unlink(libsymlink);
-        unlink(pkgdir);
-        return -1;
-    }
-
-    return 0;
-}
-
-int uninstall(const char *pkgname, uid_t persona)
-{
-    char pkgdir[PKG_PATH_MAX];
-
-    if (create_pkg_path(pkgdir, pkgname, PKG_DIR_POSTFIX, persona))
-        return -1;
-
-    /* delete contents AND directory, no exceptions */
-    return delete_dir_contents(pkgdir, 1, NULL);
-}
-
-int renamepkg(const char *oldpkgname, const char *newpkgname)
-{
-    char oldpkgdir[PKG_PATH_MAX];
-    char newpkgdir[PKG_PATH_MAX];
-
-    if (create_pkg_path(oldpkgdir, oldpkgname, PKG_DIR_POSTFIX, 0))
-        return -1;
-    if (create_pkg_path(newpkgdir, newpkgname, PKG_DIR_POSTFIX, 0))
-        return -1;
-
-    if (rename(oldpkgdir, newpkgdir) < 0) {
-        ALOGE("cannot rename dir '%s' to '%s': %s\n", oldpkgdir, newpkgdir, strerror(errno));
-        return -errno;
-    }
-    return 0;
-}
-
-int fix_uid(const char *pkgname, uid_t uid, gid_t gid)
-{
-    char pkgdir[PKG_PATH_MAX];
-    struct stat s;
-    int rc = 0;
-
-    if ((uid < AID_SYSTEM) || (gid < AID_SYSTEM)) {
-        ALOGE("invalid uid/gid: %d %d\n", uid, gid);
-        return -1;
-    }
-
-    if (create_pkg_path(pkgdir, pkgname, PKG_DIR_POSTFIX, 0)) {
-        ALOGE("cannot create package path\n");
-        return -1;
-    }
-
-    if (stat(pkgdir, &s) < 0) return -1;
-
-    if (s.st_uid != 0 || s.st_gid != 0) {
-        ALOGE("fixing uid of non-root pkg: %s %lu %lu\n", pkgdir, s.st_uid, s.st_gid);
-        return -1;
-    }
-
-    if (chmod(pkgdir, 0751) < 0) {
-        ALOGE("cannot chmod dir '%s': %s\n", pkgdir, strerror(errno));
-        unlink(pkgdir);
-        return -errno;
-    }
-    if (chown(pkgdir, uid, gid) < 0) {
-        ALOGE("cannot chown dir '%s': %s\n", pkgdir, strerror(errno));
-        unlink(pkgdir);
-        return -errno;
-    }
-
-    return 0;
-}
-
-int delete_user_data(const char *pkgname, uid_t persona)
-{
-    char pkgdir[PKG_PATH_MAX];
-
-    if (create_pkg_path(pkgdir, pkgname, PKG_DIR_POSTFIX, persona))
-        return -1;
-
-    /* delete contents, excluding "lib", but not the directory itself */
-    return delete_dir_contents(pkgdir, 0, "lib");
-}
-
-int make_user_data(const char *pkgname, uid_t uid, uid_t persona)
-{
-    char pkgdir[PKG_PATH_MAX];
-    char applibdir[PKG_PATH_MAX];
-    char libsymlink[PKG_PATH_MAX];
-    struct stat libStat;
-
-    // Create the data dir for the package
-    if (create_pkg_path(pkgdir, pkgname, PKG_DIR_POSTFIX, persona)) {
-        return -1;
-    }
-    if (create_pkg_path(libsymlink, pkgname, PKG_LIB_POSTFIX, persona)) {
-        ALOGE("cannot create package lib symlink origin path\n");
-        return -1;
-    }
-    if (create_pkg_path_in_dir(applibdir, &android_app_lib_dir, pkgname, PKG_DIR_POSTFIX)) {
-        ALOGE("cannot create package lib symlink dest path\n");
-        return -1;
-    }
-
-    if (mkdir(pkgdir, 0751) < 0) {
-        ALOGE("cannot create dir '%s': %s\n", pkgdir, strerror(errno));
-        return -errno;
-    }
-    if (chmod(pkgdir, 0751) < 0) {
-        ALOGE("cannot chmod dir '%s': %s\n", pkgdir, strerror(errno));
-        unlink(pkgdir);
-        return -errno;
-    }
-
-    if (lstat(libsymlink, &libStat) < 0) {
-        if (errno != ENOENT) {
-            ALOGE("couldn't stat lib dir for non-primary: %s\n", strerror(errno));
-            unlink(pkgdir);
-            return -1;
-        }
-    } else {
-        if (S_ISDIR(libStat.st_mode)) {
-            if (delete_dir_contents(libsymlink, 1, 0) < 0) {
-                ALOGE("couldn't delete lib directory during install for non-primary: %s",
-                        libsymlink);
-                unlink(pkgdir);
-                return -1;
-            }
-        } else if (S_ISLNK(libStat.st_mode)) {
-            if (unlink(libsymlink) < 0) {
-                ALOGE("couldn't unlink lib directory during install for non-primary: %s",
-                        libsymlink);
-                unlink(pkgdir);
-                return -1;
-            }
-        }
-    }
-
-    if (symlink(applibdir, libsymlink) < 0) {
-        ALOGE("couldn't symlink directory for non-primary '%s' -> '%s': %s\n", libsymlink,
-                applibdir, strerror(errno));
-        unlink(pkgdir);
-        return -1;
-    }
-
-    if (selinux_android_setfilecon(pkgdir, pkgname, uid) < 0) {
-        ALOGE("cannot setfilecon dir '%s': %s\n", pkgdir, strerror(errno));
-        unlink(libsymlink);
-        unlink(pkgdir);
-        return -errno;
-    }
-
-    if (chown(pkgdir, uid, uid) < 0) {
-        ALOGE("cannot chown dir '%s': %s\n", pkgdir, strerror(errno));
-        unlink(libsymlink);
-        unlink(pkgdir);
-        return -errno;
-    }
-
-    return 0;
-}
-
-int delete_persona(uid_t persona)
-{
-    char data_path[PKG_PATH_MAX];
-    if (create_persona_path(data_path, persona)) {
-        return -1;
-    }
-    if (delete_dir_contents(data_path, 1, NULL)) {
-        return -1;
-    }
-
-    char media_path[PATH_MAX];
-    if (create_persona_media_path(media_path, (userid_t) persona) == -1) {
-        return -1;
-    }
-    if (delete_dir_contents(media_path, 1, NULL) == -1) {
-        return -1;
-    }
-
-    return 0;
-}
-
-int clone_persona_data(uid_t src_persona, uid_t target_persona, int copy)
-{
-    char src_data_dir[PKG_PATH_MAX];
-    char pkg_path[PKG_PATH_MAX];
-    DIR *d;
-    struct dirent *de;
-    struct stat s;
-    uid_t uid;
-
-    if (create_persona_path(src_data_dir, src_persona)) {
-        return -1;
-    }
-
-    d = opendir(src_data_dir);
-    if (d != NULL) {
-        while ((de = readdir(d))) {
-            const char *name = de->d_name;
-
-            if (de->d_type == DT_DIR) {
-                int subfd;
-                    /* always skip "." and ".." */
-                if (name[0] == '.') {
-                    if (name[1] == 0) continue;
-                    if ((name[1] == '.') && (name[2] == 0)) continue;
-                }
-                /* Create the full path to the package's data dir */
-                create_pkg_path(pkg_path, name, PKG_DIR_POSTFIX, src_persona);
-                /* Get the file stat */
-                if (stat(pkg_path, &s) < 0) continue;
-                /* Get the uid of the package */
-                ALOGI("Adding datadir for uid = %lu\n", s.st_uid);
-                uid = (uid_t) s.st_uid % PER_USER_RANGE;
-                /* Create the directory for the target */
-                make_user_data(name, uid + target_persona * PER_USER_RANGE,
-                               target_persona);
-            }
-        }
-        closedir(d);
-    }
-
-    if (ensure_media_user_dirs((userid_t) target_persona) == -1) {
-        return -1;
-    }
-
-    return 0;
-}
-
-int delete_cache(const char *pkgname, uid_t persona)
-{
-    char cachedir[PKG_PATH_MAX];
-
-    if (create_pkg_path(cachedir, pkgname, CACHE_DIR_POSTFIX, persona))
-        return -1;
-
-        /* delete contents, not the directory, no exceptions */
-    return delete_dir_contents(cachedir, 0, 0);
-}
-
-/* Try to ensure free_size bytes of storage are available.
- * Returns 0 on success.
- * This is rather simple-minded because doing a full LRU would
- * be potentially memory-intensive, and without atime it would
- * also require that apps constantly modify file metadata even
- * when just reading from the cache, which is pretty awful.
- */
-int free_cache(int64_t free_size)
-{
-    cache_t* cache;
-    int64_t avail;
-    DIR *d;
-    struct dirent *de;
-    char tmpdir[PATH_MAX];
-    char *dirpos;
-
-    avail = data_disk_free();
-    if (avail < 0) return -1;
-
-    ALOGI("free_cache(%" PRId64 ") avail %" PRId64 "\n", free_size, avail);
-    if (avail >= free_size) return 0;
-
-    cache = start_cache_collection();
-
-    // Collect cache files for primary user.
-    if (create_persona_path(tmpdir, 0) == 0) {
-        //ALOGI("adding cache files from %s\n", tmpdir);
-        add_cache_files(cache, tmpdir, "cache");
-    }
-
-    // Search for other users and add any cache files from them.
-    snprintf(tmpdir, sizeof(tmpdir), "%s%s", android_data_dir.path,
-            SECONDARY_USER_PREFIX);
-    dirpos = tmpdir + strlen(tmpdir);
-    d = opendir(tmpdir);
-    if (d != NULL) {
-        while ((de = readdir(d))) {
-            if (de->d_type == DT_DIR) {
-                const char *name = de->d_name;
-                    /* always skip "." and ".." */
-                if (name[0] == '.') {
-                    if (name[1] == 0) continue;
-                    if ((name[1] == '.') && (name[2] == 0)) continue;
-                }
-                if ((strlen(name)+(dirpos-tmpdir)) < (sizeof(tmpdir)-1)) {
-                    strcpy(dirpos, name);
-                    //ALOGI("adding cache files from %s\n", tmpdir);
-                    add_cache_files(cache, tmpdir, "cache");
-                } else {
-                    ALOGW("Path exceeds limit: %s%s", tmpdir, name);
-                }
-            }
-        }
-        closedir(d);
-    }
-
-    // Collect cache files on external storage for all users (if it is mounted as part
-    // of the internal storage).
-    strcpy(tmpdir, android_media_dir.path);
-    dirpos = tmpdir + strlen(tmpdir);
-    d = opendir(tmpdir);
-    if (d != NULL) {
-        while ((de = readdir(d))) {
-            if (de->d_type == DT_DIR) {
-                const char *name = de->d_name;
-                    /* skip any dir that doesn't start with a number, so not a user */
-                if (name[0] < '0' || name[0] > '9') {
-                    continue;
-                }
-                if ((strlen(name)+(dirpos-tmpdir)) < (sizeof(tmpdir)-1)) {
-                    strcpy(dirpos, name);
-                    if (lookup_media_dir(tmpdir, "Android") == 0
-                            && lookup_media_dir(tmpdir, "data") == 0) {
-                        //ALOGI("adding cache files from %s\n", tmpdir);
-                        add_cache_files(cache, tmpdir, "cache");
-                    }
-                } else {
-                    ALOGW("Path exceeds limit: %s%s", tmpdir, name);
-                }
-            }
-        }
-        closedir(d);
-    }
-
-    clear_cache_files(cache, free_size);
-    finish_cache_collection(cache);
-
-    return data_disk_free() >= free_size ? 0 : -1;
-}
-
-int move_dex(const char *src, const char *dst)
-{
-    char src_dex[PKG_PATH_MAX];
-    char dst_dex[PKG_PATH_MAX];
-
-    if (validate_apk_path(src)) return -1;
-    if (validate_apk_path(dst)) return -1;
-
-    if (create_cache_path(src_dex, src)) return -1;
-    if (create_cache_path(dst_dex, dst)) return -1;
-
-    ALOGV("move %s -> %s\n", src_dex, dst_dex);
-    if (rename(src_dex, dst_dex) < 0) {
-        ALOGE("Couldn't move %s: %s\n", src_dex, strerror(errno));
-        return -1;
-    } else {
-        return 0;
-    }
-}
-
-int rm_dex(const char *path)
-{
-    char dex_path[PKG_PATH_MAX];
-
-    if (validate_apk_path(path)) return -1;
-    if (create_cache_path(dex_path, path)) return -1;
-
-    ALOGV("unlink %s\n", dex_path);
-    if (unlink(dex_path) < 0) {
-        ALOGE("Couldn't unlink %s: %s\n", dex_path, strerror(errno));
-        return -1;
-    } else {
-        return 0;
-    }
-}
-
-int get_size(const char *pkgname, int persona, const char *apkpath,
-             const char *fwdlock_apkpath, const char *asecpath,
-             int64_t *_codesize, int64_t *_datasize, int64_t *_cachesize,
-             int64_t* _asecsize)
-{
-    DIR *d;
-    int dfd;
-    struct dirent *de;
-    struct stat s;
-    char path[PKG_PATH_MAX];
-
-    int64_t codesize = 0;
-    int64_t datasize = 0;
-    int64_t cachesize = 0;
-    int64_t asecsize = 0;
-
-        /* count the source apk as code -- but only if it's not
-         * on the /system partition and its not on the sdcard.
-         */
-    if (validate_system_app_path(apkpath) &&
-            strncmp(apkpath, android_asec_dir.path, android_asec_dir.len) != 0) {
-        if (stat(apkpath, &s) == 0) {
-            codesize += stat_size(&s);
-        }
-    }
-        /* count the forward locked apk as code if it is given
-         */
-    if (fwdlock_apkpath != NULL && fwdlock_apkpath[0] != '!') {
-        if (stat(fwdlock_apkpath, &s) == 0) {
-            codesize += stat_size(&s);
-        }
-    }
-        /* count the cached dexfile as code */
-    if (!create_cache_path(path, apkpath)) {
-        if (stat(path, &s) == 0) {
-            codesize += stat_size(&s);
-        }
-    }
-
-        /* add in size of any libraries */
-    if (!create_pkg_path_in_dir(path, &android_app_lib_dir, pkgname, PKG_DIR_POSTFIX)) {
-        d = opendir(path);
-        if (d != NULL) {
-            dfd = dirfd(d);
-            codesize += calculate_dir_size(dfd);
-            closedir(d);
-        }
-    }
-
-        /* compute asec size if it is given
-         */
-    if (asecpath != NULL && asecpath[0] != '!') {
-        if (stat(asecpath, &s) == 0) {
-            asecsize += stat_size(&s);
-        }
-    }
-
-    if (create_pkg_path(path, pkgname, PKG_DIR_POSTFIX, persona)) {
-        goto done;
-    }
-
-    d = opendir(path);
-    if (d == NULL) {
-        goto done;
-    }
-    dfd = dirfd(d);
-
-    /* most stuff in the pkgdir is data, except for the "cache"
-     * directory and below, which is cache, and the "lib" directory
-     * and below, which is code...
-     */
-    while ((de = readdir(d))) {
-        const char *name = de->d_name;
-
-        if (de->d_type == DT_DIR) {
-            int subfd;
-            int64_t statsize = 0;
-            int64_t dirsize = 0;
-                /* always skip "." and ".." */
-            if (name[0] == '.') {
-                if (name[1] == 0) continue;
-                if ((name[1] == '.') && (name[2] == 0)) continue;
-            }
-            if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) == 0) {
-                statsize = stat_size(&s);
-            }
-            subfd = openat(dfd, name, O_RDONLY | O_DIRECTORY);
-            if (subfd >= 0) {
-                dirsize = calculate_dir_size(subfd);
-            }
-            if(!strcmp(name,"lib")) {
-                codesize += dirsize + statsize;
-            } else if(!strcmp(name,"cache")) {
-                cachesize += dirsize + statsize;
-            } else {
-                datasize += dirsize + statsize;
-            }
-        } else if (de->d_type == DT_LNK && !strcmp(name,"lib")) {
-            // This is the symbolic link to the application's library
-            // code.  We'll count this as code instead of data, since
-            // it is not something that the app creates.
-            if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) == 0) {
-                codesize += stat_size(&s);
-            }
-        } else {
-            if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) == 0) {
-                datasize += stat_size(&s);
-            }
-        }
-    }
-    closedir(d);
-done:
-    *_codesize = codesize;
-    *_datasize = datasize;
-    *_cachesize = cachesize;
-    *_asecsize = asecsize;
-    return 0;
-}
-
-
-/* a simpler version of dexOptGenerateCacheFileName() */
-int create_cache_path(char path[PKG_PATH_MAX], const char *src)
-{
-    char *tmp;
-    int srclen;
-    int dstlen;
-
-    srclen = strlen(src);
-
-        /* demand that we are an absolute path */
-    if ((src == 0) || (src[0] != '/') || strstr(src,"..")) {
-        return -1;
-    }
-
-    if (srclen > PKG_PATH_MAX) {        // XXX: PKG_NAME_MAX?
-        return -1;
-    }
-
-    dstlen = srclen + strlen(DALVIK_CACHE_PREFIX) + 
-        strlen(DALVIK_CACHE_POSTFIX) + 1;
-    
-    if (dstlen > PKG_PATH_MAX) {
-        return -1;
-    }
-
-    sprintf(path,"%s%s%s",
-            DALVIK_CACHE_PREFIX,
-            src + 1, /* skip the leading / */
-            DALVIK_CACHE_POSTFIX);
-    
-    for(tmp = path + strlen(DALVIK_CACHE_PREFIX); *tmp; tmp++) {
-        if (*tmp == '/') {
-            *tmp = '@';
-        }
-    }
-
-    return 0;
-}
-
-static void run_dexopt(int zip_fd, int odex_fd, const char* input_file_name,
-    const char* dexopt_flags)
-{
-    static const char* DEX_OPT_BIN = "/system/bin/dexopt";
-    static const int MAX_INT_LEN = 12;      // '-'+10dig+'\0' -OR- 0x+8dig
-    char zip_num[MAX_INT_LEN];
-    char odex_num[MAX_INT_LEN];
-
-    sprintf(zip_num, "%d", zip_fd);
-    sprintf(odex_num, "%d", odex_fd);
-
-    execl(DEX_OPT_BIN, DEX_OPT_BIN, "--zip", zip_num, odex_num, input_file_name,
-        dexopt_flags, (char*) NULL);
-    ALOGE("execl(%s) failed: %s\n", DEX_OPT_BIN, strerror(errno));
-}
-
-static int wait_dexopt(pid_t pid, const char* apk_path)
-{
-    int status;
-    pid_t got_pid;
-
-    /*
-     * Wait for the optimization process to finish.
-     */
-    while (1) {
-        got_pid = waitpid(pid, &status, 0);
-        if (got_pid == -1 && errno == EINTR) {
-            printf("waitpid interrupted, retrying\n");
-        } else {
-            break;
-        }
-    }
-    if (got_pid != pid) {
-        ALOGW("waitpid failed: wanted %d, got %d: %s\n",
-            (int) pid, (int) got_pid, strerror(errno));
-        return 1;
-    }
-
-    if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
-        ALOGV("DexInv: --- END '%s' (success) ---\n", apk_path);
-        return 0;
-    } else {
-        ALOGW("DexInv: --- END '%s' --- status=0x%04x, process failed\n",
-            apk_path, status);
-        return status;      /* always nonzero */
-    }
-}
-
-int dexopt(const char *apk_path, uid_t uid, int is_public)
-{
-    struct utimbuf ut;
-    struct stat apk_stat, dex_stat;
-    char dex_path[PKG_PATH_MAX];
-    char dexopt_flags[PROPERTY_VALUE_MAX];
-    char *end;
-    int res, zip_fd=-1, odex_fd=-1;
-
-        /* Before anything else: is there a .odex file?  If so, we have
-         * pre-optimized the apk and there is nothing to do here.
-         */
-    if (strlen(apk_path) >= (PKG_PATH_MAX - 8)) {
-        return -1;
-    }
-
-    /* platform-specific flags affecting optimization and verification */
-    property_get("dalvik.vm.dexopt-flags", dexopt_flags, "");
-
-    strcpy(dex_path, apk_path);
-    end = strrchr(dex_path, '.');
-    if (end != NULL) {
-        strcpy(end, ".odex");
-        if (stat(dex_path, &dex_stat) == 0) {
-            return 0;
-        }
-    }
-
-    if (create_cache_path(dex_path, apk_path)) {
-        return -1;
-    }
-
-    memset(&apk_stat, 0, sizeof(apk_stat));
-    stat(apk_path, &apk_stat);
-
-    zip_fd = open(apk_path, O_RDONLY, 0);
-    if (zip_fd < 0) {
-        ALOGE("dexopt cannot open '%s' for input\n", apk_path);
-        return -1;
-    }
-
-    unlink(dex_path);
-    odex_fd = open(dex_path, O_RDWR | O_CREAT | O_EXCL, 0644);
-    if (odex_fd < 0) {
-        ALOGE("dexopt cannot open '%s' for output\n", dex_path);
-        goto fail;
-    }
-    if (fchmod(odex_fd,
-               S_IRUSR|S_IWUSR|S_IRGRP |
-               (is_public ? S_IROTH : 0)) < 0) {
-        ALOGE("dexopt cannot chmod '%s'\n", dex_path);
-        goto fail;
-    }
-    if (fchown(odex_fd, AID_SYSTEM, uid) < 0) {
-        ALOGE("dexopt cannot chown '%s'\n", dex_path);
-        goto fail;
-    }
-
-    ALOGV("DexInv: --- BEGIN '%s' ---\n", apk_path);
-
-    pid_t pid;
-    pid = fork();
-    if (pid == 0) {
-        /* child -- drop privileges before continuing */
-        if (setgid(uid) != 0) {
-            ALOGE("setgid(%d) failed during dexopt\n", uid);
-            exit(64);
-        }
-        if (setuid(uid) != 0) {
-            ALOGE("setuid(%d) during dexopt\n", uid);
-            exit(65);
-        }
-        // drop capabilities
-        struct __user_cap_header_struct capheader;
-        struct __user_cap_data_struct capdata[2];
-        memset(&capheader, 0, sizeof(capheader));
-        memset(&capdata, 0, sizeof(capdata));
-        capheader.version = _LINUX_CAPABILITY_VERSION_3;
-        if (capset(&capheader, &capdata[0]) < 0) {
-            ALOGE("capset failed: %s\n", strerror(errno));
-            exit(66);
-        }
-        if (flock(odex_fd, LOCK_EX | LOCK_NB) != 0) {
-            ALOGE("flock(%s) failed: %s\n", dex_path, strerror(errno));
-            exit(67);
-        }
-
-        run_dexopt(zip_fd, odex_fd, apk_path, dexopt_flags);
-        exit(68);   /* only get here on exec failure */
-    } else {
-        res = wait_dexopt(pid, apk_path);
-        if (res != 0) {
-            ALOGE("dexopt failed on '%s' res = %d\n", dex_path, res);
-            goto fail;
-        }
-    }
-
-    ut.actime = apk_stat.st_atime;
-    ut.modtime = apk_stat.st_mtime;
-    utime(dex_path, &ut);
-    
-    close(odex_fd);
-    close(zip_fd);
-    return 0;
-
-fail:
-    if (odex_fd >= 0) {
-        close(odex_fd);
-        unlink(dex_path);
-    }
-    if (zip_fd >= 0) {
-        close(zip_fd);
-    }
-    return -1;
-}
-
-void mkinnerdirs(char* path, int basepos, mode_t mode, int uid, int gid,
-        struct stat* statbuf)
-{
-    while (path[basepos] != 0) {
-        if (path[basepos] == '/') {
-            path[basepos] = 0;
-            if (lstat(path, statbuf) < 0) {
-                ALOGV("Making directory: %s\n", path);
-                if (mkdir(path, mode) == 0) {
-                    chown(path, uid, gid);
-                } else {
-                    ALOGW("Unable to make directory %s: %s\n", path, strerror(errno));
-                }
-            }
-            path[basepos] = '/';
-            basepos++;
-        }
-        basepos++;
-    }
-}
-
-int movefileordir(char* srcpath, char* dstpath, int dstbasepos,
-        int dstuid, int dstgid, struct stat* statbuf)
-{
-    DIR *d;
-    struct dirent *de;
-    int res;
-
-    int srcend = strlen(srcpath);
-    int dstend = strlen(dstpath);
-    
-    if (lstat(srcpath, statbuf) < 0) {
-        ALOGW("Unable to stat %s: %s\n", srcpath, strerror(errno));
-        return 1;
-    }
-    
-    if ((statbuf->st_mode&S_IFDIR) == 0) {
-        mkinnerdirs(dstpath, dstbasepos, S_IRWXU|S_IRWXG|S_IXOTH,
-                dstuid, dstgid, statbuf);
-        ALOGV("Renaming %s to %s (uid %d)\n", srcpath, dstpath, dstuid);
-        if (rename(srcpath, dstpath) >= 0) {
-            if (chown(dstpath, dstuid, dstgid) < 0) {
-                ALOGE("cannot chown %s: %s\n", dstpath, strerror(errno));
-                unlink(dstpath);
-                return 1;
-            }
-        } else {
-            ALOGW("Unable to rename %s to %s: %s\n",
-                srcpath, dstpath, strerror(errno));
-            return 1;
-        }
-        return 0;
-    }
-
-    d = opendir(srcpath);
-    if (d == NULL) {
-        ALOGW("Unable to opendir %s: %s\n", srcpath, strerror(errno));
-        return 1;
-    }
-
-    res = 0;
-    
-    while ((de = readdir(d))) {
-        const char *name = de->d_name;
-            /* always skip "." and ".." */
-        if (name[0] == '.') {
-            if (name[1] == 0) continue;
-            if ((name[1] == '.') && (name[2] == 0)) continue;
-        }
-        
-        if ((srcend+strlen(name)) >= (PKG_PATH_MAX-2)) {
-            ALOGW("Source path too long; skipping: %s/%s\n", srcpath, name);
-            continue;
-        }
-        
-        if ((dstend+strlen(name)) >= (PKG_PATH_MAX-2)) {
-            ALOGW("Destination path too long; skipping: %s/%s\n", dstpath, name);
-            continue;
-        }
-        
-        srcpath[srcend] = dstpath[dstend] = '/';
-        strcpy(srcpath+srcend+1, name);
-        strcpy(dstpath+dstend+1, name);
-        
-        if (movefileordir(srcpath, dstpath, dstbasepos, dstuid, dstgid, statbuf) != 0) {
-            res = 1;
-        }
-        
-        // Note: we will be leaving empty directories behind in srcpath,
-        // but that is okay, the package manager will be erasing all of the
-        // data associated with .apks that disappear.
-        
-        srcpath[srcend] = dstpath[dstend] = 0;
-    }
-    
-    closedir(d);
-    return res;
-}
-
-int movefiles()
-{
-    DIR *d;
-    int dfd, subfd;
-    struct dirent *de;
-    struct stat s;
-    char buf[PKG_PATH_MAX+1];
-    int bufp, bufe, bufi, readlen;
-
-    char srcpkg[PKG_NAME_MAX];
-    char dstpkg[PKG_NAME_MAX];
-    char srcpath[PKG_PATH_MAX];
-    char dstpath[PKG_PATH_MAX];
-    int dstuid=-1, dstgid=-1;
-    int hasspace;
-
-    d = opendir(UPDATE_COMMANDS_DIR_PREFIX);
-    if (d == NULL) {
-        goto done;
-    }
-    dfd = dirfd(d);
-
-        /* Iterate through all files in the directory, executing the
-         * file movements requested there-in.
-         */
-    while ((de = readdir(d))) {
-        const char *name = de->d_name;
-
-        if (de->d_type == DT_DIR) {
-            continue;
-        } else {
-            subfd = openat(dfd, name, O_RDONLY);
-            if (subfd < 0) {
-                ALOGW("Unable to open update commands at %s%s\n",
-                        UPDATE_COMMANDS_DIR_PREFIX, name);
-                continue;
-            }
-            
-            bufp = 0;
-            bufe = 0;
-            buf[PKG_PATH_MAX] = 0;
-            srcpkg[0] = dstpkg[0] = 0;
-            while (1) {
-                bufi = bufp;
-                while (bufi < bufe && buf[bufi] != '\n') {
-                    bufi++;
-                }
-                if (bufi < bufe) {
-                    buf[bufi] = 0;
-                    ALOGV("Processing line: %s\n", buf+bufp);
-                    hasspace = 0;
-                    while (bufp < bufi && isspace(buf[bufp])) {
-                        hasspace = 1;
-                        bufp++;
-                    }
-                    if (buf[bufp] == '#' || bufp == bufi) {
-                        // skip comments and empty lines.
-                    } else if (hasspace) {
-                        if (dstpkg[0] == 0) {
-                            ALOGW("Path before package line in %s%s: %s\n",
-                                    UPDATE_COMMANDS_DIR_PREFIX, name, buf+bufp);
-                        } else if (srcpkg[0] == 0) {
-                            // Skip -- source package no longer exists.
-                        } else {
-                            ALOGV("Move file: %s (from %s to %s)\n", buf+bufp, srcpkg, dstpkg);
-                            if (!create_move_path(srcpath, srcpkg, buf+bufp, 0) &&
-                                    !create_move_path(dstpath, dstpkg, buf+bufp, 0)) {
-                                movefileordir(srcpath, dstpath,
-                                        strlen(dstpath)-strlen(buf+bufp),
-                                        dstuid, dstgid, &s);
-                            }
-                        }
-                    } else {
-                        char* div = strchr(buf+bufp, ':');
-                        if (div == NULL) {
-                            ALOGW("Bad package spec in %s%s; no ':' sep: %s\n",
-                                    UPDATE_COMMANDS_DIR_PREFIX, name, buf+bufp);
-                        } else {
-                            *div = 0;
-                            div++;
-                            if (strlen(buf+bufp) < PKG_NAME_MAX) {
-                                strcpy(dstpkg, buf+bufp);
-                            } else {
-                                srcpkg[0] = dstpkg[0] = 0;
-                                ALOGW("Package name too long in %s%s: %s\n",
-                                        UPDATE_COMMANDS_DIR_PREFIX, name, buf+bufp);
-                            }
-                            if (strlen(div) < PKG_NAME_MAX) {
-                                strcpy(srcpkg, div);
-                            } else {
-                                srcpkg[0] = dstpkg[0] = 0;
-                                ALOGW("Package name too long in %s%s: %s\n",
-                                        UPDATE_COMMANDS_DIR_PREFIX, name, div);
-                            }
-                            if (srcpkg[0] != 0) {
-                                if (!create_pkg_path(srcpath, srcpkg, PKG_DIR_POSTFIX, 0)) {
-                                    if (lstat(srcpath, &s) < 0) {
-                                        // Package no longer exists -- skip.
-                                        srcpkg[0] = 0;
-                                    }
-                                } else {
-                                    srcpkg[0] = 0;
-                                    ALOGW("Can't create path %s in %s%s\n",
-                                            div, UPDATE_COMMANDS_DIR_PREFIX, name);
-                                }
-                                if (srcpkg[0] != 0) {
-                                    if (!create_pkg_path(dstpath, dstpkg, PKG_DIR_POSTFIX, 0)) {
-                                        if (lstat(dstpath, &s) == 0) {
-                                            dstuid = s.st_uid;
-                                            dstgid = s.st_gid;
-                                        } else {
-                                            // Destination package doesn't
-                                            // exist...  due to original-package,
-                                            // this is normal, so don't be
-                                            // noisy about it.
-                                            srcpkg[0] = 0;
-                                        }
-                                    } else {
-                                        srcpkg[0] = 0;
-                                        ALOGW("Can't create path %s in %s%s\n",
-                                                div, UPDATE_COMMANDS_DIR_PREFIX, name);
-                                    }
-                                }
-                                ALOGV("Transfering from %s to %s: uid=%d\n",
-                                    srcpkg, dstpkg, dstuid);
-                            }
-                        }
-                    }
-                    bufp = bufi+1;
-                } else {
-                    if (bufp == 0) {
-                        if (bufp < bufe) {
-                            ALOGW("Line too long in %s%s, skipping: %s\n",
-                                    UPDATE_COMMANDS_DIR_PREFIX, name, buf);
-                        }
-                    } else if (bufp < bufe) {
-                        memcpy(buf, buf+bufp, bufe-bufp);
-                        bufe -= bufp;
-                        bufp = 0;
-                    }
-                    readlen = read(subfd, buf+bufe, PKG_PATH_MAX-bufe);
-                    if (readlen < 0) {
-                        ALOGW("Failure reading update commands in %s%s: %s\n",
-                                UPDATE_COMMANDS_DIR_PREFIX, name, strerror(errno));
-                        break;
-                    } else if (readlen == 0) {
-                        break;
-                    }
-                    bufe += readlen;
-                    buf[bufe] = 0;
-                    ALOGV("Read buf: %s\n", buf);
-                }
-            }
-            close(subfd);
-        }
-    }
-    closedir(d);
-done:
-    return 0;
-}
-
-int linklib(const char* pkgname, const char* asecLibDir, int userId)
-{
-    char pkgdir[PKG_PATH_MAX];
-    char libsymlink[PKG_PATH_MAX];
-    struct stat s, libStat;
-    int rc = 0;
-
-    if (create_pkg_path(pkgdir, pkgname, PKG_DIR_POSTFIX, userId)) {
-        ALOGE("cannot create package path\n");
-        return -1;
-    }
-    if (create_pkg_path(libsymlink, pkgname, PKG_LIB_POSTFIX, userId)) {
-        ALOGE("cannot create package lib symlink origin path\n");
-        return -1;
-    }
-
-    if (stat(pkgdir, &s) < 0) return -1;
-
-    if (chown(pkgdir, AID_INSTALL, AID_INSTALL) < 0) {
-        ALOGE("failed to chown '%s': %s\n", pkgdir, strerror(errno));
-        return -1;
-    }
-
-    if (chmod(pkgdir, 0700) < 0) {
-        ALOGE("linklib() 1: failed to chmod '%s': %s\n", pkgdir, strerror(errno));
-        rc = -1;
-        goto out;
-    }
-
-    if (lstat(libsymlink, &libStat) < 0) {
-        if (errno != ENOENT) {
-            ALOGE("couldn't stat lib dir: %s\n", strerror(errno));
-            rc = -1;
-            goto out;
-        }
-    } else {
-        if (S_ISDIR(libStat.st_mode)) {
-            if (delete_dir_contents(libsymlink, 1, 0) < 0) {
-                rc = -1;
-                goto out;
-            }
-        } else if (S_ISLNK(libStat.st_mode)) {
-            if (unlink(libsymlink) < 0) {
-                ALOGE("couldn't unlink lib dir: %s\n", strerror(errno));
-                rc = -1;
-                goto out;
-            }
-        }
-    }
-
-    if (symlink(asecLibDir, libsymlink) < 0) {
-        ALOGE("couldn't symlink directory '%s' -> '%s': %s\n", libsymlink, asecLibDir,
-                strerror(errno));
-        rc = -errno;
-        goto out;
-    }
-
-out:
-    if (chmod(pkgdir, s.st_mode) < 0) {
-        ALOGE("linklib() 2: failed to chmod '%s': %s\n", pkgdir, strerror(errno));
-        rc = -errno;
-    }
-
-    if (chown(pkgdir, s.st_uid, s.st_gid) < 0) {
-        ALOGE("failed to chown '%s' : %s\n", pkgdir, strerror(errno));
-        return -errno;
-    }
-
-    return rc;
-}
diff --git a/cmds/installd/installd.c b/cmds/installd/installd.c
deleted file mode 100644
index 21d674a..0000000
--- a/cmds/installd/installd.c
+++ /dev/null
@@ -1,592 +0,0 @@
-/*
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License"); 
-** you may not use this file except in compliance with the License. 
-** You may obtain a copy of the License at 
-**
-**     http://www.apache.org/licenses/LICENSE-2.0 
-**
-** Unless required by applicable law or agreed to in writing, software 
-** distributed under the License is distributed on an "AS IS" BASIS, 
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
-** See the License for the specific language governing permissions and 
-** limitations under the License.
-*/
-
-#include <linux/capability.h>
-#include <linux/prctl.h>
-
-#include "installd.h"
-
-
-#define BUFFER_MAX    1024  /* input buffer for commands */
-#define TOKEN_MAX     8     /* max number of arguments in buffer */
-#define REPLY_MAX     256   /* largest reply allowed */
-
-static int do_ping(char **arg, char reply[REPLY_MAX])
-{
-    return 0;
-}
-
-static int do_install(char **arg, char reply[REPLY_MAX])
-{
-    return install(arg[0], atoi(arg[1]), atoi(arg[2])); /* pkgname, uid, gid */
-}
-
-static int do_dexopt(char **arg, char reply[REPLY_MAX])
-{
-        /* apk_path, uid, is_public */
-    return dexopt(arg[0], atoi(arg[1]), atoi(arg[2]));
-}
-
-static int do_move_dex(char **arg, char reply[REPLY_MAX])
-{
-    return move_dex(arg[0], arg[1]); /* src, dst */
-}
-
-static int do_rm_dex(char **arg, char reply[REPLY_MAX])
-{
-    return rm_dex(arg[0]); /* pkgname */
-}
-
-static int do_remove(char **arg, char reply[REPLY_MAX])
-{
-    return uninstall(arg[0], atoi(arg[1])); /* pkgname, userid */
-}
-
-static int do_rename(char **arg, char reply[REPLY_MAX])
-{
-    return renamepkg(arg[0], arg[1]); /* oldpkgname, newpkgname */
-}
-
-static int do_fixuid(char **arg, char reply[REPLY_MAX])
-{
-    return fix_uid(arg[0], atoi(arg[1]), atoi(arg[2])); /* pkgname, uid, gid */
-}
-
-static int do_free_cache(char **arg, char reply[REPLY_MAX]) /* TODO int:free_size */
-{
-    return free_cache((int64_t)atoll(arg[0])); /* free_size */
-}
-
-static int do_rm_cache(char **arg, char reply[REPLY_MAX])
-{
-    return delete_cache(arg[0], atoi(arg[1])); /* pkgname, userid */
-}
-
-static int do_get_size(char **arg, char reply[REPLY_MAX])
-{
-    int64_t codesize = 0;
-    int64_t datasize = 0;
-    int64_t cachesize = 0;
-    int64_t asecsize = 0;
-    int res = 0;
-
-        /* pkgdir, persona, apkpath */
-    res = get_size(arg[0], atoi(arg[1]), arg[2], arg[3], arg[4],
-            &codesize, &datasize, &cachesize, &asecsize);
-
-    /*
-     * Each int64_t can take up 22 characters printed out. Make sure it
-     * doesn't go over REPLY_MAX in the future.
-     */
-    snprintf(reply, REPLY_MAX, "%" PRId64 " %" PRId64 " %" PRId64 " %" PRId64,
-            codesize, datasize, cachesize, asecsize);
-    return res;
-}
-
-static int do_rm_user_data(char **arg, char reply[REPLY_MAX])
-{
-    return delete_user_data(arg[0], atoi(arg[1])); /* pkgname, userid */
-}
-
-static int do_mk_user_data(char **arg, char reply[REPLY_MAX])
-{
-    return make_user_data(arg[0], atoi(arg[1]), atoi(arg[2])); /* pkgname, uid, userid */
-}
-
-static int do_rm_user(char **arg, char reply[REPLY_MAX])
-{
-    return delete_persona(atoi(arg[0])); /* userid */
-}
-
-static int do_clone_user_data(char **arg, char reply[REPLY_MAX])
-{
-    return clone_persona_data(atoi(arg[0]), atoi(arg[1]), atoi(arg[2]));
-}
-
-static int do_movefiles(char **arg, char reply[REPLY_MAX])
-{
-    return movefiles();
-}
-
-static int do_linklib(char **arg, char reply[REPLY_MAX])
-{
-    return linklib(arg[0], arg[1], atoi(arg[2]));
-}
-
-struct cmdinfo {
-    const char *name;
-    unsigned numargs;
-    int (*func)(char **arg, char reply[REPLY_MAX]);
-};
-
-struct cmdinfo cmds[] = {
-    { "ping",                 0, do_ping },
-    { "install",              3, do_install },
-    { "dexopt",               3, do_dexopt },
-    { "movedex",              2, do_move_dex },
-    { "rmdex",                1, do_rm_dex },
-    { "remove",               2, do_remove },
-    { "rename",               2, do_rename },
-    { "fixuid",               3, do_fixuid },
-    { "freecache",            1, do_free_cache },
-    { "rmcache",              2, do_rm_cache },
-    { "getsize",              5, do_get_size },
-    { "rmuserdata",           2, do_rm_user_data },
-    { "movefiles",            0, do_movefiles },
-    { "linklib",              3, do_linklib },
-    { "mkuserdata",           3, do_mk_user_data },
-    { "rmuser",               1, do_rm_user },
-    { "cloneuserdata",        3, do_clone_user_data },
-};
-
-static int readx(int s, void *_buf, int count)
-{
-    char *buf = _buf;
-    int n = 0, r;
-    if (count < 0) return -1;
-    while (n < count) {
-        r = read(s, buf + n, count - n);
-        if (r < 0) {
-            if (errno == EINTR) continue;
-            ALOGE("read error: %s\n", strerror(errno));
-            return -1;
-        }
-        if (r == 0) {
-            ALOGE("eof\n");
-            return -1; /* EOF */
-        }
-        n += r;
-    }
-    return 0;
-}
-
-static int writex(int s, const void *_buf, int count)
-{
-    const char *buf = _buf;
-    int n = 0, r;
-    if (count < 0) return -1;
-    while (n < count) {
-        r = write(s, buf + n, count - n);
-        if (r < 0) {
-            if (errno == EINTR) continue;
-            ALOGE("write error: %s\n", strerror(errno));
-            return -1;
-        }
-        n += r;
-    }
-    return 0;
-}
-
-
-/* Tokenize the command buffer, locate a matching command,
- * ensure that the required number of arguments are provided,
- * call the function(), return the result.
- */
-static int execute(int s, char cmd[BUFFER_MAX])
-{
-    char reply[REPLY_MAX];
-    char *arg[TOKEN_MAX+1];
-    unsigned i;
-    unsigned n = 0;
-    unsigned short count;
-    int ret = -1;
-
-//    ALOGI("execute('%s')\n", cmd);
-
-        /* default reply is "" */
-    reply[0] = 0;
-
-        /* n is number of args (not counting arg[0]) */
-    arg[0] = cmd;
-    while (*cmd) {
-        if (isspace(*cmd)) {
-            *cmd++ = 0;
-            n++;
-            arg[n] = cmd;
-            if (n == TOKEN_MAX) {
-                ALOGE("too many arguments\n");
-                goto done;
-            }
-        }
-        cmd++;
-    }
-
-    for (i = 0; i < sizeof(cmds) / sizeof(cmds[0]); i++) {
-        if (!strcmp(cmds[i].name,arg[0])) {
-            if (n != cmds[i].numargs) {
-                ALOGE("%s requires %d arguments (%d given)\n",
-                     cmds[i].name, cmds[i].numargs, n);
-            } else {
-                ret = cmds[i].func(arg + 1, reply);
-            }
-            goto done;
-        }
-    }
-    ALOGE("unsupported command '%s'\n", arg[0]);
-
-done:
-    if (reply[0]) {
-        n = snprintf(cmd, BUFFER_MAX, "%d %s", ret, reply);
-    } else {
-        n = snprintf(cmd, BUFFER_MAX, "%d", ret);
-    }
-    if (n > BUFFER_MAX) n = BUFFER_MAX;
-    count = n;
-
-//    ALOGI("reply: '%s'\n", cmd);
-    if (writex(s, &count, sizeof(count))) return -1;
-    if (writex(s, cmd, count)) return -1;
-    return 0;
-}
-
-/**
- * Initialize all the global variables that are used elsewhere. Returns 0 upon
- * success and -1 on error.
- */
-void free_globals() {
-    size_t i;
-
-    for (i = 0; i < android_system_dirs.count; i++) {
-        if (android_system_dirs.dirs[i].path != NULL) {
-            free(android_system_dirs.dirs[i].path);
-        }
-    }
-
-    free(android_system_dirs.dirs);
-}
-
-int initialize_globals() {
-    // Get the android data directory.
-    if (get_path_from_env(&android_data_dir, "ANDROID_DATA") < 0) {
-        return -1;
-    }
-
-    // Get the android app directory.
-    if (copy_and_append(&android_app_dir, &android_data_dir, APP_SUBDIR) < 0) {
-        return -1;
-    }
-
-    // Get the android protected app directory.
-    if (copy_and_append(&android_app_private_dir, &android_data_dir, PRIVATE_APP_SUBDIR) < 0) {
-        return -1;
-    }
-
-    // Get the android app native library directory.
-    if (copy_and_append(&android_app_lib_dir, &android_data_dir, APP_LIB_SUBDIR) < 0) {
-        return -1;
-    }
-
-    // Get the sd-card ASEC mount point.
-    if (get_path_from_env(&android_asec_dir, "ASEC_MOUNTPOINT") < 0) {
-        return -1;
-    }
-
-    // Get the android media directory.
-    if (copy_and_append(&android_media_dir, &android_data_dir, MEDIA_SUBDIR) < 0) {
-        return -1;
-    }
-
-    // Take note of the system and vendor directories.
-    android_system_dirs.count = 2;
-
-    android_system_dirs.dirs = calloc(android_system_dirs.count, sizeof(dir_rec_t));
-    if (android_system_dirs.dirs == NULL) {
-        ALOGE("Couldn't allocate array for dirs; aborting\n");
-        return -1;
-    }
-
-    // system
-    if (get_path_from_env(&android_system_dirs.dirs[0], "ANDROID_ROOT") < 0) {
-        free_globals();
-        return -1;
-    }
-
-    // append "app/" to dirs[0]
-    char *system_app_path = build_string2(android_system_dirs.dirs[0].path, APP_SUBDIR);
-    android_system_dirs.dirs[0].path = system_app_path;
-    android_system_dirs.dirs[0].len = strlen(system_app_path);
-
-    // vendor
-    // TODO replace this with an environment variable (doesn't exist yet)
-    android_system_dirs.dirs[1].path = "/vendor/app/";
-    android_system_dirs.dirs[1].len = strlen(android_system_dirs.dirs[1].path);
-
-    return 0;
-}
-
-int initialize_directories() {
-    int res = -1;
-
-    // Read current filesystem layout version to handle upgrade paths
-    char version_path[PATH_MAX];
-    snprintf(version_path, PATH_MAX, "%s.layout_version", android_data_dir.path);
-
-    int oldVersion;
-    if (fs_read_atomic_int(version_path, &oldVersion) == -1) {
-        oldVersion = 0;
-    }
-    int version = oldVersion;
-
-    // /data/user
-    char *user_data_dir = build_string2(android_data_dir.path, SECONDARY_USER_PREFIX);
-    // /data/data
-    char *legacy_data_dir = build_string2(android_data_dir.path, PRIMARY_USER_PREFIX);
-    // /data/user/0
-    char *primary_data_dir = build_string3(android_data_dir.path, SECONDARY_USER_PREFIX, "0");
-    if (!user_data_dir || !legacy_data_dir || !primary_data_dir) {
-        goto fail;
-    }
-
-    // Make the /data/user directory if necessary
-    if (access(user_data_dir, R_OK) < 0) {
-        if (mkdir(user_data_dir, 0711) < 0) {
-            goto fail;
-        }
-        if (chown(user_data_dir, AID_SYSTEM, AID_SYSTEM) < 0) {
-            goto fail;
-        }
-        if (chmod(user_data_dir, 0711) < 0) {
-            goto fail;
-        }
-    }
-    // Make the /data/user/0 symlink to /data/data if necessary
-    if (access(primary_data_dir, R_OK) < 0) {
-        if (symlink(legacy_data_dir, primary_data_dir)) {
-            goto fail;
-        }
-    }
-
-    if (version == 0) {
-        // Introducing multi-user, so migrate /data/media contents into /data/media/0
-        ALOGD("Upgrading /data/media for multi-user");
-
-        // Ensure /data/media
-        if (fs_prepare_dir(android_media_dir.path, 0770, AID_MEDIA_RW, AID_MEDIA_RW) == -1) {
-            goto fail;
-        }
-
-        // /data/media.tmp
-        char media_tmp_dir[PATH_MAX];
-        snprintf(media_tmp_dir, PATH_MAX, "%smedia.tmp", android_data_dir.path);
-
-        // Only copy when upgrade not already in progress
-        if (access(media_tmp_dir, F_OK) == -1) {
-            if (rename(android_media_dir.path, media_tmp_dir) == -1) {
-                ALOGE("Failed to move legacy media path: %s", strerror(errno));
-                goto fail;
-            }
-        }
-
-        // Create /data/media again
-        if (fs_prepare_dir(android_media_dir.path, 0770, AID_MEDIA_RW, AID_MEDIA_RW) == -1) {
-            goto fail;
-        }
-
-        // /data/media/0
-        char owner_media_dir[PATH_MAX];
-        snprintf(owner_media_dir, PATH_MAX, "%s0", android_media_dir.path);
-
-        // Move any owner data into place
-        if (access(media_tmp_dir, F_OK) == 0) {
-            if (rename(media_tmp_dir, owner_media_dir) == -1) {
-                ALOGE("Failed to move owner media path: %s", strerror(errno));
-                goto fail;
-            }
-        }
-
-        // Ensure media directories for any existing users
-        DIR *dir;
-        struct dirent *dirent;
-        char user_media_dir[PATH_MAX];
-
-        dir = opendir(user_data_dir);
-        if (dir != NULL) {
-            while ((dirent = readdir(dir))) {
-                if (dirent->d_type == DT_DIR) {
-                    const char *name = dirent->d_name;
-
-                    // skip "." and ".."
-                    if (name[0] == '.') {
-                        if (name[1] == 0) continue;
-                        if ((name[1] == '.') && (name[2] == 0)) continue;
-                    }
-
-                    // /data/media/<user_id>
-                    snprintf(user_media_dir, PATH_MAX, "%s%s", android_media_dir.path, name);
-                    if (fs_prepare_dir(user_media_dir, 0770, AID_MEDIA_RW, AID_MEDIA_RW) == -1) {
-                        goto fail;
-                    }
-                }
-            }
-            closedir(dir);
-        }
-
-        version = 1;
-    }
-
-    // /data/media/obb
-    char media_obb_dir[PATH_MAX];
-    snprintf(media_obb_dir, PATH_MAX, "%sobb", android_media_dir.path);
-
-    if (version == 1) {
-        // Introducing /data/media/obb for sharing OBB across users; migrate
-        // any existing OBB files from owner.
-        ALOGD("Upgrading to shared /data/media/obb");
-
-        // /data/media/0/Android/obb
-        char owner_obb_path[PATH_MAX];
-        snprintf(owner_obb_path, PATH_MAX, "%s0/Android/obb", android_media_dir.path);
-
-        // Only move if target doesn't already exist
-        if (access(media_obb_dir, F_OK) != 0 && access(owner_obb_path, F_OK) == 0) {
-            if (rename(owner_obb_path, media_obb_dir) == -1) {
-                ALOGE("Failed to move OBB from owner: %s", strerror(errno));
-                goto fail;
-            }
-        }
-
-        version = 2;
-    }
-
-    if (ensure_media_user_dirs(0) == -1) {
-        ALOGE("Failed to setup media for user 0");
-        goto fail;
-    }
-    if (fs_prepare_dir(media_obb_dir, 0770, AID_MEDIA_RW, AID_MEDIA_RW) == -1) {
-        goto fail;
-    }
-
-    // Persist layout version if changed
-    if (version != oldVersion) {
-        if (fs_write_atomic_int(version_path, version) == -1) {
-            ALOGE("Failed to save version to %s: %s", version_path, strerror(errno));
-            goto fail;
-        }
-    }
-
-    // Success!
-    res = 0;
-
-fail:
-    free(user_data_dir);
-    free(legacy_data_dir);
-    free(primary_data_dir);
-    return res;
-}
-
-static void drop_privileges() {
-    if (prctl(PR_SET_KEEPCAPS, 1) < 0) {
-        ALOGE("prctl(PR_SET_KEEPCAPS) failed: %s\n", strerror(errno));
-        exit(1);
-    }
-
-    if (setgid(AID_INSTALL) < 0) {
-        ALOGE("setgid() can't drop privileges; exiting.\n");
-        exit(1);
-    }
-
-    if (setuid(AID_INSTALL) < 0) {
-        ALOGE("setuid() can't drop privileges; exiting.\n");
-        exit(1);
-    }
-
-    struct __user_cap_header_struct capheader;
-    struct __user_cap_data_struct capdata[2];
-    memset(&capheader, 0, sizeof(capheader));
-    memset(&capdata, 0, sizeof(capdata));
-    capheader.version = _LINUX_CAPABILITY_VERSION_3;
-    capheader.pid = 0;
-
-    capdata[CAP_TO_INDEX(CAP_DAC_OVERRIDE)].permitted |= CAP_TO_MASK(CAP_DAC_OVERRIDE);
-    capdata[CAP_TO_INDEX(CAP_CHOWN)].permitted        |= CAP_TO_MASK(CAP_CHOWN);
-    capdata[CAP_TO_INDEX(CAP_SETUID)].permitted       |= CAP_TO_MASK(CAP_SETUID);
-    capdata[CAP_TO_INDEX(CAP_SETGID)].permitted       |= CAP_TO_MASK(CAP_SETGID);
-
-    capdata[0].effective = capdata[0].permitted;
-    capdata[1].effective = capdata[1].permitted;
-    capdata[0].inheritable = 0;
-    capdata[1].inheritable = 0;
-
-    if (capset(&capheader, &capdata[0]) < 0) {
-        ALOGE("capset failed: %s\n", strerror(errno));
-        exit(1);
-    }
-}
-
-int main(const int argc, const char *argv[]) {
-    char buf[BUFFER_MAX];
-    struct sockaddr addr;
-    socklen_t alen;
-    int lsocket, s, count;
-
-    ALOGI("installd firing up\n");
-
-    if (initialize_globals() < 0) {
-        ALOGE("Could not initialize globals; exiting.\n");
-        exit(1);
-    }
-
-    if (initialize_directories() < 0) {
-        ALOGE("Could not create directories; exiting.\n");
-        exit(1);
-    }
-
-    drop_privileges();
-
-    lsocket = android_get_control_socket(SOCKET_PATH);
-    if (lsocket < 0) {
-        ALOGE("Failed to get socket from environment: %s\n", strerror(errno));
-        exit(1);
-    }
-    if (listen(lsocket, 5)) {
-        ALOGE("Listen on socket failed: %s\n", strerror(errno));
-        exit(1);
-    }
-    fcntl(lsocket, F_SETFD, FD_CLOEXEC);
-
-    for (;;) {
-        alen = sizeof(addr);
-        s = accept(lsocket, &addr, &alen);
-        if (s < 0) {
-            ALOGE("Accept failed: %s\n", strerror(errno));
-            continue;
-        }
-        fcntl(s, F_SETFD, FD_CLOEXEC);
-
-        ALOGI("new connection\n");
-        for (;;) {
-            unsigned short count;
-            if (readx(s, &count, sizeof(count))) {
-                ALOGE("failed to read size\n");
-                break;
-            }
-            if ((count < 1) || (count >= BUFFER_MAX)) {
-                ALOGE("invalid size %d\n", count);
-                break;
-            }
-            if (readx(s, buf, count)) {
-                ALOGE("failed to read command\n");
-                break;
-            }
-            buf[count] = 0;
-            if (execute(s, buf)) break;
-        }
-        ALOGI("closing connection\n");
-        close(s);
-    }
-
-    return 0;
-}
diff --git a/cmds/installd/installd.h b/cmds/installd/installd.h
deleted file mode 100644
index 0500c23..0000000
--- a/cmds/installd/installd.h
+++ /dev/null
@@ -1,213 +0,0 @@
-/*
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License"); 
-** you may not use this file except in compliance with the License. 
-** You may obtain a copy of the License at 
-**
-**     http://www.apache.org/licenses/LICENSE-2.0 
-**
-** Unless required by applicable law or agreed to in writing, software 
-** distributed under the License is distributed on an "AS IS" BASIS, 
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
-** See the License for the specific language governing permissions and 
-** limitations under the License.
-*/
-
-#define LOG_TAG "installd"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdint.h>
-#include <inttypes.h>
-#include <sys/stat.h>
-#include <dirent.h>
-#include <unistd.h>
-#include <ctype.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <utime.h>
-#include <sys/socket.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-
-#include <cutils/fs.h>
-#include <cutils/sockets.h>
-#include <cutils/log.h>
-#include <cutils/properties.h>
-#include <cutils/multiuser.h>
-
-#include <private/android_filesystem_config.h>
-
-#if INCLUDE_SYS_MOUNT_FOR_STATFS
-#include <sys/mount.h>
-#else
-#include <sys/statfs.h>
-#endif
-
-#define SOCKET_PATH "installd"
-
-
-/* elements combined with a valid package name to form paths */
-
-#define PRIMARY_USER_PREFIX    "data/"
-#define SECONDARY_USER_PREFIX  "user/"
-
-#define PKG_DIR_POSTFIX        ""
-
-#define PKG_LIB_POSTFIX        "/lib"
-
-#define CACHE_DIR_POSTFIX      "/cache"
-
-#define APP_SUBDIR             "app/" // sub-directory under ANDROID_DATA
-
-#define APP_LIB_SUBDIR         "app-lib/" // sub-directory under ANDROID_DATA
-
-#define MEDIA_SUBDIR           "media/" // sub-directory under ANDROID_DATA
-
-/* other handy constants */
-
-#define PRIVATE_APP_SUBDIR     "app-private/" // sub-directory under ANDROID_DATA
-
-#define DALVIK_CACHE_PREFIX    "/data/dalvik-cache/"
-#define DALVIK_CACHE_POSTFIX   "/classes.dex"
-
-#define UPDATE_COMMANDS_DIR_PREFIX  "/system/etc/updatecmds/"
-
-#define PKG_NAME_MAX  128   /* largest allowed package name */
-#define PKG_PATH_MAX  256   /* max size of any path we use */
-
-#define PER_USER_RANGE ((uid_t)100000)   /* range of uids per user
-                                            uid = persona * PER_USER_RANGE + appid */
-
-/* data structures */
-
-typedef struct {
-    char* path;
-    size_t len;
-} dir_rec_t;
-
-typedef struct {
-    size_t count;
-    dir_rec_t* dirs;
-} dir_rec_array_t;
-
-extern dir_rec_t android_app_dir;
-extern dir_rec_t android_app_private_dir;
-extern dir_rec_t android_app_lib_dir;
-extern dir_rec_t android_data_dir;
-extern dir_rec_t android_asec_dir;
-extern dir_rec_t android_media_dir;
-extern dir_rec_array_t android_system_dirs;
-
-typedef struct cache_dir_struct {
-    struct cache_dir_struct* parent;
-    int32_t childCount;
-    int32_t hiddenCount;
-    int32_t deleted;
-    char name[];
-} cache_dir_t;
-
-typedef struct {
-    cache_dir_t* dir;
-    time_t modTime;
-    char name[];
-} cache_file_t;
-
-typedef struct {
-    size_t numDirs;
-    size_t availDirs;
-    cache_dir_t** dirs;
-    size_t numFiles;
-    size_t availFiles;
-    cache_file_t** files;
-    size_t numCollected;
-    void* memBlocks;
-    int8_t* curMemBlockAvail;
-    int8_t* curMemBlockEnd;
-} cache_t;
-
-/* util.c */
-
-int create_pkg_path_in_dir(char path[PKG_PATH_MAX],
-                                const dir_rec_t* dir,
-                                const char* pkgname,
-                                const char* postfix);
-
-int create_pkg_path(char path[PKG_PATH_MAX],
-                    const char *pkgname,
-                    const char *postfix,
-                    uid_t persona);
-
-int create_persona_path(char path[PKG_PATH_MAX],
-                    uid_t persona);
-
-int create_persona_media_path(char path[PKG_PATH_MAX], userid_t userid);
-
-int create_move_path(char path[PKG_PATH_MAX],
-                     const char* pkgname,
-                     const char* leaf,
-                     uid_t persona);
-
-int is_valid_package_name(const char* pkgname);
-
-int create_cache_path(char path[PKG_PATH_MAX], const char *src);
-
-int delete_dir_contents(const char *pathname,
-                        int also_delete_dir,
-                        const char *ignore);
-
-int delete_dir_contents_fd(int dfd, const char *name);
-
-int lookup_media_dir(char basepath[PATH_MAX], const char *dir);
-
-int64_t data_disk_free();
-
-cache_t* start_cache_collection();
-
-void add_cache_files(cache_t* cache, const char *basepath, const char *cachedir);
-
-void clear_cache_files(cache_t* cache, int64_t free_size);
-
-void finish_cache_collection(cache_t* cache);
-
-int validate_system_app_path(const char* path);
-
-int get_path_from_env(dir_rec_t* rec, const char* var);
-
-int get_path_from_string(dir_rec_t* rec, const char* path);
-
-int copy_and_append(dir_rec_t* dst, const dir_rec_t* src, const char* suffix);
-
-int validate_apk_path(const char *path);
-
-int append_and_increment(char** dst, const char* src, size_t* dst_size);
-
-char *build_string2(char *s1, char *s2);
-char *build_string3(char *s1, char *s2, char *s3);
-
-int ensure_dir(const char* path, mode_t mode, uid_t uid, gid_t gid);
-int ensure_media_user_dirs(userid_t userid);
-
-/* commands.c */
-
-int install(const char *pkgname, uid_t uid, gid_t gid);
-int uninstall(const char *pkgname, uid_t persona);
-int renamepkg(const char *oldpkgname, const char *newpkgname);
-int fix_uid(const char *pkgname, uid_t uid, gid_t gid);
-int delete_user_data(const char *pkgname, uid_t persona);
-int make_user_data(const char *pkgname, uid_t uid, uid_t persona);
-int delete_persona(uid_t persona);
-int clone_persona_data(uid_t src_persona, uid_t target_persona, int copy);
-int delete_cache(const char *pkgname, uid_t persona);
-int move_dex(const char *src, const char *dst);
-int rm_dex(const char *path);
-int protect(char *pkgname, gid_t gid);
-int get_size(const char *pkgname, int persona, const char *apkpath, const char *fwdlock_apkpath,
-             const char *asecpath, int64_t *codesize, int64_t *datasize, int64_t *cachesize,
-             int64_t *asecsize);
-int free_cache(int64_t free_size);
-int dexopt(const char *apk_path, uid_t uid, int is_public);
-int movefiles();
-int linklib(const char* target, const char* source, int userId);
diff --git a/cmds/installd/tests/Android.mk b/cmds/installd/tests/Android.mk
deleted file mode 100644
index c0192f4..0000000
--- a/cmds/installd/tests/Android.mk
+++ /dev/null
@@ -1,31 +0,0 @@
-# Build the unit tests for installd
-LOCAL_PATH := $(call my-dir)
-include $(CLEAR_VARS)
-
-# Build the unit tests.
-test_src_files := \
-    installd_utils_test.cpp
-
-shared_libraries := \
-    libutils \
-    libcutils \
-    libstlport
-
-static_libraries := \
-    libinstalld \
-    libdiskusage \
-    libgtest \
-    libgtest_main
-
-c_includes := \
-    frameworks/base/cmds/installd
-
-$(foreach file,$(test_src_files), \
-    $(eval include $(CLEAR_VARS)) \
-    $(eval LOCAL_SHARED_LIBRARIES := $(shared_libraries)) \
-    $(eval LOCAL_STATIC_LIBRARIES := $(static_libraries)) \
-    $(eval LOCAL_SRC_FILES := $(file)) \
-    $(eval LOCAL_C_INCLUDES := $(c_includes)) \
-    $(eval LOCAL_MODULE := $(notdir $(file:%.cpp=%))) \
-    $(eval include $(BUILD_NATIVE_TEST)) \
-)
diff --git a/cmds/installd/tests/installd_utils_test.cpp b/cmds/installd/tests/installd_utils_test.cpp
deleted file mode 100644
index 7cb9b37..0000000
--- a/cmds/installd/tests/installd_utils_test.cpp
+++ /dev/null
@@ -1,437 +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.
- */
-
-#include <stdlib.h>
-#include <string.h>
-
-#define LOG_TAG "utils_test"
-#include <utils/Log.h>
-
-#include <gtest/gtest.h>
-
-extern "C" {
-#include "installd.h"
-}
-
-#define TEST_DATA_DIR "/data/"
-#define TEST_APP_DIR "/data/app/"
-#define TEST_APP_PRIVATE_DIR "/data/app-private/"
-#define TEST_ASEC_DIR "/mnt/asec/"
-
-#define TEST_SYSTEM_DIR1 "/system/app/"
-#define TEST_SYSTEM_DIR2 "/vendor/app/"
-
-#define REALLY_LONG_APP_NAME "com.example." \
-        "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa." \
-        "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa." \
-        "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
-
-#define REALLY_LONG_LEAF_NAME "shared_prefs_shared_prefs_shared_prefs_shared_prefs_shared_prefs_" \
-        "shared_prefs_shared_prefs_shared_prefs_shared_prefs_shared_prefs_shared_prefs_" \
-        "shared_prefs_shared_prefs_shared_prefs_shared_prefs_shared_prefs_shared_prefs_" \
-        "shared_prefs_shared_prefs_shared_prefs_shared_prefs_shared_prefs_shared_prefs_"
-
-namespace android {
-
-class UtilsTest : public testing::Test {
-protected:
-    virtual void SetUp() {
-        android_app_dir.path = TEST_APP_DIR;
-        android_app_dir.len = strlen(TEST_APP_DIR);
-
-        android_app_private_dir.path = TEST_APP_PRIVATE_DIR;
-        android_app_private_dir.len = strlen(TEST_APP_PRIVATE_DIR);
-
-        android_data_dir.path = TEST_DATA_DIR;
-        android_data_dir.len = strlen(TEST_DATA_DIR);
-
-        android_asec_dir.path = TEST_ASEC_DIR;
-        android_asec_dir.len = strlen(TEST_ASEC_DIR);
-
-        android_system_dirs.count = 2;
-
-        android_system_dirs.dirs = (dir_rec_t*) calloc(android_system_dirs.count, sizeof(dir_rec_t));
-        android_system_dirs.dirs[0].path = TEST_SYSTEM_DIR1;
-        android_system_dirs.dirs[0].len = strlen(TEST_SYSTEM_DIR1);
-
-        android_system_dirs.dirs[1].path = TEST_SYSTEM_DIR2;
-        android_system_dirs.dirs[1].len = strlen(TEST_SYSTEM_DIR2);
-    }
-
-    virtual void TearDown() {
-        free(android_system_dirs.dirs);
-    }
-};
-
-TEST_F(UtilsTest, IsValidApkPath_BadPrefix) {
-    // Bad prefixes directories
-    const char *badprefix1 = "/etc/passwd";
-    EXPECT_EQ(-1, validate_apk_path(badprefix1))
-            << badprefix1 << " should be allowed as a valid path";
-
-    const char *badprefix2 = "../.." TEST_APP_DIR "../../../blah";
-    EXPECT_EQ(-1, validate_apk_path(badprefix2))
-            << badprefix2 << " should be allowed as a valid path";
-
-    const char *badprefix3 = "init.rc";
-    EXPECT_EQ(-1, validate_apk_path(badprefix3))
-            << badprefix3 << " should be allowed as a valid path";
-
-    const char *badprefix4 = "/init.rc";
-    EXPECT_EQ(-1, validate_apk_path(badprefix4))
-            << badprefix4 << " should be allowed as a valid path";
-}
-
-TEST_F(UtilsTest, IsValidApkPath_Internal) {
-    // Internal directories
-    const char *internal1 = TEST_APP_DIR "example.apk";
-    EXPECT_EQ(0, validate_apk_path(internal1))
-            << internal1 << " should be allowed as a valid path";
-
-    const char *badint1 = TEST_APP_DIR "../example.apk";
-    EXPECT_EQ(-1, validate_apk_path(badint1))
-            << badint1 << " should be rejected as a invalid path";
-
-    const char *badint2 = TEST_APP_DIR "/../example.apk";
-    EXPECT_EQ(-1, validate_apk_path(badint2))
-            << badint2 << " should be rejected as a invalid path";
-
-    const char *badint3 = TEST_APP_DIR "example.com/pkg.apk";
-    EXPECT_EQ(-1, validate_apk_path(badint3))
-            << badint3 << " should be rejected as a invalid path";
-}
-
-TEST_F(UtilsTest, IsValidApkPath_Private) {
-    // Internal directories
-    const char *private1 = TEST_APP_PRIVATE_DIR "example.apk";
-    EXPECT_EQ(0, validate_apk_path(private1))
-            << private1 << " should be allowed as a valid path";
-
-    const char *badpriv1 = TEST_APP_PRIVATE_DIR "../example.apk";
-    EXPECT_EQ(-1, validate_apk_path(badpriv1))
-            << badpriv1 << " should be rejected as a invalid path";
-
-    const char *badpriv2 = TEST_APP_PRIVATE_DIR "/../example.apk";
-    EXPECT_EQ(-1, validate_apk_path(badpriv2))
-            << badpriv2 << " should be rejected as a invalid path";
-
-    const char *badpriv3 = TEST_APP_PRIVATE_DIR "example.com/pkg.apk";
-    EXPECT_EQ(-1, validate_apk_path(badpriv3))
-            << badpriv3 << " should be rejected as a invalid path";
-}
-
-
-TEST_F(UtilsTest, IsValidApkPath_AsecGood1) {
-    const char *asec1 = TEST_ASEC_DIR "example.apk";
-    EXPECT_EQ(0, validate_apk_path(asec1))
-            << asec1 << " should be allowed as a valid path";
-}
-
-TEST_F(UtilsTest, IsValidApkPath_AsecGood2) {
-    const char *asec2 = TEST_ASEC_DIR "com.example.asec/pkg.apk";
-    EXPECT_EQ(0, validate_apk_path(asec2))
-            << asec2 << " should be allowed as a valid path";
-}
-
-TEST_F(UtilsTest, IsValidApkPath_EscapeFail) {
-    const char *badasec1 = TEST_ASEC_DIR "../example.apk";
-    EXPECT_EQ(-1, validate_apk_path(badasec1))
-            << badasec1 << " should be rejected as a invalid path";
-}
-
-TEST_F(UtilsTest, IsValidApkPath_DoubleSlashFail) {
-    const char *badasec2 = TEST_ASEC_DIR "com.example.asec//pkg.apk";
-    EXPECT_EQ(-1, validate_apk_path(badasec2))
-            << badasec2 << " should be rejected as a invalid path";
-}
-
-TEST_F(UtilsTest, IsValidApkPath_SubdirEscapeFail) {
-    const char *badasec3 = TEST_ASEC_DIR "com.example.asec/../../../pkg.apk";
-    EXPECT_EQ(-1, validate_apk_path(badasec3))
-            << badasec3  << " should be rejected as a invalid path";
-}
-
-TEST_F(UtilsTest, IsValidApkPath_SlashEscapeFail) {
-    const char *badasec4 = TEST_ASEC_DIR "/../example.apk";
-    EXPECT_EQ(-1, validate_apk_path(badasec4))
-            << badasec4 << " should be rejected as a invalid path";
-}
-
-TEST_F(UtilsTest, IsValidApkPath_CrazyDirFail) {
-    const char *badasec5 = TEST_ASEC_DIR ".//../..";
-    EXPECT_EQ(-1, validate_apk_path(badasec5))
-            << badasec5 << " should be rejected as a invalid path";
-}
-
-TEST_F(UtilsTest, IsValidApkPath_SubdirEscapeSingleFail) {
-    const char *badasec6 = TEST_ASEC_DIR "com.example.asec/../pkg.apk";
-    EXPECT_EQ(-1, validate_apk_path(badasec6))
-            << badasec6 << " should be rejected as a invalid path";
-}
-
-TEST_F(UtilsTest, IsValidApkPath_TwoSubdirFail) {
-    const char *badasec7 = TEST_ASEC_DIR "com.example.asec/subdir1/pkg.apk";
-    EXPECT_EQ(-1, validate_apk_path(badasec7))
-            << badasec7 << " should be rejected as a invalid path";
-}
-
-TEST_F(UtilsTest, CheckSystemApp_Dir1) {
-    const char *sysapp1 = TEST_SYSTEM_DIR1 "Voice.apk";
-    EXPECT_EQ(0, validate_system_app_path(sysapp1))
-            << sysapp1 << " should be allowed as a system path";
-}
-
-TEST_F(UtilsTest, CheckSystemApp_Dir2) {
-    const char *sysapp2 = TEST_SYSTEM_DIR2 "com.example.myapp.apk";
-    EXPECT_EQ(0, validate_system_app_path(sysapp2))
-            << sysapp2 << " should be allowed as a system path";
-}
-
-TEST_F(UtilsTest, CheckSystemApp_EscapeFail) {
-    const char *badapp1 = TEST_SYSTEM_DIR1 "../com.example.apk";
-    EXPECT_EQ(-1, validate_system_app_path(badapp1))
-            << badapp1 << " should be rejected not a system path";
-}
-
-TEST_F(UtilsTest, CheckSystemApp_DoubleEscapeFail) {
-    const char *badapp2 = TEST_SYSTEM_DIR2 "/../../com.example.apk";
-    EXPECT_EQ(-1, validate_system_app_path(badapp2))
-            << badapp2 << " should be rejected not a system path";
-}
-
-TEST_F(UtilsTest, CheckSystemApp_BadPathEscapeFail) {
-    const char *badapp3 = TEST_APP_DIR "/../../com.example.apk";
-    EXPECT_EQ(-1, validate_system_app_path(badapp3))
-            << badapp3 << " should be rejected not a system path";
-}
-
-TEST_F(UtilsTest, GetPathFromString_NullPathFail) {
-    dir_rec_t test1;
-    EXPECT_EQ(-1, get_path_from_string(&test1, (const char *) NULL))
-            << "Should not allow NULL as a path.";
-}
-
-TEST_F(UtilsTest, GetPathFromString_EmptyPathFail) {
-    dir_rec_t test1;
-    EXPECT_EQ(-1, get_path_from_string(&test1, ""))
-            << "Should not allow empty paths.";
-}
-
-TEST_F(UtilsTest, GetPathFromString_RelativePathFail) {
-    dir_rec_t test1;
-    EXPECT_EQ(-1, get_path_from_string(&test1, "mnt/asec"))
-            << "Should not allow relative paths.";
-}
-
-TEST_F(UtilsTest, GetPathFromString_NonCanonical) {
-    dir_rec_t test1;
-
-    EXPECT_EQ(0, get_path_from_string(&test1, "/mnt/asec"))
-            << "Should be able to canonicalize directory /mnt/asec";
-    EXPECT_STREQ("/mnt/asec/", test1.path)
-            << "/mnt/asec should be canonicalized to /mnt/asec/";
-    EXPECT_EQ(10, (ssize_t) test1.len)
-            << "path len should be equal to the length of /mnt/asec/ (10)";
-    free(test1.path);
-}
-
-TEST_F(UtilsTest, GetPathFromString_CanonicalPath) {
-    dir_rec_t test3;
-    EXPECT_EQ(0, get_path_from_string(&test3, "/data/app/"))
-            << "Should be able to canonicalize directory /data/app/";
-    EXPECT_STREQ("/data/app/", test3.path)
-            << "/data/app/ should be canonicalized to /data/app/";
-    EXPECT_EQ(10, (ssize_t) test3.len)
-            << "path len should be equal to the length of /data/app/ (10)";
-    free(test3.path);
-}
-
-TEST_F(UtilsTest, CreatePkgPath_LongPkgNameSuccess) {
-    char path[PKG_PATH_MAX];
-
-    // Create long packagename of "aaaaa..."
-    size_t pkgnameSize = PKG_NAME_MAX;
-    char pkgname[pkgnameSize + 1];
-    memset(pkgname, 'a', pkgnameSize);
-    pkgname[pkgnameSize] = '\0';
-
-    EXPECT_EQ(0, create_pkg_path(path, pkgname, "", 0))
-            << "Should successfully be able to create package name.";
-
-    const char *prefix = TEST_DATA_DIR PRIMARY_USER_PREFIX;
-    size_t offset = strlen(prefix);
-    EXPECT_STREQ(pkgname, path + offset)
-             << "Package path should be a really long string of a's";
-}
-
-TEST_F(UtilsTest, CreatePkgPath_LongPkgNameFail) {
-    char path[PKG_PATH_MAX];
-
-    // Create long packagename of "aaaaa..."
-    size_t pkgnameSize = PKG_NAME_MAX + 1;
-    char pkgname[pkgnameSize + 1];
-    memset(pkgname, 'a', pkgnameSize);
-    pkgname[pkgnameSize] = '\0';
-
-    EXPECT_EQ(-1, create_pkg_path(path, pkgname, "", 0))
-            << "Should return error because package name is too long.";
-}
-
-TEST_F(UtilsTest, CreatePkgPath_LongPostfixFail) {
-    char path[PKG_PATH_MAX];
-
-    // Create long packagename of "aaaaa..."
-    size_t postfixSize = PKG_PATH_MAX;
-    char postfix[postfixSize + 1];
-    memset(postfix, 'a', postfixSize);
-    postfix[postfixSize] = '\0';
-
-    EXPECT_EQ(-1, create_pkg_path(path, "com.example.package", postfix, 0))
-            << "Should return error because postfix is too long.";
-}
-
-TEST_F(UtilsTest, CreatePkgPath_PrimaryUser) {
-    char path[PKG_PATH_MAX];
-
-    EXPECT_EQ(0, create_pkg_path(path, "com.example.package", "", 0))
-            << "Should return error because postfix is too long.";
-
-    EXPECT_STREQ(TEST_DATA_DIR PRIMARY_USER_PREFIX "com.example.package", path)
-            << "Package path should be in /data/data/";
-}
-
-TEST_F(UtilsTest, CreatePkgPath_SecondaryUser) {
-    char path[PKG_PATH_MAX];
-
-    EXPECT_EQ(0, create_pkg_path(path, "com.example.package", "", 1))
-            << "Should successfully create package path.";
-
-    EXPECT_STREQ(TEST_DATA_DIR SECONDARY_USER_PREFIX "1/com.example.package", path)
-            << "Package path should be in /data/user/";
-}
-
-TEST_F(UtilsTest, CreatePkgPathInDir_ProtectedDir) {
-    char path[PKG_PATH_MAX];
-
-    dir_rec_t dir;
-    dir.path = "/data/app-private/";
-    dir.len = strlen(dir.path);
-
-    EXPECT_EQ(0, create_pkg_path_in_dir(path, &dir, "com.example.package", ".apk"))
-            << "Should successfully create package path.";
-
-    EXPECT_STREQ("/data/app-private/com.example.package.apk", path)
-            << "Package path should be in /data/app-private/";
-}
-
-TEST_F(UtilsTest, CreatePersonaPath_Primary) {
-    char path[PKG_PATH_MAX];
-
-    EXPECT_EQ(0, create_persona_path(path, 0))
-            << "Should successfully build primary user path.";
-
-    EXPECT_STREQ("/data/data/", path)
-            << "Primary user should have correct path";
-}
-
-TEST_F(UtilsTest, CreatePersonaPath_Secondary) {
-    char path[PKG_PATH_MAX];
-
-    EXPECT_EQ(0, create_persona_path(path, 1))
-            << "Should successfully build primary user path.";
-
-    EXPECT_STREQ("/data/user/1/", path)
-            << "Primary user should have correct path";
-}
-
-TEST_F(UtilsTest, CreateMovePath_Primary) {
-    char path[PKG_PATH_MAX];
-
-    EXPECT_EQ(0, create_move_path(path, "com.android.test", "shared_prefs", 0))
-            << "Should be able to create move path for primary user";
-
-    EXPECT_STREQ("/data/data/com.android.test/shared_prefs", path)
-            << "Primary user package directory should be created correctly";
-}
-
-TEST_F(UtilsTest, CreateMovePath_Fail_AppTooLong) {
-    char path[PKG_PATH_MAX];
-
-    EXPECT_EQ(-1, create_move_path(path, REALLY_LONG_APP_NAME, "shared_prefs", 0))
-            << "Should fail to create move path for primary user";
-}
-
-TEST_F(UtilsTest, CreateMovePath_Fail_LeafTooLong) {
-    char path[PKG_PATH_MAX];
-
-    EXPECT_EQ(-1, create_move_path(path, "com.android.test", REALLY_LONG_LEAF_NAME, 0))
-            << "Should fail to create move path for primary user";
-}
-
-TEST_F(UtilsTest, CopyAndAppend_Normal) {
-    //int copy_and_append(dir_rec_t* dst, dir_rec_t* src, char* suffix)
-    dir_rec_t dst;
-    dir_rec_t src;
-
-    src.path = "/data/";
-    src.len = strlen(src.path);
-
-    EXPECT_EQ(0, copy_and_append(&dst, &src, "app/"))
-            << "Should return error because postfix is too long.";
-
-    EXPECT_STREQ("/data/app/", dst.path)
-            << "Appended path should be correct";
-
-    EXPECT_EQ(10, (ssize_t) dst.len)
-            << "Appended path should be length of '/data/app/' (10)";
-}
-
-TEST_F(UtilsTest, AppendAndIncrement_Normal) {
-    size_t dst_size = 10;
-    char dst[dst_size];
-    char *dstp = dst;
-    const char* src = "FOO";
-
-    EXPECT_EQ(0, append_and_increment(&dstp, src, &dst_size))
-            << "String should append successfully";
-
-    EXPECT_STREQ("FOO", dst)
-            << "String should append correctly";
-
-    EXPECT_EQ(0, append_and_increment(&dstp, src, &dst_size))
-            << "String should append successfully again";
-
-    EXPECT_STREQ("FOOFOO", dst)
-            << "String should append correctly again";
-}
-
-TEST_F(UtilsTest, AppendAndIncrement_TooBig) {
-    size_t dst_size = 5;
-    char dst[dst_size];
-    char *dstp = dst;
-    const char* src = "FOO";
-
-    EXPECT_EQ(0, append_and_increment(&dstp, src, &dst_size))
-            << "String should append successfully";
-
-    EXPECT_STREQ("FOO", dst)
-            << "String should append correctly";
-
-    EXPECT_EQ(-1, append_and_increment(&dstp, src, &dst_size))
-            << "String should fail because it's too large to fit";
-}
-
-}
diff --git a/cmds/installd/utils.c b/cmds/installd/utils.c
deleted file mode 100644
index 625a35e..0000000
--- a/cmds/installd/utils.c
+++ /dev/null
@@ -1,1006 +0,0 @@
-/*
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License"); 
-** you may not use this file except in compliance with the License. 
-** You may obtain a copy of the License at 
-**
-**     http://www.apache.org/licenses/LICENSE-2.0 
-**
-** Unless required by applicable law or agreed to in writing, software 
-** distributed under the License is distributed on an "AS IS" BASIS, 
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
-** See the License for the specific language governing permissions and 
-** limitations under the License.
-*/
-
-#include "installd.h"
-
-#define CACHE_NOISY(x) //x
-
-int create_pkg_path_in_dir(char path[PKG_PATH_MAX],
-                                const dir_rec_t* dir,
-                                const char* pkgname,
-                                const char* postfix)
-{
-     const size_t postfix_len = strlen(postfix);
-
-     const size_t pkgname_len = strlen(pkgname);
-     if (pkgname_len > PKG_NAME_MAX) {
-         return -1;
-     }
-
-     if (is_valid_package_name(pkgname) < 0) {
-         return -1;
-     }
-
-     if ((pkgname_len + dir->len + postfix_len) >= PKG_PATH_MAX) {
-         return -1;
-     }
-
-     char *dst = path;
-     size_t dst_size = PKG_PATH_MAX;
-
-     if (append_and_increment(&dst, dir->path, &dst_size) < 0
-             || append_and_increment(&dst, pkgname, &dst_size) < 0
-             || append_and_increment(&dst, postfix, &dst_size) < 0) {
-         ALOGE("Error building APK path");
-         return -1;
-     }
-
-     return 0;
-}
-
-/**
- * Create the package path name for a given package name with a postfix for
- * a certain persona. Returns 0 on success, and -1 on failure.
- */
-int create_pkg_path(char path[PKG_PATH_MAX],
-                    const char *pkgname,
-                    const char *postfix,
-                    uid_t persona)
-{
-    size_t uid_len;
-    char* persona_prefix;
-    if (persona == 0) {
-        persona_prefix = PRIMARY_USER_PREFIX;
-        uid_len = 0;
-    } else {
-        persona_prefix = SECONDARY_USER_PREFIX;
-        uid_len = snprintf(NULL, 0, "%d", persona);
-    }
-
-    const size_t prefix_len = android_data_dir.len + strlen(persona_prefix) + uid_len + 1 /*slash*/;
-    char prefix[prefix_len + 1];
-
-    char *dst = prefix;
-    size_t dst_size = sizeof(prefix);
-
-    if (append_and_increment(&dst, android_data_dir.path, &dst_size) < 0
-            || append_and_increment(&dst, persona_prefix, &dst_size) < 0) {
-        ALOGE("Error building prefix for APK path");
-        return -1;
-    }
-
-    if (persona != 0) {
-        int ret = snprintf(dst, dst_size, "%d/", persona);
-        if (ret < 0 || (size_t) ret != uid_len + 1) {
-            ALOGW("Error appending UID to APK path");
-            return -1;
-        }
-    }
-
-    dir_rec_t dir;
-    dir.path = prefix;
-    dir.len = prefix_len;
-
-    return create_pkg_path_in_dir(path, &dir, pkgname, postfix);
-}
-
-/**
- * Create the path name for user data for a certain persona.
- * Returns 0 on success, and -1 on failure.
- */
-int create_persona_path(char path[PKG_PATH_MAX],
-                    uid_t persona)
-{
-    size_t uid_len;
-    char* persona_prefix;
-    if (persona == 0) {
-        persona_prefix = PRIMARY_USER_PREFIX;
-        uid_len = 0;
-    } else {
-        persona_prefix = SECONDARY_USER_PREFIX;
-        uid_len = snprintf(NULL, 0, "%d/", persona);
-    }
-
-    char *dst = path;
-    size_t dst_size = PKG_PATH_MAX;
-
-    if (append_and_increment(&dst, android_data_dir.path, &dst_size) < 0
-            || append_and_increment(&dst, persona_prefix, &dst_size) < 0) {
-        ALOGE("Error building prefix for user path");
-        return -1;
-    }
-
-    if (persona != 0) {
-        if (dst_size < uid_len + 1) {
-            ALOGE("Error building user path");
-            return -1;
-        }
-        int ret = snprintf(dst, dst_size, "%d/", persona);
-        if (ret < 0 || (size_t) ret != uid_len) {
-            ALOGE("Error appending persona id to path");
-            return -1;
-        }
-    }
-    return 0;
-}
-
-/**
- * Create the path name for media for a certain persona.
- * Returns 0 on success, and -1 on failure.
- */
-int create_persona_media_path(char path[PATH_MAX], userid_t userid) {
-    if (snprintf(path, PATH_MAX, "%s%d", android_media_dir.path, userid) > PATH_MAX) {
-        return -1;
-    }
-    return 0;
-}
-
-int create_move_path(char path[PKG_PATH_MAX],
-    const char* pkgname,
-    const char* leaf,
-    uid_t persona)
-{
-    if ((android_data_dir.len + strlen(PRIMARY_USER_PREFIX) + strlen(pkgname) + strlen(leaf) + 1)
-            >= PKG_PATH_MAX) {
-        return -1;
-    }
-
-    sprintf(path, "%s%s%s/%s", android_data_dir.path, PRIMARY_USER_PREFIX, pkgname, leaf);
-    return 0;
-}
-
-/**
- * Checks whether the package name is valid. Returns -1 on error and
- * 0 on success.
- */
-int is_valid_package_name(const char* pkgname) {
-    const char *x = pkgname;
-    int alpha = -1;
-
-    while (*x) {
-        if (isalnum(*x) || (*x == '_')) {
-                /* alphanumeric or underscore are fine */
-        } else if (*x == '.') {
-            if ((x == pkgname) || (x[1] == '.') || (x[1] == 0)) {
-                    /* periods must not be first, last, or doubled */
-                ALOGE("invalid package name '%s'\n", pkgname);
-                return -1;
-            }
-        } else if (*x == '-') {
-            /* Suffix -X is fine to let versioning of packages.
-               But whatever follows should be alphanumeric.*/
-            alpha = 1;
-        } else {
-                /* anything not A-Z, a-z, 0-9, _, or . is invalid */
-            ALOGE("invalid package name '%s'\n", pkgname);
-            return -1;
-        }
-
-        x++;
-    }
-
-    if (alpha == 1) {
-        // Skip current character
-        x++;
-        while (*x) {
-            if (!isalnum(*x)) {
-                ALOGE("invalid package name '%s' should include only numbers after -\n", pkgname);
-                return -1;
-            }
-            x++;
-        }
-    }
-
-    return 0;
-}
-
-static int _delete_dir_contents(DIR *d, const char *ignore)
-{
-    int result = 0;
-    struct dirent *de;
-    int dfd;
-
-    dfd = dirfd(d);
-
-    if (dfd < 0) return -1;
-
-    while ((de = readdir(d))) {
-        const char *name = de->d_name;
-
-            /* skip the ignore name if provided */
-        if (ignore && !strcmp(name, ignore)) continue;
-
-        if (de->d_type == DT_DIR) {
-            int r, subfd;
-            DIR *subdir;
-
-                /* always skip "." and ".." */
-            if (name[0] == '.') {
-                if (name[1] == 0) continue;
-                if ((name[1] == '.') && (name[2] == 0)) continue;
-            }
-
-            subfd = openat(dfd, name, O_RDONLY | O_DIRECTORY);
-            if (subfd < 0) {
-                ALOGE("Couldn't openat %s: %s\n", name, strerror(errno));
-                result = -1;
-                continue;
-            }
-            subdir = fdopendir(subfd);
-            if (subdir == NULL) {
-                ALOGE("Couldn't fdopendir %s: %s\n", name, strerror(errno));
-                close(subfd);
-                result = -1;
-                continue;
-            }
-            if (_delete_dir_contents(subdir, 0)) {
-                result = -1;
-            }
-            closedir(subdir);
-            if (unlinkat(dfd, name, AT_REMOVEDIR) < 0) {
-                ALOGE("Couldn't unlinkat %s: %s\n", name, strerror(errno));
-                result = -1;
-            }
-        } else {
-            if (unlinkat(dfd, name, 0) < 0) {
-                ALOGE("Couldn't unlinkat %s: %s\n", name, strerror(errno));
-                result = -1;
-            }
-        }
-    }
-
-    return result;
-}
-
-int delete_dir_contents(const char *pathname,
-                        int also_delete_dir,
-                        const char *ignore)
-{
-    int res = 0;
-    DIR *d;
-
-    d = opendir(pathname);
-    if (d == NULL) {
-        ALOGE("Couldn't opendir %s: %s\n", pathname, strerror(errno));
-        return -errno;
-    }
-    res = _delete_dir_contents(d, ignore);
-    closedir(d);
-    if (also_delete_dir) {
-        if (rmdir(pathname)) {
-            ALOGE("Couldn't rmdir %s: %s\n", pathname, strerror(errno));
-            res = -1;
-        }
-    }
-    return res;
-}
-
-int delete_dir_contents_fd(int dfd, const char *name)
-{
-    int fd, res;
-    DIR *d;
-
-    fd = openat(dfd, name, O_RDONLY | O_DIRECTORY);
-    if (fd < 0) {
-        ALOGE("Couldn't openat %s: %s\n", name, strerror(errno));
-        return -1;
-    }
-    d = fdopendir(fd);
-    if (d == NULL) {
-        ALOGE("Couldn't fdopendir %s: %s\n", name, strerror(errno));
-        close(fd);
-        return -1;
-    }
-    res = _delete_dir_contents(d, 0);
-    closedir(d);
-    return res;
-}
-
-int lookup_media_dir(char basepath[PATH_MAX], const char *dir)
-{
-    DIR *d;
-    struct dirent *de;
-    struct stat s;
-    char* dirpos = basepath + strlen(basepath);
-
-    if ((*(dirpos-1)) != '/') {
-        *dirpos = '/';
-        dirpos++;
-    }
-
-    CACHE_NOISY(ALOGI("Looking up %s in %s\n", dir, basepath));
-    // Verify the path won't extend beyond our buffer, to avoid
-    // repeated checking later.
-    if ((dirpos-basepath+strlen(dir)) >= (PATH_MAX-1)) {
-        ALOGW("Path exceeds limit: %s%s", basepath, dir);
-        return -1;
-    }
-
-    // First, can we find this directory with the case that is given?
-    strcpy(dirpos, dir);
-    if (stat(basepath, &s) >= 0) {
-        CACHE_NOISY(ALOGI("Found direct: %s\n", basepath));
-        return 0;
-    }
-
-    // Not found with that case...  search through all entries to find
-    // one that matches regardless of case.
-    *dirpos = 0;
-
-    d = opendir(basepath);
-    if (d == NULL) {
-        return -1;
-    }
-
-    while ((de = readdir(d))) {
-        if (strcasecmp(de->d_name, dir) == 0) {
-            strcpy(dirpos, de->d_name);
-            closedir(d);
-            CACHE_NOISY(ALOGI("Found search: %s\n", basepath));
-            return 0;
-        }
-    }
-
-    ALOGW("Couldn't find %s in %s", dir, basepath);
-    closedir(d);
-    return -1;
-}
-
-int64_t data_disk_free()
-{
-    struct statfs sfs;
-    if (statfs(android_data_dir.path, &sfs) == 0) {
-        return sfs.f_bavail * sfs.f_bsize;
-    } else {
-        ALOGE("Couldn't statfs %s: %s\n", android_data_dir.path, strerror(errno));
-        return -1;
-    }
-}
-
-cache_t* start_cache_collection()
-{
-    cache_t* cache = (cache_t*)calloc(1, sizeof(cache_t));
-    return cache;
-}
-
-#define CACHE_BLOCK_SIZE (512*1024)
-
-static void* _cache_malloc(cache_t* cache, size_t len)
-{
-    len = (len+3)&~3;
-    if (len > (CACHE_BLOCK_SIZE/2)) {
-        // It doesn't make sense to try to put this allocation into one
-        // of our blocks, because it is so big.  Instead, make a new dedicated
-        // block for it.
-        int8_t* res = (int8_t*)malloc(len+sizeof(void*));
-        if (res == NULL) {
-            return NULL;
-        }
-        CACHE_NOISY(ALOGI("Allocated large cache mem block: %p size %d", res, len));
-        // Link it into our list of blocks, not disrupting the current one.
-        if (cache->memBlocks == NULL) {
-            *(void**)res = NULL;
-            cache->memBlocks = res;
-        } else {
-            *(void**)res = *(void**)cache->memBlocks;
-            *(void**)cache->memBlocks = res;
-        }
-        return res + sizeof(void*);
-    }
-    int8_t* res = cache->curMemBlockAvail;
-    int8_t* nextPos = res + len;
-    if (cache->memBlocks == NULL || nextPos > cache->curMemBlockEnd) {
-        int8_t* newBlock = malloc(CACHE_BLOCK_SIZE);
-        if (newBlock == NULL) {
-            return NULL;
-        }
-        CACHE_NOISY(ALOGI("Allocated new cache mem block: %p", newBlock));
-        *(void**)newBlock = cache->memBlocks;
-        cache->memBlocks = newBlock;
-        res = cache->curMemBlockAvail = newBlock + sizeof(void*);
-        cache->curMemBlockEnd = newBlock + CACHE_BLOCK_SIZE;
-        nextPos = res + len;
-    }
-    CACHE_NOISY(ALOGI("cache_malloc: ret %p size %d, block=%p, nextPos=%p",
-            res, len, cache->memBlocks, nextPos));
-    cache->curMemBlockAvail = nextPos;
-    return res;
-}
-
-static void* _cache_realloc(cache_t* cache, void* cur, size_t origLen, size_t len)
-{
-    // This isn't really a realloc, but it is good enough for our purposes here.
-    void* alloc = _cache_malloc(cache, len);
-    if (alloc != NULL && cur != NULL) {
-        memcpy(alloc, cur, origLen < len ? origLen : len);
-    }
-    return alloc;
-}
-
-static void _inc_num_cache_collected(cache_t* cache)
-{
-    cache->numCollected++;
-    if ((cache->numCollected%20000) == 0) {
-        ALOGI("Collected cache so far: %d directories, %d files",
-            cache->numDirs, cache->numFiles);
-    }
-}
-
-static cache_dir_t* _add_cache_dir_t(cache_t* cache, cache_dir_t* parent, const char *name)
-{
-    size_t nameLen = strlen(name);
-    cache_dir_t* dir = (cache_dir_t*)_cache_malloc(cache, sizeof(cache_dir_t)+nameLen+1);
-    if (dir != NULL) {
-        dir->parent = parent;
-        dir->childCount = 0;
-        dir->hiddenCount = 0;
-        dir->deleted = 0;
-        strcpy(dir->name, name);
-        if (cache->numDirs >= cache->availDirs) {
-            size_t newAvail = cache->availDirs < 1000 ? 1000 : cache->availDirs*2;
-            cache_dir_t** newDirs = (cache_dir_t**)_cache_realloc(cache, cache->dirs,
-                    cache->availDirs*sizeof(cache_dir_t*), newAvail*sizeof(cache_dir_t*));
-            if (newDirs == NULL) {
-                ALOGE("Failure growing cache dirs array for %s\n", name);
-                return NULL;
-            }
-            cache->availDirs = newAvail;
-            cache->dirs = newDirs;
-        }
-        cache->dirs[cache->numDirs] = dir;
-        cache->numDirs++;
-        if (parent != NULL) {
-            parent->childCount++;
-        }
-        _inc_num_cache_collected(cache);
-    } else {
-        ALOGE("Failure allocating cache_dir_t for %s\n", name);
-    }
-    return dir;
-}
-
-static cache_file_t* _add_cache_file_t(cache_t* cache, cache_dir_t* dir, time_t modTime,
-        const char *name)
-{
-    size_t nameLen = strlen(name);
-    cache_file_t* file = (cache_file_t*)_cache_malloc(cache, sizeof(cache_file_t)+nameLen+1);
-    if (file != NULL) {
-        file->dir = dir;
-        file->modTime = modTime;
-        strcpy(file->name, name);
-        if (cache->numFiles >= cache->availFiles) {
-            size_t newAvail = cache->availFiles < 1000 ? 1000 : cache->availFiles*2;
-            cache_file_t** newFiles = (cache_file_t**)_cache_realloc(cache, cache->files,
-                    cache->availFiles*sizeof(cache_file_t*), newAvail*sizeof(cache_file_t*));
-            if (newFiles == NULL) {
-                ALOGE("Failure growing cache file array for %s\n", name);
-                return NULL;
-            }
-            cache->availFiles = newAvail;
-            cache->files = newFiles;
-        }
-        CACHE_NOISY(ALOGI("Setting file %p at position %d in array %p", file,
-                cache->numFiles, cache->files));
-        cache->files[cache->numFiles] = file;
-        cache->numFiles++;
-        dir->childCount++;
-        _inc_num_cache_collected(cache);
-    } else {
-        ALOGE("Failure allocating cache_file_t for %s\n", name);
-    }
-    return file;
-}
-
-static int _add_cache_files(cache_t *cache, cache_dir_t *parentDir, const char *dirName,
-        DIR* dir, char *pathBase, char *pathPos, size_t pathAvailLen)
-{
-    struct dirent *de;
-    cache_dir_t* cacheDir = NULL;
-    int dfd;
-
-    CACHE_NOISY(ALOGI("_add_cache_files: parent=%p dirName=%s dir=%p pathBase=%s",
-            parentDir, dirName, dir, pathBase));
-
-    dfd = dirfd(dir);
-
-    if (dfd < 0) return 0;
-
-    // Sub-directories always get added to the data structure, so if they
-    // are empty we will know about them to delete them later.
-    cacheDir = _add_cache_dir_t(cache, parentDir, dirName);
-
-    while ((de = readdir(dir))) {
-        const char *name = de->d_name;
-
-        if (de->d_type == DT_DIR) {
-            int subfd;
-            DIR *subdir;
-
-                /* always skip "." and ".." */
-            if (name[0] == '.') {
-                if (name[1] == 0) continue;
-                if ((name[1] == '.') && (name[2] == 0)) continue;
-            }
-
-            subfd = openat(dfd, name, O_RDONLY | O_DIRECTORY);
-            if (subfd < 0) {
-                ALOGE("Couldn't openat %s: %s\n", name, strerror(errno));
-                continue;
-            }
-            subdir = fdopendir(subfd);
-            if (subdir == NULL) {
-                ALOGE("Couldn't fdopendir %s: %s\n", name, strerror(errno));
-                close(subfd);
-                continue;
-            }
-            if (cacheDir == NULL) {
-                cacheDir = _add_cache_dir_t(cache, parentDir, dirName);
-            }
-            if (cacheDir != NULL) {
-                // Update pathBase for the new path...  this may change dirName
-                // if that is also pointing to the path, but we are done with it
-                // now.
-                size_t finallen = snprintf(pathPos, pathAvailLen, "/%s", name);
-                CACHE_NOISY(ALOGI("Collecting dir %s\n", pathBase));
-                if (finallen < pathAvailLen) {
-                    _add_cache_files(cache, cacheDir, name, subdir, pathBase,
-                            pathPos+finallen, pathAvailLen-finallen);
-                } else {
-                    // Whoops, the final path is too long!  We'll just delete
-                    // this directory.
-                    ALOGW("Cache dir %s truncated in path %s; deleting dir\n",
-                            name, pathBase);
-                    _delete_dir_contents(subdir, NULL);
-                    if (unlinkat(dfd, name, AT_REMOVEDIR) < 0) {
-                        ALOGE("Couldn't unlinkat %s: %s\n", name, strerror(errno));
-                    }
-                }
-            }
-            closedir(subdir);
-        } else if (de->d_type == DT_REG) {
-            // Skip files that start with '.'; they will be deleted if
-            // their entire directory is deleted.  This allows for metadata
-            // like ".nomedia" to remain in the directory until the entire
-            // directory is deleted.
-            if (cacheDir == NULL) {
-                cacheDir = _add_cache_dir_t(cache, parentDir, dirName);
-            }
-            if (name[0] == '.') {
-                cacheDir->hiddenCount++;
-                continue;
-            }
-            if (cacheDir != NULL) {
-                // Build final full path for file...  this may change dirName
-                // if that is also pointing to the path, but we are done with it
-                // now.
-                size_t finallen = snprintf(pathPos, pathAvailLen, "/%s", name);
-                CACHE_NOISY(ALOGI("Collecting file %s\n", pathBase));
-                if (finallen < pathAvailLen) {
-                    struct stat s;
-                    if (stat(pathBase, &s) >= 0) {
-                        _add_cache_file_t(cache, cacheDir, s.st_mtime, name);
-                    } else {
-                        ALOGW("Unable to stat cache file %s; deleting\n", pathBase);
-                        if (unlink(pathBase) < 0) {
-                            ALOGE("Couldn't unlink %s: %s\n", pathBase, strerror(errno));
-                        }
-                    }
-                } else {
-                    // Whoops, the final path is too long!  We'll just delete
-                    // this file.
-                    ALOGW("Cache file %s truncated in path %s; deleting\n",
-                            name, pathBase);
-                    if (unlinkat(dfd, name, 0) < 0) {
-                        *pathPos = 0;
-                        ALOGE("Couldn't unlinkat %s in %s: %s\n", name, pathBase,
-                                strerror(errno));
-                    }
-                }
-            }
-        } else {
-            cacheDir->hiddenCount++;
-        }
-    }
-    return 0;
-}
-
-void add_cache_files(cache_t* cache, const char *basepath, const char *cachedir)
-{
-    DIR *d;
-    struct dirent *de;
-    char dirname[PATH_MAX];
-
-    CACHE_NOISY(ALOGI("add_cache_files: base=%s cachedir=%s\n", basepath, cachedir));
-
-    d = opendir(basepath);
-    if (d == NULL) {
-        return;
-    }
-
-    while ((de = readdir(d))) {
-        if (de->d_type == DT_DIR) {
-            DIR* subdir;
-            const char *name = de->d_name;
-            char* pathpos;
-
-                /* always skip "." and ".." */
-            if (name[0] == '.') {
-                if (name[1] == 0) continue;
-                if ((name[1] == '.') && (name[2] == 0)) continue;
-            }
-
-            strcpy(dirname, basepath);
-            pathpos = dirname + strlen(dirname);
-            if ((*(pathpos-1)) != '/') {
-                *pathpos = '/';
-                pathpos++;
-                *pathpos = 0;
-            }
-            if (cachedir != NULL) {
-                snprintf(pathpos, sizeof(dirname)-(pathpos-dirname), "%s/%s", name, cachedir);
-            } else {
-                snprintf(pathpos, sizeof(dirname)-(pathpos-dirname), "%s", name);
-            }
-            CACHE_NOISY(ALOGI("Adding cache files from dir: %s\n", dirname));
-            subdir = opendir(dirname);
-            if (subdir != NULL) {
-                size_t dirnameLen = strlen(dirname);
-                _add_cache_files(cache, NULL, dirname, subdir, dirname, dirname+dirnameLen,
-                        PATH_MAX - dirnameLen);
-                closedir(subdir);
-            }
-        }
-    }
-
-    closedir(d);
-}
-
-static char *create_dir_path(char path[PATH_MAX], cache_dir_t* dir)
-{
-    char *pos = path;
-    if (dir->parent != NULL) {
-        pos = create_dir_path(path, dir->parent);
-    }
-    // Note that we don't need to worry about going beyond the buffer,
-    // since when we were constructing the cache entries our maximum
-    // buffer size for full paths was PATH_MAX.
-    strcpy(pos, dir->name);
-    pos += strlen(pos);
-    *pos = '/';
-    pos++;
-    *pos = 0;
-    return pos;
-}
-
-static void delete_cache_dir(char path[PATH_MAX], cache_dir_t* dir)
-{
-    if (dir->parent != NULL) {
-        create_dir_path(path, dir);
-        ALOGI("DEL DIR %s\n", path);
-        if (dir->hiddenCount <= 0) {
-            if (rmdir(path)) {
-                ALOGE("Couldn't rmdir %s: %s\n", path, strerror(errno));
-                return;
-            }
-        } else {
-            // The directory contains hidden files so we need to delete
-            // them along with the directory itself.
-            if (delete_dir_contents(path, 1, NULL)) {
-                return;
-            }
-        }
-        dir->parent->childCount--;
-        dir->deleted = 1;
-        if (dir->parent->childCount <= 0) {
-            delete_cache_dir(path, dir->parent);
-        }
-    } else if (dir->hiddenCount > 0) {
-        // This is a root directory, but it has hidden files.  Get rid of
-        // all of those files, but not the directory itself.
-        create_dir_path(path, dir);
-        ALOGI("DEL CONTENTS %s\n", path);
-        delete_dir_contents(path, 0, NULL);
-    }
-}
-
-static int cache_modtime_sort(const void *lhsP, const void *rhsP)
-{
-    const cache_file_t *lhs = *(const cache_file_t**)lhsP;
-    const cache_file_t *rhs = *(const cache_file_t**)rhsP;
-    return lhs->modTime < rhs->modTime ? -1 : (lhs->modTime > rhs->modTime ? 1 : 0);
-}
-
-void clear_cache_files(cache_t* cache, int64_t free_size)
-{
-    size_t i;
-    int skip = 0;
-    char path[PATH_MAX];
-
-    ALOGI("Collected cache files: %d directories, %d files",
-        cache->numDirs, cache->numFiles);
-
-    CACHE_NOISY(ALOGI("Sorting files..."));
-    qsort(cache->files, cache->numFiles, sizeof(cache_file_t*),
-            cache_modtime_sort);
-
-    CACHE_NOISY(ALOGI("Cleaning empty directories..."));
-    for (i=cache->numDirs; i>0; i--) {
-        cache_dir_t* dir = cache->dirs[i-1];
-        if (dir->childCount <= 0 && !dir->deleted) {
-            delete_cache_dir(path, dir);
-        }
-    }
-
-    CACHE_NOISY(ALOGI("Trimming files..."));
-    for (i=0; i<cache->numFiles; i++) {
-        skip++;
-        if (skip > 10) {
-            if (data_disk_free() > free_size) {
-                return;
-            }
-            skip = 0;
-        }
-        cache_file_t* file = cache->files[i];
-        strcpy(create_dir_path(path, file->dir), file->name);
-        ALOGI("DEL (mod %d) %s\n", (int)file->modTime, path);
-        if (unlink(path) < 0) {
-            ALOGE("Couldn't unlink %s: %s\n", path, strerror(errno));
-        }
-        file->dir->childCount--;
-        if (file->dir->childCount <= 0) {
-            delete_cache_dir(path, file->dir);
-        }
-    }
-}
-
-void finish_cache_collection(cache_t* cache)
-{
-    size_t i;
-
-    CACHE_NOISY(ALOGI("clear_cache_files: %d dirs, %d files\n", cache->numDirs, cache->numFiles));
-    CACHE_NOISY(
-        for (i=0; i<cache->numDirs; i++) {
-            cache_dir_t* dir = cache->dirs[i];
-            ALOGI("dir #%d: %p %s parent=%p\n", i, dir, dir->name, dir->parent);
-        })
-    CACHE_NOISY(
-        for (i=0; i<cache->numFiles; i++) {
-            cache_file_t* file = cache->files[i];
-            ALOGI("file #%d: %p %s time=%d dir=%p\n", i, file, file->name,
-                    (int)file->modTime, file->dir);
-        })
-    void* block = cache->memBlocks;
-    while (block != NULL) {
-        void* nextBlock = *(void**)block;
-        CACHE_NOISY(ALOGI("Freeing cache mem block: %p", block));
-        free(block);
-        block = nextBlock;
-    }
-    free(cache);
-}
-
-/**
- * Checks whether a path points to a system app (.apk file). Returns 0
- * if it is a system app or -1 if it is not.
- */
-int validate_system_app_path(const char* path) {
-    size_t i;
-
-    for (i = 0; i < android_system_dirs.count; i++) {
-        const size_t dir_len = android_system_dirs.dirs[i].len;
-        if (!strncmp(path, android_system_dirs.dirs[i].path, dir_len)) {
-            if (path[dir_len] == '.' || strchr(path + dir_len, '/') != NULL) {
-                ALOGE("invalid system apk path '%s' (trickery)\n", path);
-                return -1;
-            }
-            return 0;
-        }
-    }
-
-    return -1;
-}
-
-/**
- * Get the contents of a environment variable that contains a path. Caller
- * owns the string that is inserted into the directory record. Returns
- * 0 on success and -1 on error.
- */
-int get_path_from_env(dir_rec_t* rec, const char* var) {
-    const char* path = getenv(var);
-    int ret = get_path_from_string(rec, path);
-    if (ret < 0) {
-        ALOGW("Problem finding value for environment variable %s\n", var);
-    }
-    return ret;
-}
-
-/**
- * Puts the string into the record as a directory. Appends '/' to the end
- * of all paths. Caller owns the string that is inserted into the directory
- * record. A null value will result in an error.
- *
- * Returns 0 on success and -1 on error.
- */
-int get_path_from_string(dir_rec_t* rec, const char* path) {
-    if (path == NULL) {
-        return -1;
-    } else {
-        const size_t path_len = strlen(path);
-        if (path_len <= 0) {
-            return -1;
-        }
-
-        // Make sure path is absolute.
-        if (path[0] != '/') {
-            return -1;
-        }
-
-        if (path[path_len - 1] == '/') {
-            // Path ends with a forward slash. Make our own copy.
-
-            rec->path = strdup(path);
-            if (rec->path == NULL) {
-                return -1;
-            }
-
-            rec->len = path_len;
-        } else {
-            // Path does not end with a slash. Generate a new string.
-            char *dst;
-
-            // Add space for slash and terminating null.
-            size_t dst_size = path_len + 2;
-
-            rec->path = malloc(dst_size);
-            if (rec->path == NULL) {
-                return -1;
-            }
-
-            dst = rec->path;
-
-            if (append_and_increment(&dst, path, &dst_size) < 0
-                    || append_and_increment(&dst, "/", &dst_size)) {
-                ALOGE("Error canonicalizing path");
-                return -1;
-            }
-
-            rec->len = dst - rec->path;
-        }
-    }
-    return 0;
-}
-
-int copy_and_append(dir_rec_t* dst, const dir_rec_t* src, const char* suffix) {
-    dst->len = src->len + strlen(suffix);
-    const size_t dstSize = dst->len + 1;
-    dst->path = (char*) malloc(dstSize);
-
-    if (dst->path == NULL
-            || snprintf(dst->path, dstSize, "%s%s", src->path, suffix)
-                    != (ssize_t) dst->len) {
-        ALOGE("Could not allocate memory to hold appended path; aborting\n");
-        return -1;
-    }
-
-    return 0;
-}
-
-/**
- * Check whether path points to a valid path for an APK file. An ASEC
- * directory is allowed to have one level of subdirectory names. Returns -1
- * when an invalid path is encountered and 0 when a valid path is encountered.
- */
-int validate_apk_path(const char *path)
-{
-    int allowsubdir = 0;
-    char *subdir = NULL;
-    size_t dir_len;
-    size_t path_len;
-
-    if (!strncmp(path, android_app_dir.path, android_app_dir.len)) {
-        dir_len = android_app_dir.len;
-    } else if (!strncmp(path, android_app_private_dir.path, android_app_private_dir.len)) {
-        dir_len = android_app_private_dir.len;
-    } else if (!strncmp(path, android_asec_dir.path, android_asec_dir.len)) {
-        dir_len = android_asec_dir.len;
-        allowsubdir = 1;
-    } else {
-        ALOGE("invalid apk path '%s' (bad prefix)\n", path);
-        return -1;
-    }
-
-    path_len = strlen(path);
-
-    /*
-     * Only allow the path to have a subdirectory if it's been marked as being allowed.
-     */
-    if ((subdir = strchr(path + dir_len, '/')) != NULL) {
-        ++subdir;
-        if (!allowsubdir
-                || (path_len > (size_t) (subdir - path) && (strchr(subdir, '/') != NULL))) {
-            ALOGE("invalid apk path '%s' (subdir?)\n", path);
-            return -1;
-        }
-    }
-
-    /*
-     *  Directories can't have a period directly after the directory markers
-     *  to prevent ".."
-     */
-    if (path[dir_len] == '.'
-            || (subdir != NULL && ((*subdir == '.') || (strchr(subdir, '/') != NULL)))) {
-        ALOGE("invalid apk path '%s' (trickery)\n", path);
-        return -1;
-    }
-
-    return 0;
-}
-
-int append_and_increment(char** dst, const char* src, size_t* dst_size) {
-    ssize_t ret = strlcpy(*dst, src, *dst_size);
-    if (ret < 0 || (size_t) ret >= *dst_size) {
-        return -1;
-    }
-    *dst += ret;
-    *dst_size -= ret;
-    return 0;
-}
-
-char *build_string2(char *s1, char *s2) {
-    if (s1 == NULL || s2 == NULL) return NULL;
-
-    int len_s1 = strlen(s1);
-    int len_s2 = strlen(s2);
-    int len = len_s1 + len_s2 + 1;
-    char *result = malloc(len);
-    if (result == NULL) return NULL;
-
-    strcpy(result, s1);
-    strcpy(result + len_s1, s2);
-
-    return result;
-}
-
-char *build_string3(char *s1, char *s2, char *s3) {
-    if (s1 == NULL || s2 == NULL || s3 == NULL) return NULL;
-
-    int len_s1 = strlen(s1);
-    int len_s2 = strlen(s2);
-    int len_s3 = strlen(s3);
-    int len = len_s1 + len_s2 + len_s3 + 1;
-    char *result = malloc(len);
-    if (result == NULL) return NULL;
-
-    strcpy(result, s1);
-    strcpy(result + len_s1, s2);
-    strcpy(result + len_s1 + len_s2, s3);
-
-    return result;
-}
-
-/* Ensure that /data/media directories are prepared for given user. */
-int ensure_media_user_dirs(userid_t userid) {
-    char media_user_path[PATH_MAX];
-    char path[PATH_MAX];
-
-    // Ensure /data/media/<userid> exists
-    create_persona_media_path(media_user_path, userid);
-    if (fs_prepare_dir(media_user_path, 0770, AID_MEDIA_RW, AID_MEDIA_RW) == -1) {
-        return -1;
-    }
-
-    return 0;
-}
diff --git a/cmds/ip-up-vpn/ip-up-vpn.c b/cmds/ip-up-vpn/ip-up-vpn.c
deleted file mode 100644
index 9fcc950..0000000
--- a/cmds/ip-up-vpn/ip-up-vpn.c
+++ /dev/null
@@ -1,153 +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.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-
-#include <arpa/inet.h>
-#include <netinet/in.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/ioctl.h>
-#include <linux/if.h>
-#include <linux/route.h>
-
-#define LOG_TAG "ip-up-vpn"
-#include <cutils/log.h>
-
-#define DIR "/data/misc/vpn/"
-
-static const char *env(const char *name) {
-    const char *value = getenv(name);
-    return value ? value : "";
-}
-
-static int set_address(struct sockaddr *sa, const char *address) {
-    sa->sa_family = AF_INET;
-    errno = EINVAL;
-    return inet_pton(AF_INET, address, &((struct sockaddr_in *)sa)->sin_addr);
-}
-
-/*
- * The primary goal is to create a file with VPN parameters. Currently they
- * are interface, addresses, routes, DNS servers, and search domains. Each
- * parameter occupies one line in the file, and it can be an empty string or
- * space-separated values. The order and the format must be consistent with
- * com.android.server.connectivity.Vpn. Here is an example.
- *
- *   ppp0
- *   192.168.1.100/24
- *   0.0.0.0/0
- *   192.168.1.1 192.168.1.2
- *   example.org
- *
- * The secondary goal is to unify the outcome of VPN. The current baseline
- * is to have an interface configured with the given address and netmask
- * and maybe add a host route to protect the tunnel. PPP-based VPN already
- * does this, but others might not. Routes, DNS servers, and search domains
- * are handled by the framework since they can be overridden by the users.
- */
-int main(int argc, char **argv)
-{
-    FILE *state = fopen(DIR ".tmp", "wb");
-    if (!state) {
-        ALOGE("Cannot create state: %s", strerror(errno));
-        return 1;
-    }
-
-    if (argc >= 6) {
-        /* Invoked by pppd. */
-        fprintf(state, "%s\n", argv[1]);
-        fprintf(state, "%s/32\n", argv[4]);
-        fprintf(state, "0.0.0.0/0\n");
-        fprintf(state, "%s %s\n", env("DNS1"), env("DNS2"));
-        fprintf(state, "\n");
-    } else if (argc == 2) {
-        /* Invoked by racoon. */
-        const char *interface = env("INTERFACE");
-        const char *address = env("INTERNAL_ADDR4");
-        const char *routes = env("SPLIT_INCLUDE_CIDR");
-
-        int s = socket(AF_INET, SOCK_DGRAM, 0);
-        struct rtentry rt;
-        struct ifreq ifr;
-
-        memset(&rt, 0, sizeof(rt));
-        memset(&ifr, 0, sizeof(ifr));
-
-        /* Remove the old host route. There could be more than one. */
-        rt.rt_flags |= RTF_UP | RTF_HOST;
-        if (set_address(&rt.rt_dst, env("REMOTE_ADDR"))) {
-            while (!ioctl(s, SIOCDELRT, &rt));
-        }
-        if (errno != ESRCH) {
-            ALOGE("Cannot remove host route: %s", strerror(errno));
-            return 1;
-        }
-
-        /* Create a new host route. */
-        rt.rt_flags |= RTF_GATEWAY;
-        if (!set_address(&rt.rt_gateway, argv[1]) ||
-                (ioctl(s, SIOCADDRT, &rt) && errno != EEXIST)) {
-            ALOGE("Cannot create host route: %s", strerror(errno));
-            return 1;
-        }
-
-        /* Bring up the interface. */
-        ifr.ifr_flags = IFF_UP;
-        strncpy(ifr.ifr_name, interface, IFNAMSIZ);
-        if (ioctl(s, SIOCSIFFLAGS, &ifr)) {
-            ALOGE("Cannot bring up %s: %s", interface, strerror(errno));
-            return 1;
-        }
-
-        /* Set the address. */
-        if (!set_address(&ifr.ifr_addr, address) ||
-                ioctl(s, SIOCSIFADDR, &ifr)) {
-            ALOGE("Cannot set address: %s", strerror(errno));
-            return 1;
-        }
-
-        /* Set the netmask. */
-        if (set_address(&ifr.ifr_netmask, env("INTERNAL_NETMASK4"))) {
-            if (ioctl(s, SIOCSIFNETMASK, &ifr)) {
-                ALOGE("Cannot set netmask: %s", strerror(errno));
-                return 1;
-            }
-        }
-
-        /* TODO: Send few packets to trigger phase 2? */
-
-        fprintf(state, "%s\n", interface);
-        fprintf(state, "%s/%s\n", address, env("INTERNAL_CIDR4"));
-        fprintf(state, "%s\n", routes[0] ? routes : "0.0.0.0/0");
-        fprintf(state, "%s\n", env("INTERNAL_DNS4_LIST"));
-        fprintf(state, "%s\n", env("DEFAULT_DOMAIN"));
-    } else {
-        ALOGE("Cannot parse parameters");
-        return 1;
-    }
-
-    fclose(state);
-    if (chmod(DIR ".tmp", 0444) || rename(DIR ".tmp", DIR "state")) {
-        ALOGE("Cannot write state: %s", strerror(errno));
-        return 1;
-    }
-    return 0;
-}
diff --git a/cmds/rawbu/Android.mk b/cmds/rawbu/Android.mk
deleted file mode 100644
index b580390..0000000
--- a/cmds/rawbu/Android.mk
+++ /dev/null
@@ -1,15 +0,0 @@
-# Copyright 2009 The Android Open Source Project
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= backup.cpp
-
-LOCAL_SHARED_LIBRARIES := libcutils libc
-
-LOCAL_MODULE:= rawbu
-
-LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES)
-LOCAL_MODULE_TAGS := debug
-
-include $(BUILD_EXECUTABLE)
diff --git a/cmds/rawbu/NOTICE b/cmds/rawbu/NOTICE
deleted file mode 100644
index c5b1efa..0000000
--- a/cmds/rawbu/NOTICE
+++ /dev/null
@@ -1,190 +0,0 @@
-
-   Copyright (c) 2005-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.
-
-   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.
-
-
-                                 Apache License
-                           Version 2.0, January 2004
-                        http://www.apache.org/licenses/
-
-   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
-   1. Definitions.
-
-      "License" shall mean the terms and conditions for use, reproduction,
-      and distribution as defined by Sections 1 through 9 of this document.
-
-      "Licensor" shall mean the copyright owner or entity authorized by
-      the copyright owner that is granting the License.
-
-      "Legal Entity" shall mean the union of the acting entity and all
-      other entities that control, are controlled by, or are under common
-      control with that entity. For the purposes of this definition,
-      "control" means (i) the power, direct or indirect, to cause the
-      direction or management of such entity, whether by contract or
-      otherwise, or (ii) ownership of fifty percent (50%) or more of the
-      outstanding shares, or (iii) beneficial ownership of such entity.
-
-      "You" (or "Your") shall mean an individual or Legal Entity
-      exercising permissions granted by this License.
-
-      "Source" form shall mean the preferred form for making modifications,
-      including but not limited to software source code, documentation
-      source, and configuration files.
-
-      "Object" form shall mean any form resulting from mechanical
-      transformation or translation of a Source form, including but
-      not limited to compiled object code, generated documentation,
-      and conversions to other media types.
-
-      "Work" shall mean the work of authorship, whether in Source or
-      Object form, made available under the License, as indicated by a
-      copyright notice that is included in or attached to the work
-      (an example is provided in the Appendix below).
-
-      "Derivative Works" shall mean any work, whether in Source or Object
-      form, that is based on (or derived from) the Work and for which the
-      editorial revisions, annotations, elaborations, or other modifications
-      represent, as a whole, an original work of authorship. For the purposes
-      of this License, Derivative Works shall not include works that remain
-      separable from, or merely link (or bind by name) to the interfaces of,
-      the Work and Derivative Works thereof.
-
-      "Contribution" shall mean any work of authorship, including
-      the original version of the Work and any modifications or additions
-      to that Work or Derivative Works thereof, that is intentionally
-      submitted to Licensor for inclusion in the Work by the copyright owner
-      or by an individual or Legal Entity authorized to submit on behalf of
-      the copyright owner. For the purposes of this definition, "submitted"
-      means any form of electronic, verbal, or written communication sent
-      to the Licensor or its representatives, including but not limited to
-      communication on electronic mailing lists, source code control systems,
-      and issue tracking systems that are managed by, or on behalf of, the
-      Licensor for the purpose of discussing and improving the Work, but
-      excluding communication that is conspicuously marked or otherwise
-      designated in writing by the copyright owner as "Not a Contribution."
-
-      "Contributor" shall mean Licensor and any individual or Legal Entity
-      on behalf of whom a Contribution has been received by Licensor and
-      subsequently incorporated within the Work.
-
-   2. Grant of Copyright License. Subject to the terms and conditions of
-      this License, each Contributor hereby grants to You a perpetual,
-      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-      copyright license to reproduce, prepare Derivative Works of,
-      publicly display, publicly perform, sublicense, and distribute the
-      Work and such Derivative Works in Source or Object form.
-
-   3. Grant of Patent License. Subject to the terms and conditions of
-      this License, each Contributor hereby grants to You a perpetual,
-      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-      (except as stated in this section) patent license to make, have made,
-      use, offer to sell, sell, import, and otherwise transfer the Work,
-      where such license applies only to those patent claims licensable
-      by such Contributor that are necessarily infringed by their
-      Contribution(s) alone or by combination of their Contribution(s)
-      with the Work to which such Contribution(s) was submitted. If You
-      institute patent litigation against any entity (including a
-      cross-claim or counterclaim in a lawsuit) alleging that the Work
-      or a Contribution incorporated within the Work constitutes direct
-      or contributory patent infringement, then any patent licenses
-      granted to You under this License for that Work shall terminate
-      as of the date such litigation is filed.
-
-   4. Redistribution. You may reproduce and distribute copies of the
-      Work or Derivative Works thereof in any medium, with or without
-      modifications, and in Source or Object form, provided that You
-      meet the following conditions:
-
-      (a) You must give any other recipients of the Work or
-          Derivative Works a copy of this License; and
-
-      (b) You must cause any modified files to carry prominent notices
-          stating that You changed the files; and
-
-      (c) You must retain, in the Source form of any Derivative Works
-          that You distribute, all copyright, patent, trademark, and
-          attribution notices from the Source form of the Work,
-          excluding those notices that do not pertain to any part of
-          the Derivative Works; and
-
-      (d) If the Work includes a "NOTICE" text file as part of its
-          distribution, then any Derivative Works that You distribute must
-          include a readable copy of the attribution notices contained
-          within such NOTICE file, excluding those notices that do not
-          pertain to any part of the Derivative Works, in at least one
-          of the following places: within a NOTICE text file distributed
-          as part of the Derivative Works; within the Source form or
-          documentation, if provided along with the Derivative Works; or,
-          within a display generated by the Derivative Works, if and
-          wherever such third-party notices normally appear. The contents
-          of the NOTICE file are for informational purposes only and
-          do not modify the License. You may add Your own attribution
-          notices within Derivative Works that You distribute, alongside
-          or as an addendum to the NOTICE text from the Work, provided
-          that such additional attribution notices cannot be construed
-          as modifying the License.
-
-      You may add Your own copyright statement to Your modifications and
-      may provide additional or different license terms and conditions
-      for use, reproduction, or distribution of Your modifications, or
-      for any such Derivative Works as a whole, provided Your use,
-      reproduction, and distribution of the Work otherwise complies with
-      the conditions stated in this License.
-
-   5. Submission of Contributions. Unless You explicitly state otherwise,
-      any Contribution intentionally submitted for inclusion in the Work
-      by You to the Licensor shall be under the terms and conditions of
-      this License, without any additional terms or conditions.
-      Notwithstanding the above, nothing herein shall supersede or modify
-      the terms of any separate license agreement you may have executed
-      with Licensor regarding such Contributions.
-
-   6. Trademarks. This License does not grant permission to use the trade
-      names, trademarks, service marks, or product names of the Licensor,
-      except as required for reasonable and customary use in describing the
-      origin of the Work and reproducing the content of the NOTICE file.
-
-   7. Disclaimer of Warranty. Unless required by applicable law or
-      agreed to in writing, Licensor provides the Work (and each
-      Contributor provides its Contributions) on an "AS IS" BASIS,
-      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-      implied, including, without limitation, any warranties or conditions
-      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
-      PARTICULAR PURPOSE. You are solely responsible for determining the
-      appropriateness of using or redistributing the Work and assume any
-      risks associated with Your exercise of permissions under this License.
-
-   8. Limitation of Liability. In no event and under no legal theory,
-      whether in tort (including negligence), contract, or otherwise,
-      unless required by applicable law (such as deliberate and grossly
-      negligent acts) or agreed to in writing, shall any Contributor be
-      liable to You for damages, including any direct, indirect, special,
-      incidental, or consequential damages of any character arising as a
-      result of this License or out of the use or inability to use the
-      Work (including but not limited to damages for loss of goodwill,
-      work stoppage, computer failure or malfunction, or any and all
-      other commercial damages or losses), even if such Contributor
-      has been advised of the possibility of such damages.
-
-   9. Accepting Warranty or Additional Liability. While redistributing
-      the Work or Derivative Works thereof, You may choose to offer,
-      and charge a fee for, acceptance of support, warranty, indemnity,
-      or other liability obligations and/or rights consistent with this
-      License. However, in accepting such obligations, You may act only
-      on Your own behalf and on Your sole responsibility, not on behalf
-      of any other Contributor, and only if You agree to indemnify,
-      defend, and hold each Contributor harmless for any liability
-      incurred by, or claims asserted against, such Contributor by reason
-      of your accepting any such warranty or additional liability.
-
-   END OF TERMS AND CONDITIONS
-
diff --git a/cmds/rawbu/backup.cpp b/cmds/rawbu/backup.cpp
deleted file mode 100644
index 70e7b57..0000000
--- a/cmds/rawbu/backup.cpp
+++ /dev/null
@@ -1,746 +0,0 @@
-// Copyright 2009 The Android Open Source Project
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <string.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <time.h>
-#include <dirent.h>
-#include <errno.h>
-#include <assert.h>
-#include <ctype.h>
-#include <utime.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <stdint.h>
-
-#include <cutils/properties.h>
-
-#include <private/android_filesystem_config.h>
-
-#ifndef PATH_MAX
-#define PATH_MAX 4096
-#endif
-
-// First version.
-#define FILE_VERSION_1 0xffff0001
-
-// Introduces backup all option to header.
-#define FILE_VERSION_2 0xffff0002
-
-#define FILE_VERSION FILE_VERSION_2
-
-namespace android {
-
-static char nameBuffer[PATH_MAX];
-static struct stat statBuffer;
-
-static char copyBuffer[8192];
-static char *backupFilePath = NULL;
-
-static uint32_t inputFileVersion;
-
-static int opt_backupAll;
-
-#define SPECIAL_NO_TOUCH 0
-#define SPECIAL_NO_BACKUP 1
-
-struct special_dir {
-    const char* path;
-    int type;
-};
-
-/* Directory paths that we will not backup/restore */
-static const struct special_dir SKIP_PATHS[] = {
-    { "/data/misc", SPECIAL_NO_TOUCH },
-    { "/data/system/batterystats.bin", SPECIAL_NO_TOUCH },
-    { "/data/system/location", SPECIAL_NO_TOUCH },
-    { "/data/dalvik-cache", SPECIAL_NO_BACKUP },
-    { NULL, 0 },
-};
-
-/* This is just copied from the shell's built-in wipe command. */
-static int wipe (const char *path) 
-{
-    DIR *dir;
-    struct dirent *de;
-    int ret;
-    int i;
-
-    dir = opendir(path);
-
-    if (dir == NULL) {
-        fprintf (stderr, "Error opendir'ing %s: %s\n",
-                    path, strerror(errno));
-        return 0;
-    }
-
-    char *filenameOffset;
-
-    strcpy(nameBuffer, path);
-    strcat(nameBuffer, "/");
-
-    filenameOffset = nameBuffer + strlen(nameBuffer);
-
-    for (;;) {
-        de = readdir(dir);
-
-        if (de == NULL) {
-            break;
-        }
-
-        if (0 == strcmp(de->d_name, ".")
-                || 0 == strcmp(de->d_name, "..")
-                || 0 == strcmp(de->d_name, "lost+found")
-        ) {
-            continue;
-        }
-
-        strcpy(filenameOffset, de->d_name);
-        bool noBackup = false;
-        
-        /* See if this is a path we should skip. */
-        for (i = 0; SKIP_PATHS[i].path; i++) {
-            if (strcmp(SKIP_PATHS[i].path, nameBuffer) == 0) {
-                if (opt_backupAll || SKIP_PATHS[i].type == SPECIAL_NO_BACKUP) {
-                    // In this case we didn't back up the directory --
-                    // we do want to wipe its contents, but not the
-                    // directory itself, since the restore file won't
-                    // contain the directory.
-                    noBackup = true;
-                }
-                break;
-            }
-        }
-        
-        if (!noBackup && SKIP_PATHS[i].path != NULL) {
-            // This is a SPECIAL_NO_TOUCH directory.
-            continue;
-        }
-
-        ret = lstat (nameBuffer, &statBuffer);
-
-        if (ret != 0) {
-            fprintf(stderr, "warning -- stat() error on '%s': %s\n", 
-                    nameBuffer, strerror(errno));
-            continue;
-        }
-
-        if(S_ISDIR(statBuffer.st_mode)) {
-            int i;
-            char *newpath;
-
-            newpath = strdup(nameBuffer);
-            if (wipe(newpath) == 0) {
-                free(newpath);
-                closedir(dir);
-                return 0;
-            }
-            
-            if (!noBackup) {
-                ret = rmdir(newpath);
-                if (ret != 0) {
-                    fprintf(stderr, "warning -- rmdir() error on '%s': %s\n", 
-                        newpath, strerror(errno));
-                }
-            }
-
-            free(newpath);
-
-            strcpy(nameBuffer, path);
-            strcat(nameBuffer, "/");
-
-        } else {
-            // Don't delete the backup file
-            if (backupFilePath && strcmp(backupFilePath, nameBuffer) == 0) {
-                continue;
-            }
-            ret = unlink(nameBuffer);
-
-            if (ret != 0) {
-                fprintf(stderr, "warning -- unlink() error on '%s': %s\n", 
-                    nameBuffer, strerror(errno));
-            }
-        }
-    }
-
-    closedir(dir);
-    
-    return 1;
-}
-
-static int write_int32(FILE* fh, int32_t val)
-{
-    int res = fwrite(&val, 1, sizeof(val), fh);
-    if (res != sizeof(val)) {
-        fprintf(stderr, "unable to write int32 (%d bytes): %s\n", res, strerror(errno));
-        return 0;
-    }
-    
-    return 1;
-}
-
-static int write_int64(FILE* fh, int64_t val)
-{
-    int res = fwrite(&val, 1, sizeof(val), fh); 
-    if (res != sizeof(val)) {
-        fprintf(stderr, "unable to write int64 (%d bytes): %s\n", res, strerror(errno));
-        return 0;
-    }
-    
-    return 1;
-}
-
-static int copy_file(FILE* dest, FILE* src, off_t size, const char* destName,
-        const char* srcName)
-{
-    errno = 0;
-    
-    off_t origSize = size;
-    
-    while (size > 0) {
-        int amt = size > (off_t)sizeof(copyBuffer) ? sizeof(copyBuffer) : (int)size;
-        int readLen = fread(copyBuffer, 1, amt, src);
-        if (readLen <= 0) {
-            if (srcName != NULL) {
-                fprintf(stderr, "unable to read source (%d of %ld bytes) file '%s': %s\n",
-                    amt, origSize, srcName, errno != 0 ? strerror(errno) : "unexpected EOF");
-            } else {
-                fprintf(stderr, "unable to read buffer (%d of %ld bytes): %s\n",
-                    amt, origSize, errno != 0 ? strerror(errno) : "unexpected EOF");
-            }
-            return 0;
-        }
-        int writeLen = fwrite(copyBuffer, 1, readLen, dest); 
-        if (writeLen != readLen) {
-            if (destName != NULL) {
-                fprintf(stderr, "unable to write file (%d of %d bytes) '%s': '%s'\n",
-                    writeLen, readLen, destName, strerror(errno));
-            } else {
-                fprintf(stderr, "unable to write buffer (%d of %d bytes): '%s'\n",
-                    writeLen, readLen, strerror(errno));
-            }
-            return 0;
-        }
-        size -= readLen;
-    }
-    return 1;
-}
-
-#define TYPE_END 0
-#define TYPE_DIR 1
-#define TYPE_FILE 2
-
-static int write_header(FILE* fh, int type, const char* path, const struct stat* st)
-{
-    int pathLen = strlen(path);
-    if (!write_int32(fh, type)) return 0;
-    if (!write_int32(fh, pathLen)) return 0;
-    if (fwrite(path, 1, pathLen, fh) != (size_t)pathLen) {
-        fprintf(stderr, "unable to write: %s\n", strerror(errno));
-        return 0;
-    }
-    
-    if (!write_int32(fh, st->st_uid)) return 0;
-    if (!write_int32(fh, st->st_gid)) return 0;
-    if (!write_int32(fh, st->st_mode)) return 0;
-    if (!write_int64(fh, ((int64_t)st->st_atime)*1000*1000*1000)) return 0;
-    if (!write_int64(fh, ((int64_t)st->st_mtime)*1000*1000*1000)) return 0;
-    if (!write_int64(fh, ((int64_t)st->st_ctime)*1000*1000*1000)) return 0;
-    
-    return 1;
-}
-
-static int backup_dir(FILE* fh, const char* srcPath)
-{
-    DIR *dir;
-    struct dirent *de;
-    char* fullPath = NULL;
-    int srcLen = strlen(srcPath);
-    int result = 1;
-    int i;
-    
-    dir = opendir(srcPath);
-
-    if (dir == NULL) {
-        fprintf (stderr, "error opendir'ing '%s': %s\n",
-                    srcPath, strerror(errno));
-        return 0;
-    }
-    
-    for (;;) {
-        de = readdir(dir);
-
-        if (de == NULL) {
-            break;
-        }
-
-        if (0 == strcmp(de->d_name, ".")
-                || 0 == strcmp(de->d_name, "..")
-                || 0 == strcmp(de->d_name, "lost+found")
-        ) {
-            continue;
-        }
-
-        if (fullPath != NULL) {
-            free(fullPath);
-        }
-        fullPath = (char*)malloc(srcLen + strlen(de->d_name) + 2);
-        strcpy(fullPath, srcPath);
-        fullPath[srcLen] = '/';
-        strcpy(fullPath+srcLen+1, de->d_name);
-
-        /* See if this is a path we should skip. */
-        if (!opt_backupAll) {
-            for (i = 0; SKIP_PATHS[i].path; i++) {
-                if (strcmp(SKIP_PATHS[i].path, fullPath) == 0) {
-                    break;
-                }
-            }
-            if (SKIP_PATHS[i].path != NULL) {
-                continue;
-            }
-        }
-
-        int ret = lstat(fullPath, &statBuffer);
-
-        if (ret != 0) {
-            fprintf(stderr, "stat() error on '%s': %s\n", 
-                    fullPath, strerror(errno));
-            result = 0;
-            goto done;
-        }
-
-        if(S_ISDIR(statBuffer.st_mode)) {
-            printf("Saving dir %s...\n", fullPath);
-            
-            if (write_header(fh, TYPE_DIR, fullPath, &statBuffer) == 0) {
-                result = 0;
-                goto done;
-            }
-            if (backup_dir(fh, fullPath) == 0) {
-                result = 0;
-                goto done;
-            }
-        } else if (S_ISREG(statBuffer.st_mode)) {
-            // Skip the backup file
-            if (backupFilePath && strcmp(fullPath, backupFilePath) == 0) {
-                printf("Skipping backup file %s...\n", backupFilePath);
-                continue;
-            } else {
-                printf("Saving file %s...\n", fullPath);
-            }
-            if (write_header(fh, TYPE_FILE, fullPath, &statBuffer) == 0) {
-                result = 0;
-                goto done;
-            }
-            
-            off_t size = statBuffer.st_size;
-            if (!write_int64(fh, size)) {
-                result = 0;
-                goto done;
-            }
-            
-            FILE* src = fopen(fullPath, "r");
-            if (src == NULL) {
-                fprintf(stderr, "unable to open source file '%s': %s\n",
-                    fullPath, strerror(errno));
-                result = 0;
-                goto done;
-            }
-            
-            int copyres = copy_file(fh, src, size, NULL, fullPath);
-            fclose(src);
-            if (!copyres) {
-                result = 0;
-                goto done;
-            }
-        }
-    }
-
-done:
-    if (fullPath != NULL) {
-        free(fullPath);
-    }
-    
-    closedir(dir);
-    
-    return result;
-}
-
-static int backup_data(const char* destPath)
-{
-    int res = -1;
-    
-    FILE* fh = fopen(destPath, "w");
-    if (fh == NULL) {
-        fprintf(stderr, "unable to open destination '%s': %s\n",
-                destPath, strerror(errno));
-        return -1;
-    }
-    
-    printf("Backing up /data to %s...\n", destPath);
-
-    // The path that shouldn't be backed up
-    backupFilePath = strdup(destPath);
-
-    if (!write_int32(fh, FILE_VERSION)) goto done;
-    if (!write_int32(fh, opt_backupAll)) goto done;
-    if (!backup_dir(fh, "/data")) goto done;
-    if (!write_int32(fh, 0)) goto done;
-    
-    res = 0;
-    
-done:
-    if (fflush(fh) != 0) {
-        fprintf(stderr, "error flushing destination '%s': %s\n",
-            destPath, strerror(errno));
-        res = -1;
-        goto donedone;
-    }
-    if (fsync(fileno(fh)) != 0) {
-        fprintf(stderr, "error syncing destination '%s': %s\n",
-            destPath, strerror(errno));
-        res = -1;
-        goto donedone;
-    }
-    fclose(fh);
-    sync();
-
-donedone:    
-    return res;
-}
-
-static int32_t read_int32(FILE* fh, int32_t defVal)
-{
-    int32_t val;
-    if (fread(&val, 1, sizeof(val), fh) != sizeof(val)) {
-        fprintf(stderr, "unable to read: %s\n", strerror(errno));
-        return defVal;
-    }
-    
-    return val;
-}
-
-static int64_t read_int64(FILE* fh, int64_t defVal)
-{
-    int64_t val;
-    if (fread(&val, 1, sizeof(val), fh) != sizeof(val)) {
-        fprintf(stderr, "unable to read: %s\n", strerror(errno));
-        return defVal;
-    }
-    
-    return val;
-}
-
-static int read_header(FILE* fh, int* type, char** path, struct stat* st)
-{
-    *type = read_int32(fh, -1);
-    if (*type == TYPE_END) {
-        return 1;
-    }
-    
-    if (*type < 0) {
-        fprintf(stderr, "bad token %d in restore file\n", *type);
-        return 0;
-    }
-    
-    int32_t pathLen = read_int32(fh, -1);
-    if (pathLen <= 0) {
-        fprintf(stderr, "bad path length %d in restore file\n", pathLen);
-        return 0;
-    }
-    char* readPath = (char*)malloc(pathLen+1);
-    if (fread(readPath, 1, pathLen, fh) != (size_t)pathLen) {
-        fprintf(stderr, "truncated path in restore file\n");
-        free(readPath);
-        return 0;
-    }
-    readPath[pathLen] = 0;
-    *path = readPath;
-    
-    st->st_uid = read_int32(fh, -1);
-    if (st->st_uid == (uid_t)-1) {
-        fprintf(stderr, "bad uid in restore file at '%s'\n", readPath);
-        return 0;
-    }
-    st->st_gid = read_int32(fh, -1);
-    if (st->st_gid == (gid_t)-1) {
-        fprintf(stderr, "bad gid in restore file at '%s'\n", readPath);
-        return 0;
-    }
-    st->st_mode = read_int32(fh, -1);
-    if (st->st_mode == (mode_t)-1) {
-        fprintf(stderr, "bad mode in restore file at '%s'\n", readPath);
-        return 0;
-    }
-    int64_t ltime = read_int64(fh, -1);
-    if (ltime < 0) {
-        fprintf(stderr, "bad atime in restore file at '%s'\n", readPath);
-        return 0;
-    }
-    st->st_atime = (time_t)(ltime/1000/1000/1000);
-    ltime = read_int64(fh, -1);
-    if (ltime < 0) {
-        fprintf(stderr, "bad mtime in restore file at '%s'\n", readPath);
-        return 0;
-    }
-    st->st_mtime = (time_t)(ltime/1000/1000/1000);
-    ltime = read_int64(fh, -1);
-    if (ltime < 0) {
-        fprintf(stderr, "bad ctime in restore file at '%s'\n", readPath);
-        return 0;
-    }
-    st->st_ctime = (time_t)(ltime/1000/1000/1000);
-    
-    st->st_mode &= (S_IRWXU|S_IRWXG|S_IRWXO);
-    
-    return 1;
-}
-
-static int restore_data(const char* srcPath)
-{
-    int res = -1;
-    
-    FILE* fh = fopen(srcPath, "r");
-    if (fh == NULL) {
-        fprintf(stderr, "Unable to open source '%s': %s\n",
-                srcPath, strerror(errno));
-        return -1;
-    }
-    
-    inputFileVersion = read_int32(fh, 0);
-    if (inputFileVersion < FILE_VERSION_1 || inputFileVersion > FILE_VERSION) {
-        fprintf(stderr, "Restore file has bad version: 0x%x\n", inputFileVersion);
-        goto done;
-    }
-    
-    if (inputFileVersion >= FILE_VERSION_2) {
-        opt_backupAll = read_int32(fh, 0);
-    } else {
-        opt_backupAll = 0;
-    }
-
-    // The path that shouldn't be deleted
-    backupFilePath = strdup(srcPath);
-    
-    printf("Wiping contents of /data...\n");
-    if (!wipe("/data")) {
-        goto done;
-    }
-
-    printf("Restoring from %s to /data...\n", srcPath);
-
-    while (1) {
-        int type;
-        char* path = NULL;
-        if (read_header(fh, &type, &path, &statBuffer) == 0) {
-            goto done;
-        }
-        if (type == 0) {
-            break;
-        }
-        
-        const char* typeName = "?";
-        
-        if (type == TYPE_DIR) {
-            typeName = "dir";
-            
-            printf("Restoring dir %s...\n", path);
-            
-            if (mkdir(path, statBuffer.st_mode) != 0) {
-                if (errno != EEXIST) {
-                    fprintf(stderr, "unable to create directory '%s': %s\n",
-                        path, strerror(errno));
-                    free(path);
-                    goto done;
-                }
-            }
-            
-        } else if (type == TYPE_FILE) {
-            typeName = "file";
-            off_t size = read_int64(fh, -1);
-            if (size < 0) {
-                fprintf(stderr, "bad file size %ld in restore file\n", size);
-                free(path);
-                goto done;
-            }
-            
-            printf("Restoring file %s...\n", path);
-            
-            FILE* dest = fopen(path, "w");
-            if (dest == NULL) {
-                fprintf(stderr, "unable to open destination file '%s': %s\n",
-                    path, strerror(errno));
-                free(path);
-                goto done;
-            }
-            
-            int copyres = copy_file(dest, fh, size, path, NULL);
-            fclose(dest);
-            if (!copyres) {
-                free(path);
-                goto done;
-            }
-        
-        } else {
-            fprintf(stderr, "unknown node type %d\n", type);
-            goto done;
-        }
-        
-        // Do this even for directories, since the dir may have already existed
-        // so we need to make sure it gets the correct mode.    
-        if (chmod(path, statBuffer.st_mode&(S_IRWXU|S_IRWXG|S_IRWXO)) != 0) {
-            fprintf(stderr, "unable to chmod destination %s '%s' to 0x%x: %s\n",
-                typeName, path, statBuffer.st_mode, strerror(errno));
-            free(path);
-            goto done;
-        }
-        
-        if (chown(path, statBuffer.st_uid, statBuffer.st_gid) != 0) {
-            fprintf(stderr, "unable to chown destination %s '%s' to uid %d / gid %d: %s\n",
-                typeName, path, (int)statBuffer.st_uid, (int)statBuffer.st_gid, strerror(errno));
-            free(path);
-            goto done;
-        }
-        
-        struct utimbuf timbuf;
-        timbuf.actime = statBuffer.st_atime;
-        timbuf.modtime = statBuffer.st_mtime;
-        if (utime(path, &timbuf) != 0) {
-            fprintf(stderr, "unable to utime destination %s '%s': %s\n",
-                typeName, path, strerror(errno));
-            free(path);
-            goto done;
-        }
-        
-        
-        free(path);
-    }
-    
-    res = 0;
-        
-done:    
-    fclose(fh);
-    
-    return res;
-}
-
-static void show_help(const char *cmd)
-{
-    fprintf(stderr,"Usage: %s COMMAND [options] [backup-file-path]\n", cmd);
-
-    fprintf(stderr, "commands are:\n"
-                    "  help            Show this help text.\n"
-                    "  backup          Perform a backup of /data.\n"
-                    "  restore         Perform a restore of /data.\n");
-    fprintf(stderr, "options include:\n"
-                    "  -h              Show this help text.\n"
-                    "  -a              Backup all files.\n");
-    fprintf(stderr, "\nThe %s command allows you to perform low-level\n"
-                    "backup and restore of the /data partition.  This is\n"
-                    "where all user data is kept, allowing for a fairly\n"
-                    "complete restore of a device's state.  Note that\n"
-                    "because this is low-level, it will only work across\n"
-                    "builds of the same (or very similar) device software.\n",
-                    cmd);
-}
-
-} /* namespace android */
-
-int main (int argc, char **argv)
-{
-    int restore = 0;
-
-    if (getuid() != AID_ROOT) {
-        fprintf(stderr, "error -- %s must run as root\n", argv[0]);
-        exit(-1);
-    }
-    
-    if (argc < 2) {
-        fprintf(stderr, "No command specified.\n");
-        android::show_help(argv[0]);
-        exit(-1);
-    }
-
-    if (0 == strcmp(argv[1], "restore")) {
-        restore = 1;
-    } else if (0 == strcmp(argv[1], "help")) {
-        android::show_help(argv[0]);
-        exit(0);
-    } else if (0 != strcmp(argv[1], "backup")) {
-        fprintf(stderr, "Unknown command: %s\n", argv[1]);
-        android::show_help(argv[0]);
-        exit(-1);
-    }
-
-    android::opt_backupAll = 0;
-                
-    optind = 2;
-    
-    for (;;) {
-        int ret;
-
-        ret = getopt(argc, argv, "ah");
-
-        if (ret < 0) {
-            break;
-        }
-
-        switch(ret) {
-            case 'a':
-                android::opt_backupAll = 1;
-                if (restore) fprintf(stderr, "Warning: -a option ignored on restore\n");
-                break;
-            case 'h':
-                android::show_help(argv[0]);
-                exit(0);
-            break;
-
-            default:
-                fprintf(stderr,"Unrecognized Option\n");
-                android::show_help(argv[0]);
-                exit(-1);
-            break;
-        }
-    }
-
-    const char* backupFile = "/sdcard/backup.dat";
-    
-    if (argc > optind) {
-        backupFile = argv[optind];
-        optind++;
-        if (argc != optind) {
-            fprintf(stderr, "Too many arguments\n");
-            android::show_help(argv[0]);
-            exit(-1);
-        }
-    }
-    
-    printf("Stopping system...\n");
-    property_set("ctl.stop", "runtime");
-    property_set("ctl.stop", "zygote");
-    sleep(1);
-    
-    int res;
-    if (restore) {
-        res = android::restore_data(backupFile);
-        if (res != 0) {
-            // Don't restart system, since the data partition is hosed.
-            return res;
-        }
-        printf("Restore complete!  Restarting system, cross your fingers...\n");
-    } else {
-        res = android::backup_data(backupFile);
-        if (res == 0) {
-            printf("Backup complete!  Restarting system...\n");
-        } else {
-            printf("Restarting system...\n");
-        }
-    }
-    
-    property_set("ctl.start", "zygote");
-    property_set("ctl.start", "runtime");
-}
diff --git a/cmds/screenshot/Android.mk b/cmds/screenshot/Android.mk
deleted file mode 100644
index 73a8e22..0000000
--- a/cmds/screenshot/Android.mk
+++ /dev/null
@@ -1,12 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := screenshot.c
-
-LOCAL_MODULE := screenshot
-
-LOCAL_SHARED_LIBRARIES := libcutils libz
-LOCAL_STATIC_LIBRARIES := libpng
-LOCAL_C_INCLUDES += external/zlib
-
-include $(BUILD_EXECUTABLE)
diff --git a/cmds/screenshot/screenshot.c b/cmds/screenshot/screenshot.c
deleted file mode 100644
index cca80c3..0000000
--- a/cmds/screenshot/screenshot.c
+++ /dev/null
@@ -1,171 +0,0 @@
-#include <stdlib.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <string.h>
-#include <fcntl.h>
-#include <errno.h>
-
-#include <linux/fb.h>
-
-#include <zlib.h>
-#include <libpng/png.h>
-
-#include "private/android_filesystem_config.h"
-
-#define LOG_TAG "screenshot"
-#include <utils/Log.h>
-
-void take_screenshot(FILE *fb_in, FILE *fb_out) {
-    int fb;
-    char imgbuf[0x10000];
-    struct fb_var_screeninfo vinfo;
-    png_structp png;
-    png_infop info;
-    unsigned int r,c,rowlen;
-    unsigned int bytespp,offset;
-
-    fb = fileno(fb_in);
-    if(fb < 0) {
-        ALOGE("failed to open framebuffer\n");
-        return;
-    }
-    fb_in = fdopen(fb, "r");
-
-    if(ioctl(fb, FBIOGET_VSCREENINFO, &vinfo) < 0) {
-        ALOGE("failed to get framebuffer info\n");
-        return;
-    }
-    fcntl(fb, F_SETFD, FD_CLOEXEC);
-
-    png = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
-    if (png == NULL) {
-        ALOGE("failed png_create_write_struct\n");
-        fclose(fb_in);
-        return;
-    }
-
-    png_init_io(png, fb_out);
-    info = png_create_info_struct(png);
-    if (info == NULL) {
-        ALOGE("failed png_create_info_struct\n");
-        png_destroy_write_struct(&png, NULL);
-        fclose(fb_in);
-        return;
-    }
-    if (setjmp(png_jmpbuf(png))) {
-        ALOGE("failed png setjmp\n");
-        png_destroy_write_struct(&png, NULL);
-        fclose(fb_in);
-        return;
-    }
-
-    bytespp = vinfo.bits_per_pixel / 8;
-    png_set_IHDR(png, info,
-        vinfo.xres, vinfo.yres, vinfo.bits_per_pixel / 4, 
-        PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE,
-        PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
-    png_write_info(png, info);
-
-    rowlen=vinfo.xres * bytespp;
-    if (rowlen > sizeof(imgbuf)) {
-        ALOGE("crazy rowlen: %d\n", rowlen);
-        png_destroy_write_struct(&png, NULL);
-        fclose(fb_in);
-        return;
-    }
-
-    offset = vinfo.xoffset * bytespp + vinfo.xres * vinfo.yoffset * bytespp;
-    fseek(fb_in, offset, SEEK_SET);
-
-    for(r=0; r<vinfo.yres; r++) {
-        int len = fread(imgbuf, 1, rowlen, fb_in);
-        if (len <= 0) break;
-        png_write_row(png, (png_bytep)imgbuf);
-    }
-
-    png_write_end(png, info);
-    fclose(fb_in);
-    png_destroy_write_struct(&png, NULL);
-}
-
-void fork_sound(const char* path) {
-    pid_t pid = fork();
-    if (pid == 0) {
-        execl("/system/bin/stagefright", "stagefright", "-o", "-a", path, NULL);
-    }
-}
-
-void usage() {
-    fprintf(stderr,
-            "usage: screenshot [-s soundfile] filename.png\n"
-            "   -s: play a sound effect to signal success\n"
-            "   -i: autoincrement to avoid overwriting filename.png\n"
-    );
-}
-
-int main(int argc, char**argv) {
-    FILE *png = NULL;
-    FILE *fb_in = NULL;
-    char outfile[PATH_MAX] = "";
-
-    char * soundfile = NULL;
-    int do_increment = 0;
-
-    int c;
-    while ((c = getopt(argc, argv, "s:i")) != -1) {
-        switch (c) {
-            case 's': soundfile = optarg; break;
-            case 'i': do_increment = 1; break;
-            case '?':
-            case 'h':
-                usage(); exit(1);
-        }
-    }
-    argc -= optind;
-    argv += optind;
-
-    if (argc < 1) {
-        usage(); exit(1);
-    }
-
-    strlcpy(outfile, argv[0], PATH_MAX);
-    if (do_increment) {
-        struct stat st;
-        char base[PATH_MAX] = "";
-        int i = 0;
-        while (stat(outfile, &st) == 0) {
-            if (!base[0]) {
-                char *p = strrchr(outfile, '.');
-                if (p) *p = '\0';
-                strcpy(base, outfile);
-            }
-            snprintf(outfile, PATH_MAX, "%s-%d.png", base, ++i);
-        }
-    }
-
-    fb_in = fopen("/dev/graphics/fb0", "r");
-    if (!fb_in) {
-        fprintf(stderr, "error: could not read framebuffer\n");
-        exit(1);
-    }
-
-    /* switch to non-root user and group */
-    gid_t groups[] = { AID_LOG, AID_SDCARD_RW };
-    setgroups(sizeof(groups)/sizeof(groups[0]), groups);
-    setuid(AID_SHELL);
-
-    png = fopen(outfile, "w");
-    if (!png) {
-        fprintf(stderr, "error: writing file %s: %s\n",
-                outfile, strerror(errno));
-        exit(1);
-    }
-
-    take_screenshot(fb_in, png);
-
-    if (soundfile) {
-        fork_sound(soundfile);
-    }
-
-    exit(0);
-}
diff --git a/cmds/service/Android.mk b/cmds/service/Android.mk
deleted file mode 100644
index 275bbb2..0000000
--- a/cmds/service/Android.mk
+++ /dev/null
@@ -1,16 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
-	service.cpp
-
-LOCAL_SHARED_LIBRARIES := libutils libbinder
-
-ifeq ($(TARGET_OS),linux)
-	LOCAL_CFLAGS += -DXP_UNIX
-	#LOCAL_SHARED_LIBRARIES += librt
-endif
-
-LOCAL_MODULE:= service
-
-include $(BUILD_EXECUTABLE)
diff --git a/cmds/service/MODULE_LICENSE_APACHE2 b/cmds/service/MODULE_LICENSE_APACHE2
deleted file mode 100644
index e69de29..0000000
--- a/cmds/service/MODULE_LICENSE_APACHE2
+++ /dev/null
diff --git a/cmds/service/NOTICE b/cmds/service/NOTICE
deleted file mode 100644
index c5b1efa..0000000
--- a/cmds/service/NOTICE
+++ /dev/null
@@ -1,190 +0,0 @@
-
-   Copyright (c) 2005-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.
-
-   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.
-
-
-                                 Apache License
-                           Version 2.0, January 2004
-                        http://www.apache.org/licenses/
-
-   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
-   1. Definitions.
-
-      "License" shall mean the terms and conditions for use, reproduction,
-      and distribution as defined by Sections 1 through 9 of this document.
-
-      "Licensor" shall mean the copyright owner or entity authorized by
-      the copyright owner that is granting the License.
-
-      "Legal Entity" shall mean the union of the acting entity and all
-      other entities that control, are controlled by, or are under common
-      control with that entity. For the purposes of this definition,
-      "control" means (i) the power, direct or indirect, to cause the
-      direction or management of such entity, whether by contract or
-      otherwise, or (ii) ownership of fifty percent (50%) or more of the
-      outstanding shares, or (iii) beneficial ownership of such entity.
-
-      "You" (or "Your") shall mean an individual or Legal Entity
-      exercising permissions granted by this License.
-
-      "Source" form shall mean the preferred form for making modifications,
-      including but not limited to software source code, documentation
-      source, and configuration files.
-
-      "Object" form shall mean any form resulting from mechanical
-      transformation or translation of a Source form, including but
-      not limited to compiled object code, generated documentation,
-      and conversions to other media types.
-
-      "Work" shall mean the work of authorship, whether in Source or
-      Object form, made available under the License, as indicated by a
-      copyright notice that is included in or attached to the work
-      (an example is provided in the Appendix below).
-
-      "Derivative Works" shall mean any work, whether in Source or Object
-      form, that is based on (or derived from) the Work and for which the
-      editorial revisions, annotations, elaborations, or other modifications
-      represent, as a whole, an original work of authorship. For the purposes
-      of this License, Derivative Works shall not include works that remain
-      separable from, or merely link (or bind by name) to the interfaces of,
-      the Work and Derivative Works thereof.
-
-      "Contribution" shall mean any work of authorship, including
-      the original version of the Work and any modifications or additions
-      to that Work or Derivative Works thereof, that is intentionally
-      submitted to Licensor for inclusion in the Work by the copyright owner
-      or by an individual or Legal Entity authorized to submit on behalf of
-      the copyright owner. For the purposes of this definition, "submitted"
-      means any form of electronic, verbal, or written communication sent
-      to the Licensor or its representatives, including but not limited to
-      communication on electronic mailing lists, source code control systems,
-      and issue tracking systems that are managed by, or on behalf of, the
-      Licensor for the purpose of discussing and improving the Work, but
-      excluding communication that is conspicuously marked or otherwise
-      designated in writing by the copyright owner as "Not a Contribution."
-
-      "Contributor" shall mean Licensor and any individual or Legal Entity
-      on behalf of whom a Contribution has been received by Licensor and
-      subsequently incorporated within the Work.
-
-   2. Grant of Copyright License. Subject to the terms and conditions of
-      this License, each Contributor hereby grants to You a perpetual,
-      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-      copyright license to reproduce, prepare Derivative Works of,
-      publicly display, publicly perform, sublicense, and distribute the
-      Work and such Derivative Works in Source or Object form.
-
-   3. Grant of Patent License. Subject to the terms and conditions of
-      this License, each Contributor hereby grants to You a perpetual,
-      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-      (except as stated in this section) patent license to make, have made,
-      use, offer to sell, sell, import, and otherwise transfer the Work,
-      where such license applies only to those patent claims licensable
-      by such Contributor that are necessarily infringed by their
-      Contribution(s) alone or by combination of their Contribution(s)
-      with the Work to which such Contribution(s) was submitted. If You
-      institute patent litigation against any entity (including a
-      cross-claim or counterclaim in a lawsuit) alleging that the Work
-      or a Contribution incorporated within the Work constitutes direct
-      or contributory patent infringement, then any patent licenses
-      granted to You under this License for that Work shall terminate
-      as of the date such litigation is filed.
-
-   4. Redistribution. You may reproduce and distribute copies of the
-      Work or Derivative Works thereof in any medium, with or without
-      modifications, and in Source or Object form, provided that You
-      meet the following conditions:
-
-      (a) You must give any other recipients of the Work or
-          Derivative Works a copy of this License; and
-
-      (b) You must cause any modified files to carry prominent notices
-          stating that You changed the files; and
-
-      (c) You must retain, in the Source form of any Derivative Works
-          that You distribute, all copyright, patent, trademark, and
-          attribution notices from the Source form of the Work,
-          excluding those notices that do not pertain to any part of
-          the Derivative Works; and
-
-      (d) If the Work includes a "NOTICE" text file as part of its
-          distribution, then any Derivative Works that You distribute must
-          include a readable copy of the attribution notices contained
-          within such NOTICE file, excluding those notices that do not
-          pertain to any part of the Derivative Works, in at least one
-          of the following places: within a NOTICE text file distributed
-          as part of the Derivative Works; within the Source form or
-          documentation, if provided along with the Derivative Works; or,
-          within a display generated by the Derivative Works, if and
-          wherever such third-party notices normally appear. The contents
-          of the NOTICE file are for informational purposes only and
-          do not modify the License. You may add Your own attribution
-          notices within Derivative Works that You distribute, alongside
-          or as an addendum to the NOTICE text from the Work, provided
-          that such additional attribution notices cannot be construed
-          as modifying the License.
-
-      You may add Your own copyright statement to Your modifications and
-      may provide additional or different license terms and conditions
-      for use, reproduction, or distribution of Your modifications, or
-      for any such Derivative Works as a whole, provided Your use,
-      reproduction, and distribution of the Work otherwise complies with
-      the conditions stated in this License.
-
-   5. Submission of Contributions. Unless You explicitly state otherwise,
-      any Contribution intentionally submitted for inclusion in the Work
-      by You to the Licensor shall be under the terms and conditions of
-      this License, without any additional terms or conditions.
-      Notwithstanding the above, nothing herein shall supersede or modify
-      the terms of any separate license agreement you may have executed
-      with Licensor regarding such Contributions.
-
-   6. Trademarks. This License does not grant permission to use the trade
-      names, trademarks, service marks, or product names of the Licensor,
-      except as required for reasonable and customary use in describing the
-      origin of the Work and reproducing the content of the NOTICE file.
-
-   7. Disclaimer of Warranty. Unless required by applicable law or
-      agreed to in writing, Licensor provides the Work (and each
-      Contributor provides its Contributions) on an "AS IS" BASIS,
-      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-      implied, including, without limitation, any warranties or conditions
-      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
-      PARTICULAR PURPOSE. You are solely responsible for determining the
-      appropriateness of using or redistributing the Work and assume any
-      risks associated with Your exercise of permissions under this License.
-
-   8. Limitation of Liability. In no event and under no legal theory,
-      whether in tort (including negligence), contract, or otherwise,
-      unless required by applicable law (such as deliberate and grossly
-      negligent acts) or agreed to in writing, shall any Contributor be
-      liable to You for damages, including any direct, indirect, special,
-      incidental, or consequential damages of any character arising as a
-      result of this License or out of the use or inability to use the
-      Work (including but not limited to damages for loss of goodwill,
-      work stoppage, computer failure or malfunction, or any and all
-      other commercial damages or losses), even if such Contributor
-      has been advised of the possibility of such damages.
-
-   9. Accepting Warranty or Additional Liability. While redistributing
-      the Work or Derivative Works thereof, You may choose to offer,
-      and charge a fee for, acceptance of support, warranty, indemnity,
-      or other liability obligations and/or rights consistent with this
-      License. However, in accepting such obligations, You may act only
-      on Your own behalf and on Your sole responsibility, not on behalf
-      of any other Contributor, and only if You agree to indemnify,
-      defend, and hold each Contributor harmless for any liability
-      incurred by, or claims asserted against, such Contributor by reason
-      of your accepting any such warranty or additional liability.
-
-   END OF TERMS AND CONDITIONS
-
diff --git a/cmds/service/service.cpp b/cmds/service/service.cpp
deleted file mode 100644
index 32db83b..0000000
--- a/cmds/service/service.cpp
+++ /dev/null
@@ -1,275 +0,0 @@
-/*
- * Command line access to services.
- *
- */
- 
-#include <binder/Parcel.h>
-#include <binder/ProcessState.h>
-#include <binder/IServiceManager.h>
-#include <utils/TextOutput.h>
-
-#include <getopt.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-#include <sys/time.h>
-
-using namespace android;
-
-void writeString16(Parcel& parcel, const char* string)
-{
-    if (string != NULL)
-    {
-        parcel.writeString16(String16(string));
-    }
-    else
-    {
-        parcel.writeInt32(-1);
-    }
-}
-
-// get the name of the generic interface we hold a reference to
-static String16 get_interface_name(sp<IBinder> service)
-{
-    if (service != NULL) {
-        Parcel data, reply;
-        status_t err = service->transact(IBinder::INTERFACE_TRANSACTION, data, &reply);
-        if (err == NO_ERROR) {
-            return reply.readString16();
-        }
-    }
-    return String16();
-}
-
-static String8 good_old_string(const String16& src)
-{
-    String8 name8;
-    char ch8[2];
-    ch8[1] = 0;
-    for (unsigned j = 0; j < src.size(); j++) {
-        char16_t ch = src[j];
-        if (ch < 128) ch8[0] = (char)ch;
-        name8.append(ch8);
-    }
-    return name8;
-}
-
-int main(int argc, char* const argv[])
-{
-    sp<IServiceManager> sm = defaultServiceManager();
-    fflush(stdout);
-    if (sm == NULL) {
-        aerr << "service: Unable to get default service manager!" << endl;
-        return 20;
-    }
-    
-    bool wantsUsage = false;
-    int result = 0;
-    
-    while (1) {
-        int ic = getopt(argc, argv, "h?");
-        if (ic < 0)
-            break;
-
-        switch (ic) {
-        case 'h':
-        case '?':
-            wantsUsage = true;
-            break;
-        default:
-            aerr << "service: Unknown option -" << ic << endl;
-            wantsUsage = true;
-            result = 10;
-            break;
-        }
-    }
-    
-    if (optind >= argc) {
-        wantsUsage = true;
-    } else if (!wantsUsage) {
-        if (strcmp(argv[optind], "check") == 0) {
-            optind++;
-            if (optind < argc) {
-                sp<IBinder> service = sm->checkService(String16(argv[optind]));
-                aout << "Service " << argv[optind] <<
-                    (service == NULL ? ": not found" : ": found") << endl;
-            } else {
-                aerr << "service: No service specified for check" << endl;
-                wantsUsage = true;
-                result = 10;
-            }
-        }
-        else if (strcmp(argv[optind], "list") == 0) {
-            Vector<String16> services = sm->listServices();
-            aout << "Found " << services.size() << " services:" << endl;
-            for (unsigned i = 0; i < services.size(); i++) {
-                String16 name = services[i];
-                sp<IBinder> service = sm->checkService(name);
-                aout << i 
-                     << "\t" << good_old_string(name) 
-                     << ": [" << good_old_string(get_interface_name(service)) << "]"
-                     << endl;
-            }
-        } else if (strcmp(argv[optind], "call") == 0) {
-            optind++;
-            if (optind+1 < argc) {
-                int serviceArg = optind;
-                sp<IBinder> service = sm->checkService(String16(argv[optind++]));
-                String16 ifName = get_interface_name(service);
-                int32_t code = atoi(argv[optind++]);
-                if (service != NULL && ifName.size() > 0) {
-                    Parcel data, reply;
-
-                    // the interface name is first
-                    data.writeInterfaceToken(ifName);
-
-                    // then the rest of the call arguments
-                    while (optind < argc) {
-                        if (strcmp(argv[optind], "i32") == 0) {
-                            optind++;
-                            if (optind >= argc) {
-                                aerr << "service: no integer supplied for 'i32'" << endl;
-                                wantsUsage = true;
-                                result = 10;
-                                break;
-                            }
-                            data.writeInt32(atoi(argv[optind++]));
-                        } else if (strcmp(argv[optind], "s16") == 0) {
-                            optind++;
-                            if (optind >= argc) {
-                                aerr << "service: no string supplied for 's16'" << endl;
-                                wantsUsage = true;
-                                result = 10;
-                                break;
-                            }
-                            data.writeString16(String16(argv[optind++]));
-                        } else if (strcmp(argv[optind], "null") == 0) {
-                            optind++;
-                            data.writeStrongBinder(NULL);
-                        } else if (strcmp(argv[optind], "intent") == 0) {
-                        	
-                        	char* action = NULL;
-                        	char* dataArg = NULL;
-                        	char* type = NULL;
-                        	int launchFlags = 0;
-                        	char* component = NULL;
-                        	int categoryCount = 0;
-                        	char* categories[16];
-                        	
-                        	char* context1 = NULL;
-                        	
-                            optind++;
-                            
-                        	while (optind < argc)
-                        	{
-                        		char* key = strtok_r(argv[optind], "=", &context1);
-                        		char* value = strtok_r(NULL, "=", &context1);
-                                
-                                // we have reached the end of the XXX=XXX args.
-                                if (key == NULL) break;
-                        		
-                        		if (strcmp(key, "action") == 0)
-                        		{
-                        			action = value;
-                        		}
-                        		else if (strcmp(key, "data") == 0)
-                        		{
-                        			dataArg = value;
-                        		}
-                        		else if (strcmp(key, "type") == 0)
-                        		{
-                        			type = value;
-                        		}
-                        		else if (strcmp(key, "launchFlags") == 0)
-                        		{
-                        			launchFlags = atoi(value);
-                        		}
-                        		else if (strcmp(key, "component") == 0)
-                        		{
-                        			component = value;
-                        		}
-                        		else if (strcmp(key, "categories") == 0)
-                        		{
-                        			char* context2 = NULL;
-                        			int categoryCount = 0;
-                        			categories[categoryCount] = strtok_r(value, ",", &context2);
-                        			
-                        			while (categories[categoryCount] != NULL)
-                        			{
-                        				categoryCount++;
-                        				categories[categoryCount] = strtok_r(NULL, ",", &context2);
-                        			}
-                        		}
-                                
-                                optind++;
-                        	} 
-                        	
-                            writeString16(data, action);
-                            writeString16(data, dataArg);
-                            writeString16(data, type);
-                       		data.writeInt32(launchFlags);
-                            writeString16(data, component);
-                        	
-                            if (categoryCount > 0)
-                            {
-                                data.writeInt32(categoryCount);
-                                for (int i = 0 ; i < categoryCount ; i++)
-                                {
-                                    writeString16(data, categories[i]);
-                                }
-                            }
-                            else
-                            {
-                                data.writeInt32(0);
-                            }                            
-  
-                            // for now just set the extra field to be null.
-                       		data.writeInt32(-1);
-                        } else {
-                            aerr << "service: unknown option " << argv[optind] << endl;
-                            wantsUsage = true;
-                            result = 10;
-                            break;
-                        }
-                    }
-                    
-                    service->transact(code, data, &reply);
-                    aout << "Result: " << reply << endl;
-                } else {
-                    aerr << "service: Service " << argv[serviceArg]
-                        << " does not exist" << endl;
-                    result = 10;
-                }
-            } else {
-                if (optind < argc) {
-                    aerr << "service: No service specified for call" << endl;
-                } else {
-                    aerr << "service: No code specified for call" << endl;
-                }
-                wantsUsage = true;
-                result = 10;
-            }
-        } else {
-            aerr << "service: Unknown command " << argv[optind] << endl;
-            wantsUsage = true;
-            result = 10;
-        }
-    }
-    
-    if (wantsUsage) {
-        aout << "Usage: service [-h|-?]\n"
-                "       service list\n"
-                "       service check SERVICE\n"
-                "       service call SERVICE CODE [i32 INT | s16 STR] ...\n"
-                "Options:\n"
-                "   i32: Write the integer INT into the send parcel.\n"
-                "   s16: Write the UTF-16 string STR into the send parcel.\n";
-//                "   intent: Write and Intent int the send parcel. ARGS can be\n"
-//                "       action=STR data=STR type=STR launchFlags=INT component=STR categories=STR[,STR,...]\n";
-        return result;
-    }
-    
-    return result;
-}
-
diff --git a/cmds/servicemanager/Android.mk b/cmds/servicemanager/Android.mk
deleted file mode 100644
index 8840867..0000000
--- a/cmds/servicemanager/Android.mk
+++ /dev/null
@@ -1,12 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-
-#include $(CLEAR_VARS)
-#LOCAL_SRC_FILES := bctest.c binder.c
-#LOCAL_MODULE := bctest
-#include $(BUILD_EXECUTABLE)
-
-include $(CLEAR_VARS)
-LOCAL_SHARED_LIBRARIES := liblog
-LOCAL_SRC_FILES := service_manager.c binder.c
-LOCAL_MODULE := servicemanager
-include $(BUILD_EXECUTABLE)
diff --git a/cmds/servicemanager/bctest.c b/cmds/servicemanager/bctest.c
deleted file mode 100644
index ff5aced..0000000
--- a/cmds/servicemanager/bctest.c
+++ /dev/null
@@ -1,103 +0,0 @@
-/* Copyright 2008 The Android Open Source Project
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <errno.h>
-
-#include "binder.h"
-
-void *svcmgr_lookup(struct binder_state *bs, void *target, const char *name)
-{
-    void *ptr;
-    unsigned iodata[512/4];
-    struct binder_io msg, reply;
-
-    bio_init(&msg, iodata, sizeof(iodata), 4);
-    bio_put_uint32(&msg, 0);  // strict mode header
-    bio_put_string16_x(&msg, SVC_MGR_NAME);
-    bio_put_string16_x(&msg, name);
-
-    if (binder_call(bs, &msg, &reply, target, SVC_MGR_CHECK_SERVICE))
-        return 0;
-
-    ptr = bio_get_ref(&reply);
-
-    if (ptr)
-        binder_acquire(bs, ptr);
-
-    binder_done(bs, &msg, &reply);
-
-    return ptr;
-}
-
-int svcmgr_publish(struct binder_state *bs, void *target, const char *name, void *ptr)
-{
-    unsigned status;
-    unsigned iodata[512/4];
-    struct binder_io msg, reply;
-
-    bio_init(&msg, iodata, sizeof(iodata), 4);
-    bio_put_uint32(&msg, 0);  // strict mode header
-    bio_put_string16_x(&msg, SVC_MGR_NAME);
-    bio_put_string16_x(&msg, name);
-    bio_put_obj(&msg, ptr);
-
-    if (binder_call(bs, &msg, &reply, target, SVC_MGR_ADD_SERVICE))
-        return -1;
-
-    status = bio_get_uint32(&reply);
-
-    binder_done(bs, &msg, &reply);
-
-    return status;
-}
-
-unsigned token;
-
-int main(int argc, char **argv)
-{
-    int fd;
-    struct binder_state *bs;
-    void *svcmgr = BINDER_SERVICE_MANAGER;
-
-    bs = binder_open(128*1024);
-
-    argc--;
-    argv++;
-    while (argc > 0) {
-        if (!strcmp(argv[0],"alt")) {
-            void *ptr = svcmgr_lookup(bs, svcmgr, "alt_svc_mgr");
-            if (!ptr) {
-                fprintf(stderr,"cannot find alt_svc_mgr\n");
-                return -1;
-            }
-            svcmgr = ptr;
-            fprintf(stderr,"svcmgr is via %p\n", ptr);
-        } else if (!strcmp(argv[0],"lookup")) {
-            void *ptr;
-            if (argc < 2) {
-                fprintf(stderr,"argument required\n");
-                return -1;
-            }
-            ptr = svcmgr_lookup(bs, svcmgr, argv[1]);
-            fprintf(stderr,"lookup(%s) = %p\n", argv[1], ptr);
-            argc--;
-            argv++;
-        } else if (!strcmp(argv[0],"publish")) {
-            if (argc < 2) {
-                fprintf(stderr,"argument required\n");
-                return -1;
-            }
-            svcmgr_publish(bs, svcmgr, argv[1], &token);
-            argc--;
-            argv++;
-        } else {
-            fprintf(stderr,"unknown command %s\n", argv[0]);
-            return -1;
-        }
-        argc--;
-        argv++;
-    }
-    return 0;
-}
diff --git a/cmds/servicemanager/binder.c b/cmds/servicemanager/binder.c
deleted file mode 100644
index 1985756..0000000
--- a/cmds/servicemanager/binder.c
+++ /dev/null
@@ -1,616 +0,0 @@
-/* Copyright 2008 The Android Open Source Project
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <sys/mman.h>
-
-#include "binder.h"
-
-#define MAX_BIO_SIZE (1 << 30)
-
-#define TRACE 0
-
-#define LOG_TAG "Binder"
-#include <cutils/log.h>
-
-void bio_init_from_txn(struct binder_io *io, struct binder_txn *txn);
-
-#if TRACE
-void hexdump(void *_data, unsigned len)
-{
-    unsigned char *data = _data;
-    unsigned count;
-
-    for (count = 0; count < len; count++) {
-        if ((count & 15) == 0)
-            fprintf(stderr,"%04x:", count);
-        fprintf(stderr," %02x %c", *data,
-                (*data < 32) || (*data > 126) ? '.' : *data);
-        data++;
-        if ((count & 15) == 15)
-            fprintf(stderr,"\n");
-    }
-    if ((count & 15) != 0)
-        fprintf(stderr,"\n");
-}
-
-void binder_dump_txn(struct binder_txn *txn)
-{
-    struct binder_object *obj;
-    unsigned *offs = txn->offs;
-    unsigned count = txn->offs_size / 4;
-
-    fprintf(stderr,"  target %p  cookie %p  code %08x  flags %08x\n",
-            txn->target, txn->cookie, txn->code, txn->flags);
-    fprintf(stderr,"  pid %8d  uid %8d  data %8d  offs %8d\n",
-            txn->sender_pid, txn->sender_euid, txn->data_size, txn->offs_size);
-    hexdump(txn->data, txn->data_size);
-    while (count--) {
-        obj = (void*) (((char*) txn->data) + *offs++);
-        fprintf(stderr,"  - type %08x  flags %08x  ptr %p  cookie %p\n",
-                obj->type, obj->flags, obj->pointer, obj->cookie);
-    }
-}
-
-#define NAME(n) case n: return #n
-const char *cmd_name(uint32_t cmd)
-{
-    switch(cmd) {
-        NAME(BR_NOOP);
-        NAME(BR_TRANSACTION_COMPLETE);
-        NAME(BR_INCREFS);
-        NAME(BR_ACQUIRE);
-        NAME(BR_RELEASE);
-        NAME(BR_DECREFS);
-        NAME(BR_TRANSACTION);
-        NAME(BR_REPLY);
-        NAME(BR_FAILED_REPLY);
-        NAME(BR_DEAD_REPLY);
-        NAME(BR_DEAD_BINDER);
-    default: return "???";
-    }
-}
-#else
-#define hexdump(a,b) do{} while (0)
-#define binder_dump_txn(txn)  do{} while (0)
-#endif
-
-#define BIO_F_SHARED    0x01  /* needs to be buffer freed */
-#define BIO_F_OVERFLOW  0x02  /* ran out of space */
-#define BIO_F_IOERROR   0x04
-#define BIO_F_MALLOCED  0x08  /* needs to be free()'d */
-
-struct binder_state
-{
-    int fd;
-    void *mapped;
-    unsigned mapsize;
-};
-
-struct binder_state *binder_open(unsigned mapsize)
-{
-    struct binder_state *bs;
-
-    bs = malloc(sizeof(*bs));
-    if (!bs) {
-        errno = ENOMEM;
-        return 0;
-    }
-
-    bs->fd = open("/dev/binder", O_RDWR);
-    if (bs->fd < 0) {
-        fprintf(stderr,"binder: cannot open device (%s)\n",
-                strerror(errno));
-        goto fail_open;
-    }
-
-    bs->mapsize = mapsize;
-    bs->mapped = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, bs->fd, 0);
-    if (bs->mapped == MAP_FAILED) {
-        fprintf(stderr,"binder: cannot map device (%s)\n",
-                strerror(errno));
-        goto fail_map;
-    }
-
-        /* TODO: check version */
-
-    return bs;
-
-fail_map:
-    close(bs->fd);
-fail_open:
-    free(bs);
-    return 0;
-}
-
-void binder_close(struct binder_state *bs)
-{
-    munmap(bs->mapped, bs->mapsize);
-    close(bs->fd);
-    free(bs);
-}
-
-int binder_become_context_manager(struct binder_state *bs)
-{
-    return ioctl(bs->fd, BINDER_SET_CONTEXT_MGR, 0);
-}
-
-int binder_write(struct binder_state *bs, void *data, unsigned len)
-{
-    struct binder_write_read bwr;
-    int res;
-    bwr.write_size = len;
-    bwr.write_consumed = 0;
-    bwr.write_buffer = (unsigned) data;
-    bwr.read_size = 0;
-    bwr.read_consumed = 0;
-    bwr.read_buffer = 0;
-    res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);
-    if (res < 0) {
-        fprintf(stderr,"binder_write: ioctl failed (%s)\n",
-                strerror(errno));
-    }
-    return res;
-}
-
-void binder_send_reply(struct binder_state *bs,
-                       struct binder_io *reply,
-                       void *buffer_to_free,
-                       int status)
-{
-    struct {
-        uint32_t cmd_free;
-        void *buffer;
-        uint32_t cmd_reply;
-        struct binder_txn txn;
-    } __attribute__((packed)) data;
-
-    data.cmd_free = BC_FREE_BUFFER;
-    data.buffer = buffer_to_free;
-    data.cmd_reply = BC_REPLY;
-    data.txn.target = 0;
-    data.txn.cookie = 0;
-    data.txn.code = 0;
-    if (status) {
-        data.txn.flags = TF_STATUS_CODE;
-        data.txn.data_size = sizeof(int);
-        data.txn.offs_size = 0;
-        data.txn.data = &status;
-        data.txn.offs = 0;
-    } else {
-        data.txn.flags = 0;
-        data.txn.data_size = reply->data - reply->data0;
-        data.txn.offs_size = ((char*) reply->offs) - ((char*) reply->offs0);
-        data.txn.data = reply->data0;
-        data.txn.offs = reply->offs0;
-    }
-    binder_write(bs, &data, sizeof(data));
-}
-
-int binder_parse(struct binder_state *bs, struct binder_io *bio,
-                 uint32_t *ptr, uint32_t size, binder_handler func)
-{
-    int r = 1;
-    uint32_t *end = ptr + (size / 4);
-
-    while (ptr < end) {
-        uint32_t cmd = *ptr++;
-#if TRACE
-        fprintf(stderr,"%s:\n", cmd_name(cmd));
-#endif
-        switch(cmd) {
-        case BR_NOOP:
-            break;
-        case BR_TRANSACTION_COMPLETE:
-            break;
-        case BR_INCREFS:
-        case BR_ACQUIRE:
-        case BR_RELEASE:
-        case BR_DECREFS:
-#if TRACE
-            fprintf(stderr,"  %08x %08x\n", ptr[0], ptr[1]);
-#endif
-            ptr += 2;
-            break;
-        case BR_TRANSACTION: {
-            struct binder_txn *txn = (void *) ptr;
-            if ((end - ptr) * sizeof(uint32_t) < sizeof(struct binder_txn)) {
-                ALOGE("parse: txn too small!\n");
-                return -1;
-            }
-            binder_dump_txn(txn);
-            if (func) {
-                unsigned rdata[256/4];
-                struct binder_io msg;
-                struct binder_io reply;
-                int res;
-
-                bio_init(&reply, rdata, sizeof(rdata), 4);
-                bio_init_from_txn(&msg, txn);
-                res = func(bs, txn, &msg, &reply);
-                binder_send_reply(bs, &reply, txn->data, res);
-            }
-            ptr += sizeof(*txn) / sizeof(uint32_t);
-            break;
-        }
-        case BR_REPLY: {
-            struct binder_txn *txn = (void*) ptr;
-            if ((end - ptr) * sizeof(uint32_t) < sizeof(struct binder_txn)) {
-                ALOGE("parse: reply too small!\n");
-                return -1;
-            }
-            binder_dump_txn(txn);
-            if (bio) {
-                bio_init_from_txn(bio, txn);
-                bio = 0;
-            } else {
-                    /* todo FREE BUFFER */
-            }
-            ptr += (sizeof(*txn) / sizeof(uint32_t));
-            r = 0;
-            break;
-        }
-        case BR_DEAD_BINDER: {
-            struct binder_death *death = (void*) *ptr++;
-            death->func(bs, death->ptr);
-            break;
-        }
-        case BR_FAILED_REPLY:
-            r = -1;
-            break;
-        case BR_DEAD_REPLY:
-            r = -1;
-            break;
-        default:
-            ALOGE("parse: OOPS %d\n", cmd);
-            return -1;
-        }
-    }
-
-    return r;
-}
-
-void binder_acquire(struct binder_state *bs, void *ptr)
-{
-    uint32_t cmd[2];
-    cmd[0] = BC_ACQUIRE;
-    cmd[1] = (uint32_t) ptr;
-    binder_write(bs, cmd, sizeof(cmd));
-}
-
-void binder_release(struct binder_state *bs, void *ptr)
-{
-    uint32_t cmd[2];
-    cmd[0] = BC_RELEASE;
-    cmd[1] = (uint32_t) ptr;
-    binder_write(bs, cmd, sizeof(cmd));
-}
-
-void binder_link_to_death(struct binder_state *bs, void *ptr, struct binder_death *death)
-{
-    uint32_t cmd[3];
-    cmd[0] = BC_REQUEST_DEATH_NOTIFICATION;
-    cmd[1] = (uint32_t) ptr;
-    cmd[2] = (uint32_t) death;
-    binder_write(bs, cmd, sizeof(cmd));
-}
-
-
-int binder_call(struct binder_state *bs,
-                struct binder_io *msg, struct binder_io *reply,
-                void *target, uint32_t code)
-{
-    int res;
-    struct binder_write_read bwr;
-    struct {
-        uint32_t cmd;
-        struct binder_txn txn;
-    } writebuf;
-    unsigned readbuf[32];
-
-    if (msg->flags & BIO_F_OVERFLOW) {
-        fprintf(stderr,"binder: txn buffer overflow\n");
-        goto fail;
-    }
-
-    writebuf.cmd = BC_TRANSACTION;
-    writebuf.txn.target = target;
-    writebuf.txn.code = code;
-    writebuf.txn.flags = 0;
-    writebuf.txn.data_size = msg->data - msg->data0;
-    writebuf.txn.offs_size = ((char*) msg->offs) - ((char*) msg->offs0);
-    writebuf.txn.data = msg->data0;
-    writebuf.txn.offs = msg->offs0;
-
-    bwr.write_size = sizeof(writebuf);
-    bwr.write_consumed = 0;
-    bwr.write_buffer = (unsigned) &writebuf;
-    
-    hexdump(msg->data0, msg->data - msg->data0);
-    for (;;) {
-        bwr.read_size = sizeof(readbuf);
-        bwr.read_consumed = 0;
-        bwr.read_buffer = (unsigned) readbuf;
-
-        res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);
-
-        if (res < 0) {
-            fprintf(stderr,"binder: ioctl failed (%s)\n", strerror(errno));
-            goto fail;
-        }
-
-        res = binder_parse(bs, reply, readbuf, bwr.read_consumed, 0);
-        if (res == 0) return 0;
-        if (res < 0) goto fail;
-    }
-
-fail:
-    memset(reply, 0, sizeof(*reply));
-    reply->flags |= BIO_F_IOERROR;
-    return -1;
-}
-
-void binder_loop(struct binder_state *bs, binder_handler func)
-{
-    int res;
-    struct binder_write_read bwr;
-    unsigned readbuf[32];
-
-    bwr.write_size = 0;
-    bwr.write_consumed = 0;
-    bwr.write_buffer = 0;
-    
-    readbuf[0] = BC_ENTER_LOOPER;
-    binder_write(bs, readbuf, sizeof(unsigned));
-
-    for (;;) {
-        bwr.read_size = sizeof(readbuf);
-        bwr.read_consumed = 0;
-        bwr.read_buffer = (unsigned) readbuf;
-
-        res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);
-
-        if (res < 0) {
-            ALOGE("binder_loop: ioctl failed (%s)\n", strerror(errno));
-            break;
-        }
-
-        res = binder_parse(bs, 0, readbuf, bwr.read_consumed, func);
-        if (res == 0) {
-            ALOGE("binder_loop: unexpected reply?!\n");
-            break;
-        }
-        if (res < 0) {
-            ALOGE("binder_loop: io error %d %s\n", res, strerror(errno));
-            break;
-        }
-    }
-}
-
-void bio_init_from_txn(struct binder_io *bio, struct binder_txn *txn)
-{
-    bio->data = bio->data0 = txn->data;
-    bio->offs = bio->offs0 = txn->offs;
-    bio->data_avail = txn->data_size;
-    bio->offs_avail = txn->offs_size / 4;
-    bio->flags = BIO_F_SHARED;
-}
-
-void bio_init(struct binder_io *bio, void *data,
-              uint32_t maxdata, uint32_t maxoffs)
-{
-    uint32_t n = maxoffs * sizeof(uint32_t);
-
-    if (n > maxdata) {
-        bio->flags = BIO_F_OVERFLOW;
-        bio->data_avail = 0;
-        bio->offs_avail = 0;
-        return;
-    }
-
-    bio->data = bio->data0 = (char *) data + n;
-    bio->offs = bio->offs0 = data;
-    bio->data_avail = maxdata - n;
-    bio->offs_avail = maxoffs;
-    bio->flags = 0;
-}
-
-static void *bio_alloc(struct binder_io *bio, uint32_t size)
-{
-    size = (size + 3) & (~3);
-    if (size > bio->data_avail) {
-        bio->flags |= BIO_F_OVERFLOW;
-        return 0;
-    } else {
-        void *ptr = bio->data;
-        bio->data += size;
-        bio->data_avail -= size;
-        return ptr;
-    }
-}
-
-void binder_done(struct binder_state *bs,
-                 struct binder_io *msg,
-                 struct binder_io *reply)
-{
-    if (reply->flags & BIO_F_SHARED) {
-        uint32_t cmd[2];
-        cmd[0] = BC_FREE_BUFFER;
-        cmd[1] = (uint32_t) reply->data0;
-        binder_write(bs, cmd, sizeof(cmd));
-        reply->flags = 0;
-    }
-}
-
-static struct binder_object *bio_alloc_obj(struct binder_io *bio)
-{
-    struct binder_object *obj;
-
-    obj = bio_alloc(bio, sizeof(*obj));
-    
-    if (obj && bio->offs_avail) {
-        bio->offs_avail--;
-        *bio->offs++ = ((char*) obj) - ((char*) bio->data0);
-        return obj;
-    }
-
-    bio->flags |= BIO_F_OVERFLOW;
-    return 0;
-}
-
-void bio_put_uint32(struct binder_io *bio, uint32_t n)
-{
-    uint32_t *ptr = bio_alloc(bio, sizeof(n));
-    if (ptr)
-        *ptr = n;
-}
-
-void bio_put_obj(struct binder_io *bio, void *ptr)
-{
-    struct binder_object *obj;
-
-    obj = bio_alloc_obj(bio);
-    if (!obj)
-        return;
-
-    obj->flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;
-    obj->type = BINDER_TYPE_BINDER;
-    obj->pointer = ptr;
-    obj->cookie = 0;
-}
-
-void bio_put_ref(struct binder_io *bio, void *ptr)
-{
-    struct binder_object *obj;
-
-    if (ptr)
-        obj = bio_alloc_obj(bio);
-    else
-        obj = bio_alloc(bio, sizeof(*obj));
-
-    if (!obj)
-        return;
-
-    obj->flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;
-    obj->type = BINDER_TYPE_HANDLE;
-    obj->pointer = ptr;
-    obj->cookie = 0;
-}
-
-void bio_put_string16(struct binder_io *bio, const uint16_t *str)
-{
-    uint32_t len;
-    uint16_t *ptr;
-
-    if (!str) {
-        bio_put_uint32(bio, 0xffffffff);
-        return;
-    }
-
-    len = 0;
-    while (str[len]) len++;
-
-    if (len >= (MAX_BIO_SIZE / sizeof(uint16_t))) {
-        bio_put_uint32(bio, 0xffffffff);
-        return;
-    }
-
-    bio_put_uint32(bio, len);
-    len = (len + 1) * sizeof(uint16_t);
-    ptr = bio_alloc(bio, len);
-    if (ptr)
-        memcpy(ptr, str, len);
-}
-
-void bio_put_string16_x(struct binder_io *bio, const char *_str)
-{
-    unsigned char *str = (unsigned char*) _str;
-    uint32_t len;
-    uint16_t *ptr;
-
-    if (!str) {
-        bio_put_uint32(bio, 0xffffffff);
-        return;
-    }
-
-    len = strlen(_str);
-
-    if (len >= (MAX_BIO_SIZE / sizeof(uint16_t))) {
-        bio_put_uint32(bio, 0xffffffff);
-        return;
-    }
-
-    bio_put_uint32(bio, len);
-    ptr = bio_alloc(bio, (len + 1) * sizeof(uint16_t));
-    if (!ptr)
-        return;
-
-    while (*str)
-        *ptr++ = *str++;
-    *ptr++ = 0;
-}
-
-static void *bio_get(struct binder_io *bio, uint32_t size)
-{
-    size = (size + 3) & (~3);
-
-    if (bio->data_avail < size){
-        bio->data_avail = 0;
-        bio->flags |= BIO_F_OVERFLOW;
-        return 0;
-    }  else {
-        void *ptr = bio->data;
-        bio->data += size;
-        bio->data_avail -= size;
-        return ptr;
-    }
-}
-
-uint32_t bio_get_uint32(struct binder_io *bio)
-{
-    uint32_t *ptr = bio_get(bio, sizeof(*ptr));
-    return ptr ? *ptr : 0;
-}
-
-uint16_t *bio_get_string16(struct binder_io *bio, unsigned *sz)
-{
-    unsigned len;
-    len = bio_get_uint32(bio);
-    if (sz)
-        *sz = len;
-    return bio_get(bio, (len + 1) * sizeof(uint16_t));
-}
-
-static struct binder_object *_bio_get_obj(struct binder_io *bio)
-{
-    unsigned n;
-    unsigned off = bio->data - bio->data0;
-
-        /* TODO: be smarter about this? */
-    for (n = 0; n < bio->offs_avail; n++) {
-        if (bio->offs[n] == off)
-            return bio_get(bio, sizeof(struct binder_object));
-    }
-
-    bio->data_avail = 0;
-    bio->flags |= BIO_F_OVERFLOW;
-    return 0;
-}
-
-void *bio_get_ref(struct binder_io *bio)
-{
-    struct binder_object *obj;
-
-    obj = _bio_get_obj(bio);
-    if (!obj)
-        return 0;
-
-    if (obj->type == BINDER_TYPE_HANDLE)
-        return obj->pointer;
-
-    return 0;
-}
diff --git a/cmds/servicemanager/binder.h b/cmds/servicemanager/binder.h
deleted file mode 100644
index d8c51ef..0000000
--- a/cmds/servicemanager/binder.h
+++ /dev/null
@@ -1,119 +0,0 @@
-/* Copyright 2008 The Android Open Source Project
- */
-
-#ifndef _BINDER_H_
-#define _BINDER_H_
-
-#include <sys/ioctl.h>
-#include <linux/binder.h>
-
-struct binder_state;
-
-struct binder_object
-{
-    uint32_t type;
-    uint32_t flags;
-    void *pointer;
-    void *cookie;
-};
-
-struct binder_txn
-{
-    void *target;
-    void *cookie;
-    uint32_t code;
-    uint32_t flags;
-
-    uint32_t sender_pid;
-    uint32_t sender_euid;
-
-    uint32_t data_size;
-    uint32_t offs_size;
-    void *data;
-    void *offs;
-};
-
-struct binder_io
-{
-    char *data;            /* pointer to read/write from */
-    uint32_t *offs;        /* array of offsets */
-    uint32_t data_avail;   /* bytes available in data buffer */
-    uint32_t offs_avail;   /* entries available in offsets array */
-
-    char *data0;           /* start of data buffer */
-    uint32_t *offs0;       /* start of offsets buffer */
-    uint32_t flags;
-    uint32_t unused;
-};
-
-struct binder_death {
-    void (*func)(struct binder_state *bs, void *ptr);
-    void *ptr;
-};    
-
-/* the one magic object */
-#define BINDER_SERVICE_MANAGER ((void*) 0)
-
-#define SVC_MGR_NAME "android.os.IServiceManager"
-
-enum {
-    SVC_MGR_GET_SERVICE = 1,
-    SVC_MGR_CHECK_SERVICE,
-    SVC_MGR_ADD_SERVICE,
-    SVC_MGR_LIST_SERVICES,
-};
-
-typedef int (*binder_handler)(struct binder_state *bs,
-                              struct binder_txn *txn,
-                              struct binder_io *msg,
-                              struct binder_io *reply);
-
-struct binder_state *binder_open(unsigned mapsize);
-void binder_close(struct binder_state *bs);
-
-/* initiate a blocking binder call
- * - returns zero on success
- */
-int binder_call(struct binder_state *bs,
-                struct binder_io *msg, struct binder_io *reply,
-                void *target, uint32_t code);
-
-/* release any state associate with the binder_io
- * - call once any necessary data has been extracted from the
- *   binder_io after binder_call() returns
- * - can safely be called even if binder_call() fails
- */
-void binder_done(struct binder_state *bs,
-                 struct binder_io *msg, struct binder_io *reply);
-
-/* manipulate strong references */
-void binder_acquire(struct binder_state *bs, void *ptr);
-void binder_release(struct binder_state *bs, void *ptr);
-
-void binder_link_to_death(struct binder_state *bs, void *ptr, struct binder_death *death);
-
-void binder_loop(struct binder_state *bs, binder_handler func);
-
-int binder_become_context_manager(struct binder_state *bs);
-
-/* allocate a binder_io, providing a stack-allocated working
- * buffer, size of the working buffer, and how many object
- * offset entries to reserve from the buffer
- */
-void bio_init(struct binder_io *bio, void *data,
-           uint32_t maxdata, uint32_t maxobjects);
-
-void bio_destroy(struct binder_io *bio);
-
-void bio_put_obj(struct binder_io *bio, void *ptr);
-void bio_put_ref(struct binder_io *bio, void *ptr);
-void bio_put_uint32(struct binder_io *bio, uint32_t n);
-void bio_put_string16(struct binder_io *bio, const uint16_t *str);
-void bio_put_string16_x(struct binder_io *bio, const char *_str);
-
-uint32_t bio_get_uint32(struct binder_io *bio);
-uint16_t *bio_get_string16(struct binder_io *bio, uint32_t *sz);
-void *bio_get_obj(struct binder_io *bio);
-void *bio_get_ref(struct binder_io *bio);
-
-#endif
diff --git a/cmds/servicemanager/service_manager.c b/cmds/servicemanager/service_manager.c
deleted file mode 100644
index c563a82..0000000
--- a/cmds/servicemanager/service_manager.c
+++ /dev/null
@@ -1,287 +0,0 @@
-/* Copyright 2008 The Android Open Source Project
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <fcntl.h>
-
-#include <private/android_filesystem_config.h>
-
-#include "binder.h"
-
-#if 0
-#define ALOGI(x...) fprintf(stderr, "svcmgr: " x)
-#define ALOGE(x...) fprintf(stderr, "svcmgr: " x)
-#else
-#define LOG_TAG "ServiceManager"
-#include <cutils/log.h>
-#endif
-
-/* TODO:
- * These should come from a config file or perhaps be
- * based on some namespace rules of some sort (media
- * uid can register media.*, etc)
- */
-static struct {
-    unsigned uid;
-    const char *name;
-} allowed[] = {
-    { AID_MEDIA, "media.audio_flinger" },
-    { AID_MEDIA, "media.player" },
-    { AID_MEDIA, "media.camera" },
-    { AID_MEDIA, "media.audio_policy" },
-    { AID_MEDIA, "android.media.IAAHMetaDataService" },
-    { AID_DRM,   "drm.drmManager" },
-    { AID_NFC,   "nfc" },
-    { AID_BLUETOOTH, "bluetooth" },
-    { AID_RADIO, "radio.phone" },
-    { AID_RADIO, "radio.sms" },
-    { AID_RADIO, "radio.phonesubinfo" },
-    { AID_RADIO, "radio.simphonebook" },
-/* TODO: remove after phone services are updated: */
-    { AID_RADIO, "phone" },
-    { AID_RADIO, "sip" },
-    { AID_RADIO, "isms" },
-    { AID_RADIO, "iphonesubinfo" },
-    { AID_RADIO, "simphonebook" },
-    { AID_MEDIA, "common_time.clock" },
-    { AID_MEDIA, "common_time.config" },
-    { AID_KEYSTORE, "android.security.keystore" },
-};
-
-void *svcmgr_handle;
-
-const char *str8(uint16_t *x)
-{
-    static char buf[128];
-    unsigned max = 127;
-    char *p = buf;
-
-    if (x) {
-        while (*x && max--) {
-            *p++ = *x++;
-        }
-    }
-    *p++ = 0;
-    return buf;
-}
-
-int str16eq(uint16_t *a, const char *b)
-{
-    while (*a && *b)
-        if (*a++ != *b++) return 0;
-    if (*a || *b)
-        return 0;
-    return 1;
-}
-
-int svc_can_register(unsigned uid, uint16_t *name)
-{
-    unsigned n;
-    
-    if ((uid == 0) || (uid == AID_SYSTEM))
-        return 1;
-
-    for (n = 0; n < sizeof(allowed) / sizeof(allowed[0]); n++)
-        if ((uid == allowed[n].uid) && str16eq(name, allowed[n].name))
-            return 1;
-
-    return 0;
-}
-
-struct svcinfo 
-{
-    struct svcinfo *next;
-    void *ptr;
-    struct binder_death death;
-    int allow_isolated;
-    unsigned len;
-    uint16_t name[0];
-};
-
-struct svcinfo *svclist = 0;
-
-struct svcinfo *find_svc(uint16_t *s16, unsigned len)
-{
-    struct svcinfo *si;
-
-    for (si = svclist; si; si = si->next) {
-        if ((len == si->len) &&
-            !memcmp(s16, si->name, len * sizeof(uint16_t))) {
-            return si;
-        }
-    }
-    return 0;
-}
-
-void svcinfo_death(struct binder_state *bs, void *ptr)
-{
-    struct svcinfo *si = ptr;
-    ALOGI("service '%s' died\n", str8(si->name));
-    if (si->ptr) {
-        binder_release(bs, si->ptr);
-        si->ptr = 0;
-    }   
-}
-
-uint16_t svcmgr_id[] = { 
-    'a','n','d','r','o','i','d','.','o','s','.',
-    'I','S','e','r','v','i','c','e','M','a','n','a','g','e','r' 
-};
-  
-
-void *do_find_service(struct binder_state *bs, uint16_t *s, unsigned len, unsigned uid)
-{
-    struct svcinfo *si;
-    si = find_svc(s, len);
-
-//    ALOGI("check_service('%s') ptr = %p\n", str8(s), si ? si->ptr : 0);
-    if (si && si->ptr) {
-        if (!si->allow_isolated) {
-            // If this service doesn't allow access from isolated processes,
-            // then check the uid to see if it is isolated.
-            unsigned appid = uid % AID_USER;
-            if (appid >= AID_ISOLATED_START && appid <= AID_ISOLATED_END) {
-                return 0;
-            }
-        }
-        return si->ptr;
-    } else {
-        return 0;
-    }
-}
-
-int do_add_service(struct binder_state *bs,
-                   uint16_t *s, unsigned len,
-                   void *ptr, unsigned uid, int allow_isolated)
-{
-    struct svcinfo *si;
-    //ALOGI("add_service('%s',%p,%s) uid=%d\n", str8(s), ptr,
-    //        allow_isolated ? "allow_isolated" : "!allow_isolated", uid);
-
-    if (!ptr || (len == 0) || (len > 127))
-        return -1;
-
-    if (!svc_can_register(uid, s)) {
-        ALOGE("add_service('%s',%p) uid=%d - PERMISSION DENIED\n",
-             str8(s), ptr, uid);
-        return -1;
-    }
-
-    si = find_svc(s, len);
-    if (si) {
-        if (si->ptr) {
-            ALOGE("add_service('%s',%p) uid=%d - ALREADY REGISTERED, OVERRIDE\n",
-                 str8(s), ptr, uid);
-            svcinfo_death(bs, si);
-        }
-        si->ptr = ptr;
-    } else {
-        si = malloc(sizeof(*si) + (len + 1) * sizeof(uint16_t));
-        if (!si) {
-            ALOGE("add_service('%s',%p) uid=%d - OUT OF MEMORY\n",
-                 str8(s), ptr, uid);
-            return -1;
-        }
-        si->ptr = ptr;
-        si->len = len;
-        memcpy(si->name, s, (len + 1) * sizeof(uint16_t));
-        si->name[len] = '\0';
-        si->death.func = svcinfo_death;
-        si->death.ptr = si;
-        si->allow_isolated = allow_isolated;
-        si->next = svclist;
-        svclist = si;
-    }
-
-    binder_acquire(bs, ptr);
-    binder_link_to_death(bs, ptr, &si->death);
-    return 0;
-}
-
-int svcmgr_handler(struct binder_state *bs,
-                   struct binder_txn *txn,
-                   struct binder_io *msg,
-                   struct binder_io *reply)
-{
-    struct svcinfo *si;
-    uint16_t *s;
-    unsigned len;
-    void *ptr;
-    uint32_t strict_policy;
-    int allow_isolated;
-
-//    ALOGI("target=%p code=%d pid=%d uid=%d\n",
-//         txn->target, txn->code, txn->sender_pid, txn->sender_euid);
-
-    if (txn->target != svcmgr_handle)
-        return -1;
-
-    // Equivalent to Parcel::enforceInterface(), reading the RPC
-    // header with the strict mode policy mask and the interface name.
-    // Note that we ignore the strict_policy and don't propagate it
-    // further (since we do no outbound RPCs anyway).
-    strict_policy = bio_get_uint32(msg);
-    s = bio_get_string16(msg, &len);
-    if ((len != (sizeof(svcmgr_id) / 2)) ||
-        memcmp(svcmgr_id, s, sizeof(svcmgr_id))) {
-        fprintf(stderr,"invalid id %s\n", str8(s));
-        return -1;
-    }
-
-    switch(txn->code) {
-    case SVC_MGR_GET_SERVICE:
-    case SVC_MGR_CHECK_SERVICE:
-        s = bio_get_string16(msg, &len);
-        ptr = do_find_service(bs, s, len, txn->sender_euid);
-        if (!ptr)
-            break;
-        bio_put_ref(reply, ptr);
-        return 0;
-
-    case SVC_MGR_ADD_SERVICE:
-        s = bio_get_string16(msg, &len);
-        ptr = bio_get_ref(msg);
-        allow_isolated = bio_get_uint32(msg) ? 1 : 0;
-        if (do_add_service(bs, s, len, ptr, txn->sender_euid, allow_isolated))
-            return -1;
-        break;
-
-    case SVC_MGR_LIST_SERVICES: {
-        unsigned n = bio_get_uint32(msg);
-
-        si = svclist;
-        while ((n-- > 0) && si)
-            si = si->next;
-        if (si) {
-            bio_put_string16(reply, si->name);
-            return 0;
-        }
-        return -1;
-    }
-    default:
-        ALOGE("unknown code %d\n", txn->code);
-        return -1;
-    }
-
-    bio_put_uint32(reply, 0);
-    return 0;
-}
-
-int main(int argc, char **argv)
-{
-    struct binder_state *bs;
-    void *svcmgr = BINDER_SERVICE_MANAGER;
-
-    bs = binder_open(128*1024);
-
-    if (binder_become_context_manager(bs)) {
-        ALOGE("cannot become context manager (%s)\n", strerror(errno));
-        return -1;
-    }
-
-    svcmgr_handle = svcmgr;
-    binder_loop(bs, svcmgr_handler);
-    return 0;
-}
diff --git a/core/java/android/accounts/AccountManager.java b/core/java/android/accounts/AccountManager.java
index bcb35d5..6d9bb1d 100644
--- a/core/java/android/accounts/AccountManager.java
+++ b/core/java/android/accounts/AccountManager.java
@@ -1846,7 +1846,7 @@
      * Returns an intent to an {@link Activity} that prompts the user to choose from a list of
      * accounts.
      * The caller will then typically start the activity by calling
-     * <code>startActivityWithResult(intent, ...);</code>.
+     * <code>startActivityForResult(intent, ...);</code>.
      * <p>
      * On success the activity returns a Bundle with the account name and type specified using
      * keys {@link #KEY_ACCOUNT_NAME} and {@link #KEY_ACCOUNT_TYPE}.
diff --git a/core/java/android/bluetooth/BluetoothTetheringDataTracker.java b/core/java/android/bluetooth/BluetoothTetheringDataTracker.java
index 063e5a8..3ba4f26 100644
--- a/core/java/android/bluetooth/BluetoothTetheringDataTracker.java
+++ b/core/java/android/bluetooth/BluetoothTetheringDataTracker.java
@@ -21,7 +21,6 @@
 import android.os.INetworkManagementService;
 import android.content.Context;
 import android.net.ConnectivityManager;
-import android.net.DhcpInfoInternal;
 import android.net.LinkCapabilities;
 import android.net.LinkProperties;
 import android.net.NetworkInfo;
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
index 9e406d4..b20cf88 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -169,6 +169,25 @@
     /** @hide */
     public static final int SYNC_ERROR_INTERNAL = 8;
 
+    private static final String[] SYNC_ERROR_NAMES = new String[] {
+          "already-in-progress",
+          "authentication-error",
+          "io-error",
+          "parse-error",
+          "conflict",
+          "too-many-deletions",
+          "too-many-retries",
+          "internal-error",
+    };
+
+    /** @hide */
+    static String syncErrorToString(int error) {
+        if (error < 1 || error > SYNC_ERROR_NAMES.length) {
+            return String.valueOf(error);
+        }
+        return SYNC_ERROR_NAMES[error - 1];
+    }
+
     public static final int SYNC_OBSERVER_TYPE_SETTINGS = 1<<0;
     public static final int SYNC_OBSERVER_TYPE_PENDING = 1<<1;
     public static final int SYNC_OBSERVER_TYPE_ACTIVE = 1<<2;
diff --git a/core/java/android/content/ContentService.java b/core/java/android/content/ContentService.java
index 4512e82..8bac888 100644
--- a/core/java/android/content/ContentService.java
+++ b/core/java/android/content/ContentService.java
@@ -226,6 +226,7 @@
             }
         }
 
+        final int uid = Binder.getCallingUid();
         // This makes it so that future permission checks will be in the context of this
         // process rather than the caller's process. We will restore this before returning.
         long identityToken = clearCallingIdentity();
@@ -264,7 +265,7 @@
             if (syncToNetwork) {
                 SyncManager syncManager = getSyncManager();
                 if (syncManager != null) {
-                    syncManager.scheduleLocalSync(null /* all accounts */, callingUserHandle,
+                    syncManager.scheduleLocalSync(null /* all accounts */, callingUserHandle, uid,
                             uri.getAuthority());
                 }
             }
@@ -300,6 +301,7 @@
     public void requestSync(Account account, String authority, Bundle extras) {
         ContentResolver.validateSyncExtrasBundle(extras);
         int userId = UserHandle.getCallingUserId();
+        int uId = Binder.getCallingUid();
 
         // This makes it so that future permission checks will be in the context of this
         // process rather than the caller's process. We will restore this before returning.
@@ -307,7 +309,7 @@
         try {
             SyncManager syncManager = getSyncManager();
             if (syncManager != null) {
-                syncManager.scheduleSync(account, userId, authority, extras, 0 /* no delay */,
+                syncManager.scheduleSync(account, userId, uId, authority, extras, 0 /* no delay */,
                         false /* onlyThoseWithUnkownSyncableState */);
             }
         } finally {
diff --git a/core/java/android/content/SyncManager.java b/core/java/android/content/SyncManager.java
index e4b4b97..e428968 100644
--- a/core/java/android/content/SyncManager.java
+++ b/core/java/android/content/SyncManager.java
@@ -65,6 +65,7 @@
 import com.google.android.collect.Sets;
 
 import java.io.FileDescriptor;
+import java.io.PrintStream;
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -201,7 +202,9 @@
     private BroadcastReceiver mBackgroundDataSettingChanged = new BroadcastReceiver() {
         public void onReceive(Context context, Intent intent) {
             if (getConnectivityManager().getBackgroundDataSetting()) {
-                scheduleSync(null /* account */, UserHandle.USER_ALL, null /* authority */,
+                scheduleSync(null /* account */, UserHandle.USER_ALL,
+                        SyncOperation.REASON_BACKGROUND_DATA_SETTINGS_CHANGED,
+                        null /* authority */,
                         new Bundle(), 0 /* delay */,
                         false /* onlyThoseWithUnknownSyncableState */);
             }
@@ -213,7 +216,8 @@
             updateRunningAccounts();
 
             // Kick off sync for everyone, since this was a radical account change
-            scheduleSync(null, UserHandle.USER_ALL, null, null, 0 /* no delay */, false);
+            scheduleSync(null, UserHandle.USER_ALL, SyncOperation.REASON_ACCOUNTS_UPDATED, null,
+                    null, 0 /* no delay */, false);
         }
     };
 
@@ -351,14 +355,14 @@
         SyncStorageEngine.init(context);
         mSyncStorageEngine = SyncStorageEngine.getSingleton();
         mSyncStorageEngine.setOnSyncRequestListener(new OnSyncRequestListener() {
-            public void onSyncRequest(Account account, int userId, String authority,
+            public void onSyncRequest(Account account, int userId, int reason, String authority,
                     Bundle extras) {
-                scheduleSync(account, userId, authority, extras, 0, false);
+                scheduleSync(account, userId, reason, authority, extras, 0, false);
             }
         });
 
         mSyncAdapters = new SyncAdaptersCache(mContext);
-        mSyncQueue = new SyncQueue(mSyncStorageEngine, mSyncAdapters);
+        mSyncQueue = new SyncQueue(mContext.getPackageManager(), mSyncStorageEngine, mSyncAdapters);
 
         HandlerThread syncThread = new HandlerThread("SyncHandlerThread",
                 Process.THREAD_PRIORITY_BACKGROUND);
@@ -369,7 +373,9 @@
             @Override
             public void onServiceChanged(SyncAdapterType type, int userId, boolean removed) {
                 if (!removed) {
-                    scheduleSync(null, UserHandle.USER_ALL, type.authority, null, 0 /* no delay */,
+                    scheduleSync(null, UserHandle.USER_ALL,
+                            SyncOperation.REASON_SERVICE_CHANGED,
+                            type.authority, null, 0 /* no delay */,
                             false /* onlyThoseWithUnkownSyncableState */);
                 }
             }
@@ -498,6 +504,17 @@
      * @param requestedAccount the account to sync, may be null to signify all accounts
      * @param userId the id of the user whose accounts are to be synced. If userId is USER_ALL,
      *          then all users' accounts are considered.
+     * @param reason for sync request. If this is a positive integer, it is the Linux uid
+     * assigned to the process that requested the sync. If it's negative, the sync was requested by
+     * the SyncManager itself and could be one of the following:
+     *      {@link SyncOperation#REASON_BACKGROUND_DATA_SETTINGS_CHANGED}
+     *      {@link SyncOperation#REASON_ACCOUNTS_UPDATED}
+     *      {@link SyncOperation#REASON_SERVICE_CHANGED}
+     *      {@link SyncOperation#REASON_PERIODIC}
+     *      {@link SyncOperation#REASON_IS_SYNCABLE}
+     *      {@link SyncOperation#REASON_SYNC_AUTO}
+     *      {@link SyncOperation#REASON_MASTER_SYNC_AUTO}
+     *      {@link SyncOperation#REASON_USER_START}
      * @param requestedAuthority the authority to sync, may be null to indicate all authorities
      * @param extras a Map of SyncAdapter-specific information to control
      *          syncs of a specific provider. Can be null. Is ignored
@@ -505,8 +522,9 @@
      * @param delay how many milliseconds in the future to wait before performing this
      * @param onlyThoseWithUnkownSyncableState
      */
-    public void scheduleSync(Account requestedAccount, int userId, String requestedAuthority,
-            Bundle extras, long delay, boolean onlyThoseWithUnkownSyncableState) {
+    public void scheduleSync(Account requestedAccount, int userId, int reason,
+            String requestedAuthority, Bundle extras, long delay,
+            boolean onlyThoseWithUnkownSyncableState) {
         boolean isLoggable = Log.isLoggable(TAG, Log.VERBOSE);
 
         final boolean backgroundDataUsageAllowed = !mBootCompleted ||
@@ -632,8 +650,9 @@
                                 + ", extras " + newExtras);
                     }
                     scheduleSyncOperation(
-                            new SyncOperation(account.account, account.userId, source, authority,
-                                    newExtras, 0, backoffTime, delayUntil, allowParallelSyncs));
+                            new SyncOperation(account.account, account.userId, reason, source,
+                                    authority, newExtras, 0, backoffTime, delayUntil,
+                                    allowParallelSyncs));
                 }
                 if (!onlyThoseWithUnkownSyncableState) {
                     if (isLoggable) {
@@ -645,17 +664,18 @@
                                 + ", extras " + extras);
                     }
                     scheduleSyncOperation(
-                            new SyncOperation(account.account, account.userId, source, authority,
-                                    extras, delay, backoffTime, delayUntil, allowParallelSyncs));
+                            new SyncOperation(account.account, account.userId, reason, source,
+                                    authority, extras, delay, backoffTime, delayUntil,
+                                    allowParallelSyncs));
                 }
             }
         }
     }
 
-    public void scheduleLocalSync(Account account, int userId, String authority) {
+    public void scheduleLocalSync(Account account, int userId, int reason, String authority) {
         final Bundle extras = new Bundle();
         extras.putBoolean(ContentResolver.SYNC_EXTRAS_UPLOAD, true);
-        scheduleSync(account, userId, authority, extras, LOCAL_SYNC_DELAY,
+        scheduleSync(account, userId, reason, authority, extras, LOCAL_SYNC_DELAY,
                 false /* onlyThoseWithUnkownSyncableState */);
     }
 
@@ -881,6 +901,7 @@
                         + "sync in progress: " + operation);
             }
             scheduleSyncOperation(new SyncOperation(operation.account, operation.userId,
+                    operation.reason,
                     operation.syncSource,
                     operation.authority, operation.extras,
                     DELAY_RETRY_SYNC_IN_PROGRESS_IN_SECONDS * 1000,
@@ -912,8 +933,8 @@
         // Schedule sync for any accounts under started user
         final Account[] accounts = AccountManagerService.getSingleton().getAccounts(userId);
         for (Account account : accounts) {
-            scheduleSync(account, userId, null, null, 0 /* no delay */,
-                    true /* onlyThoseWithUnknownSyncableState */);
+            scheduleSync(account, userId, SyncOperation.REASON_USER_START, null, null,
+                    0 /* no delay */, true /* onlyThoseWithUnknownSyncableState */);
         }
 
         sendCheckAlarmsMessage();
@@ -1127,12 +1148,13 @@
 
         pw.println();
         pw.println("Active Syncs: " + mActiveSyncContexts.size());
+        final PackageManager pm = mContext.getPackageManager();
         for (SyncManager.ActiveSyncContext activeSyncContext : mActiveSyncContexts) {
             final long durationInSeconds = (now - activeSyncContext.mStartTime) / 1000;
             pw.print("  ");
             pw.print(DateUtils.formatElapsedTime(durationInSeconds));
             pw.print(" - ");
-            pw.print(activeSyncContext.mSyncOperation.dump(false));
+            pw.print(activeSyncContext.mSyncOperation.dump(pm, false));
             pw.println();
         }
 
@@ -1147,78 +1169,96 @@
         pw.println();
         pw.println("Sync Status");
         for (AccountAndUser account : accounts) {
-            pw.print("  Account "); pw.print(account.account.name);
-                    pw.print(" u"); pw.print(account.userId);
-                    pw.print(" "); pw.print(account.account.type);
-                    pw.println(":");
-            for (RegisteredServicesCache.ServiceInfo<SyncAdapterType> syncAdapterType :
-                    mSyncAdapters.getAllServices(account.userId)) {
+            pw.printf("Account %s u%d %s\n",
+                    account.account.name, account.userId, account.account.type);
+
+            pw.println("=======================================================================");
+            final PrintTable table = new PrintTable(13);
+            table.set(0, 0,
+                    "Authority", // 0
+                    "Syncable",  // 1
+                    "Enabled",   // 2
+                    "Delay",     // 3
+                    "Loc",       // 4
+                    "Poll",      // 5
+                    "Per",       // 6
+                    "Serv",      // 7
+                    "User",      // 8
+                    "Tot",       // 9
+                    "Time",      // 10
+                    "Last Sync", // 11
+                    "Periodic"   // 12
+            );
+
+            final List<RegisteredServicesCache.ServiceInfo<SyncAdapterType>> sorted =
+                    Lists.newArrayList();
+            sorted.addAll(mSyncAdapters.getAllServices(account.userId));
+            Collections.sort(sorted,
+                    new Comparator<RegisteredServicesCache.ServiceInfo<SyncAdapterType>>() {
+                @Override
+                public int compare(RegisteredServicesCache.ServiceInfo<SyncAdapterType> lhs,
+                        RegisteredServicesCache.ServiceInfo<SyncAdapterType> rhs) {
+                    return lhs.type.authority.compareTo(rhs.type.authority);
+                }
+            });
+            for (RegisteredServicesCache.ServiceInfo<SyncAdapterType> syncAdapterType : sorted) {
                 if (!syncAdapterType.type.accountType.equals(account.account.type)) {
                     continue;
                 }
-
+                int row = table.getNumRows();
                 SyncStorageEngine.AuthorityInfo settings =
                         mSyncStorageEngine.getOrCreateAuthority(
                                 account.account, account.userId, syncAdapterType.type.authority);
                 SyncStatusInfo status = mSyncStorageEngine.getOrCreateSyncStatus(settings);
-                pw.print("    "); pw.print(settings.authority);
-                pw.println(":");
-                pw.print("      settings:");
-                pw.print(" " + (settings.syncable > 0
-                        ? "syncable"
-                        : (settings.syncable == 0 ? "not syncable" : "not initialized")));
-                pw.print(", " + (settings.enabled ? "enabled" : "disabled"));
+
+                String authority = settings.authority;
+                if (authority.length() > 50) {
+                    authority = authority.substring(authority.length() - 50);
+                }
+                table.set(row, 0, authority, settings.syncable, settings.enabled);
+                table.set(row, 4,
+                        status.numSourceLocal,
+                        status.numSourcePoll,
+                        status.numSourcePeriodic,
+                        status.numSourceServer,
+                        status.numSourceUser,
+                        status.numSyncs,
+                        DateUtils.formatElapsedTime(status.totalElapsedTime / 1000));
+
+
+                for (int i = 0; i < settings.periodicSyncs.size(); i++) {
+                    final Pair<Bundle, Long> pair = settings.periodicSyncs.get(0);
+                    final String period = String.valueOf(pair.second);
+                    final String extras = pair.first.size() > 0 ? pair.first.toString() : "";
+                    final String next = formatTime(status.getPeriodicSyncTime(0)
+                            + pair.second * 1000);
+                    table.set(row + i * 2, 12, period + extras);
+                    table.set(row + i * 2 + 1, 12, next);
+                }
+
+                int row1 = row;
                 if (settings.delayUntil > now) {
-                    pw.print(", delay for "
-                            + ((settings.delayUntil - now) / 1000) + " sec");
+                    table.set(row1++, 12, "D: " + (settings.delayUntil - now) / 1000);
+                    if (settings.backoffTime > now) {
+                        table.set(row1++, 12, "B: " + (settings.backoffTime - now) / 1000);
+                        table.set(row1++, 12, settings.backoffDelay / 1000);
+                    }
                 }
-                if (settings.backoffTime > now) {
-                    pw.print(", backoff for "
-                            + ((settings.backoffTime - now) / 1000) + " sec");
-                }
-                if (settings.backoffDelay > 0) {
-                    pw.print(", the backoff increment is " + settings.backoffDelay / 1000
-                                + " sec");
-                }
-                pw.println();
-                for (int periodicIndex = 0;
-                        periodicIndex < settings.periodicSyncs.size();
-                        periodicIndex++) {
-                    Pair<Bundle, Long> info = settings.periodicSyncs.get(periodicIndex);
-                    long lastPeriodicTime = status.getPeriodicSyncTime(periodicIndex);
-                    long nextPeriodicTime = lastPeriodicTime + info.second * 1000;
-                    pw.println("      periodic period=" + info.second
-                            + ", extras=" + info.first
-                            + ", next=" + formatTime(nextPeriodicTime));
-                }
-                pw.print("      count: local="); pw.print(status.numSourceLocal);
-                pw.print(" poll="); pw.print(status.numSourcePoll);
-                pw.print(" periodic="); pw.print(status.numSourcePeriodic);
-                pw.print(" server="); pw.print(status.numSourceServer);
-                pw.print(" user="); pw.print(status.numSourceUser);
-                pw.print(" total="); pw.print(status.numSyncs);
-                pw.println();
-                pw.print("      total duration: ");
-                pw.println(DateUtils.formatElapsedTime(status.totalElapsedTime/1000));
+
                 if (status.lastSuccessTime != 0) {
-                    pw.print("      SUCCESS: source=");
-                    pw.print(SyncStorageEngine.SOURCES[status.lastSuccessSource]);
-                    pw.print(" time=");
-                    pw.println(formatTime(status.lastSuccessTime));
+                    table.set(row1++, 11, SyncStorageEngine.SOURCES[status.lastSuccessSource]
+                            + " " + "SUCCESS");
+                    table.set(row1++, 11, formatTime(status.lastSuccessTime));
                 }
                 if (status.lastFailureTime != 0) {
-                    pw.print("      FAILURE: source=");
-                    pw.print(SyncStorageEngine.SOURCES[
-                            status.lastFailureSource]);
-                    pw.print(" initialTime=");
-                    pw.print(formatTime(status.initialFailureTime));
-                    pw.print(" lastTime=");
-                    pw.println(formatTime(status.lastFailureTime));
-                    int errCode = status.getLastFailureMesgAsInt(0);
-                    pw.print("      message: "); pw.println(
-                            getLastFailureMessage(errCode) + " (" + errCode + ")");
+                    table.set(row1++, 11, SyncStorageEngine.SOURCES[status.lastFailureSource]
+                            + " " + "FAILURE");
+                    table.set(row1++, 11, formatTime(status.lastFailureTime));
+                    //noinspection UnusedAssignment
+                    table.set(row1++, 11, status.lastFailureMesg);
                 }
             }
+            table.writeTo(pw);
         }
     }
 
@@ -1412,9 +1452,9 @@
 
             pw.println();
             pw.println("Recent Sync History");
-            final String format = "  %-" + maxAccount + "s  %s\n";
+            final String format = "  %-" + maxAccount + "s  %-" + maxAuthority + "s %s\n";
             final Map<String, Long> lastTimeMap = Maps.newHashMap();
-
+            final PackageManager pm = mContext.getPackageManager();
             for (int i = 0; i < N; i++) {
                 SyncStorageEngine.SyncHistoryItem item = items.get(i);
                 SyncStorageEngine.AuthorityInfo authority
@@ -1459,7 +1499,8 @@
                         SyncStorageEngine.SOURCES[item.source],
                         ((float) elapsedTime) / 1000,
                         diffString);
-                pw.printf(format, accountKey, authorityName);
+                pw.printf(format, accountKey, authorityName,
+                        SyncOperation.reasonToString(pm, item.reason));
 
                 if (item.event != SyncStorageEngine.EVENT_STOP
                         || item.upstreamActivity != 0
@@ -1474,6 +1515,37 @@
                     pw.printf("    mesg=%s\n", item.mesg);
                 }
             }
+            pw.println();
+            pw.println("Recent Sync History Extras");
+            for (int i = 0; i < N; i++) {
+                final SyncStorageEngine.SyncHistoryItem item = items.get(i);
+                final Bundle extras = item.extras;
+                if (extras == null || extras.size() == 0) {
+                    continue;
+                }
+                final SyncStorageEngine.AuthorityInfo authority
+                        = mSyncStorageEngine.getAuthority(item.authorityId);
+                final String authorityName;
+                final String accountKey;
+                if (authority != null) {
+                    authorityName = authority.authority;
+                    accountKey = authority.account.name + "/" + authority.account.type
+                            + " u" + authority.userId;
+                } else {
+                    authorityName = "Unknown";
+                    accountKey = "Unknown";
+                }
+                final Time time = new Time();
+                final long eventTime = item.eventTime;
+                time.set(eventTime);
+
+                pw.printf("  #%-3d: %s %8s ",
+                        i + 1,
+                        formatTime(eventTime),
+                        SyncStorageEngine.SOURCES[item.source]);
+
+                pw.printf(format, accountKey, authorityName, extras);
+            }
         }
     }
 
@@ -1888,6 +1960,7 @@
                         }
                         scheduleSyncOperation(
                                 new SyncOperation(info.account, info.userId,
+                                        SyncOperation.REASON_PERIODIC,
                                         SyncStorageEngine.SOURCE_PERIODIC,
                                         info.authority, extras, 0 /* delay */,
                                         backoff != null ? backoff.first : 0,
@@ -2289,7 +2362,8 @@
                     }
                     // reschedule the sync if so indicated by the syncResult
                     maybeRescheduleSync(syncResult, syncOperation);
-                    historyMessage = Integer.toString(syncResultToErrorNumber(syncResult));
+                    historyMessage = ContentResolver.syncErrorToString(
+                            syncResultToErrorNumber(syncResult));
                     // TODO: set these correctly when the SyncResult is extended to include it
                     downstreamActivity = 0;
                     upstreamActivity = 0;
@@ -2327,6 +2401,7 @@
 
             if (syncResult != null && syncResult.fullSyncRequested) {
                 scheduleSyncOperation(new SyncOperation(syncOperation.account, syncOperation.userId,
+                        syncOperation.reason,
                         syncOperation.syncSource, syncOperation.authority, new Bundle(), 0,
                         syncOperation.backoff, syncOperation.delayUntil,
                         syncOperation.allowParallelSyncs));
@@ -2606,8 +2681,10 @@
                                 syncOperation.account.name.hashCode());
 
             return mSyncStorageEngine.insertStartSyncEvent(
-                    syncOperation.account, syncOperation.userId, syncOperation.authority,
-                    now, source, syncOperation.isInitialization());
+                    syncOperation.account, syncOperation.userId, syncOperation.reason,
+                    syncOperation.authority,
+                    now, source, syncOperation.isInitialization(), syncOperation.extras
+            );
         }
 
         public void stopSyncEvent(long rowId, SyncOperation syncOperation, String resultMessage,
@@ -2629,4 +2706,66 @@
         }
         return false;
     }
+
+    static class PrintTable {
+        private ArrayList<Object[]> mTable = Lists.newArrayList();
+        private final int mCols;
+
+        PrintTable(int cols) {
+            mCols = cols;
+        }
+
+        void set(int row, int col, Object... values) {
+            if (col + values.length > mCols) {
+                throw new IndexOutOfBoundsException("Table only has " + mCols +
+                        " columns. can't set " + values.length + " at column " + col);
+            }
+            for (int i = mTable.size(); i <= row; i++) {
+                final Object[] list = new Object[mCols];
+                mTable.add(list);
+                for (int j = 0; j < mCols; j++) {
+                    list[j] = "";
+                }
+            }
+            System.arraycopy(values, 0, mTable.get(row), col, values.length);
+        }
+
+        void writeTo(PrintWriter out) {
+            final String[] formats = new String[mCols];
+            int totalLength = 0;
+            for (int col = 0; col < mCols; ++col) {
+                int maxLength = 0;
+                for (Object[] row : mTable) {
+                    final int length = row[col].toString().length();
+                    if (length > maxLength) {
+                        maxLength = length;
+                    }
+                }
+                totalLength += maxLength;
+                formats[col] = String.format("%%-%ds", maxLength);
+            }
+            printRow(out, formats, mTable.get(0));
+            totalLength += (mCols - 1) * 2;
+            for (int i = 0; i < totalLength; ++i) {
+                out.print("-");
+            }
+            out.println();
+            for (int i = 1, mTableSize = mTable.size(); i < mTableSize; i++) {
+                Object[] row = mTable.get(i);
+                printRow(out, formats, row);
+            }
+        }
+
+        private void printRow(PrintWriter out, String[] formats, Object[] row) {
+            for (int j = 0, rowLength = row.length; j < rowLength; j++) {
+                out.printf(String.format(formats[j], row[j].toString()));
+                out.print("  ");
+            }
+            out.println();
+        }
+
+        public int getNumRows() {
+            return mTable.size();
+        }
+    }
 }
diff --git a/core/java/android/content/SyncOperation.java b/core/java/android/content/SyncOperation.java
index 6611fcd..a4c2cff 100644
--- a/core/java/android/content/SyncOperation.java
+++ b/core/java/android/content/SyncOperation.java
@@ -17,6 +17,7 @@
 package android.content;
 
 import android.accounts.Account;
+import android.content.pm.PackageManager;
 import android.os.Bundle;
 import android.os.SystemClock;
 
@@ -25,8 +26,29 @@
  * @hide
  */
 public class SyncOperation implements Comparable {
+    public static final int REASON_BACKGROUND_DATA_SETTINGS_CHANGED = -1;
+    public static final int REASON_ACCOUNTS_UPDATED = -2;
+    public static final int REASON_SERVICE_CHANGED = -3;
+    public static final int REASON_PERIODIC = -4;
+    public static final int REASON_IS_SYNCABLE = -5;
+    public static final int REASON_SYNC_AUTO = -6;
+    public static final int REASON_MASTER_SYNC_AUTO = -7;
+    public static final int REASON_USER_START = -8;
+
+    private static String[] REASON_NAMES = new String[] {
+            "DataSettingsChanged",
+            "AccountsUpdated",
+            "ServiceChanged",
+            "Periodic",
+            "IsSyncable",
+            "AutoSync",
+            "MasterSyncAuto",
+            "UserStart",
+    };
+
     public final Account account;
     public final int userId;
+    public final int reason;
     public int syncSource;
     public String authority;
     public final boolean allowParallelSyncs;
@@ -39,10 +61,12 @@
     public long delayUntil;
     public long effectiveRunTime;
 
-    public SyncOperation(Account account, int userId, int source, String authority, Bundle extras,
-            long delayInMs, long backoff, long delayUntil, boolean allowParallelSyncs) {
+    public SyncOperation(Account account, int userId, int reason, int source, String authority,
+            Bundle extras, long delayInMs, long backoff, long delayUntil,
+            boolean allowParallelSyncs) {
         this.account = account;
         this.userId = userId;
+        this.reason = reason;
         this.syncSource = source;
         this.authority = authority;
         this.allowParallelSyncs = allowParallelSyncs;
@@ -78,6 +102,7 @@
     SyncOperation(SyncOperation other) {
         this.account = other.account;
         this.userId = other.userId;
+        this.reason = other.reason;
         this.syncSource = other.syncSource;
         this.authority = other.authority;
         this.extras = new Bundle(other.extras);
@@ -91,10 +116,10 @@
     }
 
     public String toString() {
-        return dump(true);
+        return dump(null, true);
     }
 
-    public String dump(boolean useOneLine) {
+    public String dump(PackageManager pm, boolean useOneLine) {
         StringBuilder sb = new StringBuilder()
                 .append(account.name)
                 .append(" u")
@@ -110,6 +135,8 @@
         if (expedited) {
             sb.append(", EXPEDITED");
         }
+        sb.append(", reason: ");
+        sb.append(reasonToString(pm, reason));
         if (!useOneLine && !extras.keySet().isEmpty()) {
             sb.append("\n    ");
             extrasToStringBuilder(extras, sb);
@@ -117,6 +144,31 @@
         return sb.toString();
     }
 
+    public static String reasonToString(PackageManager pm, int reason) {
+        if (reason >= 0) {
+            if (pm != null) {
+                final String[] packages = pm.getPackagesForUid(reason);
+                if (packages != null && packages.length == 1) {
+                    return packages[0];
+                }
+                final String name = pm.getNameForUid(reason);
+                if (name != null) {
+                    return name;
+                }
+                return String.valueOf(reason);
+            } else {
+                return String.valueOf(reason);
+            }
+        } else {
+            final int index = -reason - 1;
+            if (index >= REASON_NAMES.length) {
+                return String.valueOf(reason);
+            } else {
+                return REASON_NAMES[index];
+            }
+        }
+    }
+
     public boolean isInitialization() {
         return extras.getBoolean(ContentResolver.SYNC_EXTRAS_INITIALIZE, false);
     }
diff --git a/core/java/android/content/SyncQueue.java b/core/java/android/content/SyncQueue.java
index c9a325e..c09703c 100644
--- a/core/java/android/content/SyncQueue.java
+++ b/core/java/android/content/SyncQueue.java
@@ -17,6 +17,8 @@
 package android.content;
 
 import android.accounts.Account;
+import android.content.pm.PackageManager;
+import android.content.pm.RegisteredServicesCache;
 import android.content.pm.RegisteredServicesCache.ServiceInfo;
 import android.os.SystemClock;
 import android.os.UserHandle;
@@ -40,15 +42,17 @@
  */
 public class SyncQueue {
     private static final String TAG = "SyncManager";
-
     private final SyncStorageEngine mSyncStorageEngine;
     private final SyncAdaptersCache mSyncAdapters;
+    private final PackageManager mPackageManager;
 
     // A Map of SyncOperations operationKey -> SyncOperation that is designed for
     // quick lookup of an enqueued SyncOperation.
     private final HashMap<String, SyncOperation> mOperationsMap = Maps.newHashMap();
 
-    public SyncQueue(SyncStorageEngine syncStorageEngine, final SyncAdaptersCache syncAdapters) {
+    public SyncQueue(PackageManager packageManager, SyncStorageEngine syncStorageEngine,
+            final SyncAdaptersCache syncAdapters) {
+        mPackageManager = packageManager;
         mSyncStorageEngine = syncStorageEngine;
         mSyncAdapters = syncAdapters;
     }
@@ -67,8 +71,8 @@
                 continue;
             }
             SyncOperation syncOperation = new SyncOperation(
-                    op.account, op.userId, op.syncSource, op.authority, op.extras, 0 /* delay */,
-                    backoff != null ? backoff.first : 0,
+                    op.account, op.userId, op.reason, op.syncSource, op.authority, op.extras,
+                    0 /* delay */, backoff != null ? backoff.first : 0,
                     mSyncStorageEngine.getDelayUntilTime(op.account, op.userId, op.authority),
                     syncAdapterInfo.type.allowParallelSyncs());
             syncOperation.expedited = op.expedited;
@@ -112,7 +116,7 @@
         operation.pendingOperation = pop;
         if (operation.pendingOperation == null) {
             pop = new SyncStorageEngine.PendingOperation(
-                    operation.account, operation.userId, operation.syncSource,
+                    operation.account, operation.userId, operation.reason, operation.syncSource,
                     operation.authority, operation.extras, operation.expedited);
             pop = mSyncStorageEngine.insertIntoPending(pop);
             if (pop == null) {
@@ -214,7 +218,7 @@
                 sb.append(DateUtils.formatElapsedTime((operation.effectiveRunTime - now) / 1000));
             }
             sb.append(" - ");
-            sb.append(operation.dump(false)).append("\n");
+            sb.append(operation.dump(mPackageManager, false)).append("\n");
         }
     }
 }
diff --git a/core/java/android/content/SyncStorageEngine.java b/core/java/android/content/SyncStorageEngine.java
index bdc5a3f..c490bd5 100644
--- a/core/java/android/content/SyncStorageEngine.java
+++ b/core/java/android/content/SyncStorageEngine.java
@@ -26,7 +26,6 @@
 
 import android.accounts.Account;
 import android.accounts.AccountAndUser;
-import android.content.res.Resources;
 import android.database.Cursor;
 import android.database.sqlite.SQLiteDatabase;
 import android.database.sqlite.SQLiteException;
@@ -146,6 +145,7 @@
     public static class PendingOperation {
         final Account account;
         final int userId;
+        final int reason;
         final int syncSource;
         final String authority;
         final Bundle extras;        // note: read-only.
@@ -154,11 +154,12 @@
         int authorityId;
         byte[] flatExtras;
 
-        PendingOperation(Account account, int userId, int source,
+        PendingOperation(Account account, int userId, int reason,int source,
                 String authority, Bundle extras, boolean expedited) {
             this.account = account;
             this.userId = userId;
             this.syncSource = source;
+            this.reason = reason;
             this.authority = authority;
             this.extras = extras != null ? new Bundle(extras) : extras;
             this.expedited = expedited;
@@ -168,6 +169,7 @@
         PendingOperation(PendingOperation other) {
             this.account = other.account;
             this.userId = other.userId;
+            this.reason = other.reason;
             this.syncSource = other.syncSource;
             this.authority = other.authority;
             this.extras = other.extras;
@@ -246,6 +248,8 @@
         long downstreamActivity;
         String mesg;
         boolean initialization;
+        Bundle extras;
+        int reason;
     }
 
     public static class DayStats {
@@ -265,10 +269,12 @@
          * Called when a sync is needed on an account(s) due to some change in state.
          * @param account
          * @param userId
+         * @param reason
          * @param authority
          * @param extras
          */
-        public void onSyncRequest(Account account, int userId, String authority, Bundle extras);
+        public void onSyncRequest(Account account, int userId, int reason, String authority,
+                Bundle extras);
     }
 
     // Primary list of all syncable authorities.  Also our global lock.
@@ -498,7 +504,8 @@
         }
 
         if (sync) {
-            requestSync(account, userId, providerName, new Bundle());
+            requestSync(account, userId, SyncOperation.REASON_SYNC_AUTO, providerName,
+                    new Bundle());
         }
         reportChange(ContentResolver.SYNC_OBSERVER_TYPE_SETTINGS);
     }
@@ -546,7 +553,8 @@
         }
 
         if (syncable > 0) {
-            requestSync(account, userId, providerName, new Bundle());
+            requestSync(account, userId, SyncOperation.REASON_IS_SYNCABLE,  providerName,
+                    new Bundle());
         }
         reportChange(ContentResolver.SYNC_OBSERVER_TYPE_SETTINGS);
     }
@@ -779,7 +787,8 @@
             writeAccountInfoLocked();
         }
         if (flag) {
-            requestSync(null, userId, null, new Bundle());
+            requestSync(null, userId, SyncOperation.REASON_MASTER_SYNC_AUTO, null,
+                    new Bundle());
         }
         reportChange(ContentResolver.SYNC_OBSERVER_TYPE_SETTINGS);
         mContext.sendBroadcast(SYNC_CONNECTION_SETTING_CHANGED_INTENT);
@@ -1042,8 +1051,8 @@
     /**
      * Note that sync has started for the given account and authority.
      */
-    public long insertStartSyncEvent(Account accountName, int userId, String authorityName,
-                                     long now, int source, boolean initialization) {
+    public long insertStartSyncEvent(Account accountName, int userId, int reason,
+            String authorityName, long now, int source, boolean initialization, Bundle extras) {
         long id;
         synchronized (mAuthorities) {
             if (Log.isLoggable(TAG, Log.VERBOSE)) {
@@ -1062,6 +1071,8 @@
             if (mNextHistoryId < 0) mNextHistoryId = 0;
             item.eventTime = now;
             item.source = source;
+            item.reason = reason;
+            item.extras = extras;
             item.event = EVENT_START;
             mSyncHistory.add(0, item);
             while (mSyncHistory.size() > MAX_HISTORY) {
@@ -2037,7 +2048,7 @@
         }
     }
 
-    public static final int PENDING_OPERATION_VERSION = 2;
+    public static final int PENDING_OPERATION_VERSION = 3;
 
     /**
      * Read all pending operations back in to the initial engine state.
@@ -2066,6 +2077,7 @@
                 } else {
                     expedited = false;
                 }
+                int reason = in.readInt();
                 AuthorityInfo authority = mAuthorities.get(authorityId);
                 if (authority != null) {
                     Bundle extras;
@@ -2077,13 +2089,14 @@
                         extras = new Bundle();
                     }
                     PendingOperation op = new PendingOperation(
-                            authority.account, authority.userId, syncSource,
+                            authority.account, authority.userId, reason, syncSource,
                             authority.authority, extras, expedited);
                     op.authorityId = authorityId;
                     op.flatExtras = flatExtras;
                     if (DEBUG_FILE) Log.v(TAG, "Adding pending op: account=" + op.account
                             + " auth=" + op.authority
                             + " src=" + op.syncSource
+                            + " reason=" + op.reason
                             + " expedited=" + op.expedited
                             + " extras=" + op.extras);
                     mPendingOperations.add(op);
@@ -2103,6 +2116,7 @@
         }
         out.writeByteArray(op.flatExtras);
         out.writeInt(op.expedited ? 1 : 0);
+        out.writeInt(op.reason);
     }
 
     /**
@@ -2197,14 +2211,15 @@
         return bundle;
     }
 
-    private void requestSync(Account account, int userId, String authority, Bundle extras) {
+    private void requestSync(Account account, int userId, int reason, String authority,
+            Bundle extras) {
         // If this is happening in the system process, then call the syncrequest listener
         // to make a request back to the SyncManager directly.
         // If this is probably a test instance, then call back through the ContentResolver
         // which will know which userId to apply based on the Binder id.
         if (android.os.Process.myUid() == android.os.Process.SYSTEM_UID
                 && mSyncRequestListener != null) {
-            mSyncRequestListener.onSyncRequest(account, userId, authority, extras);
+            mSyncRequestListener.onSyncRequest(account, userId, reason, authority, extras);
         } else {
             ContentResolver.requestSync(account, authority, extras);
         }
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index 6f1cc94..99624cc 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -1955,7 +1955,7 @@
         ic.sendKeyEvent(new KeyEvent(eventTime, eventTime,
                 KeyEvent.ACTION_DOWN, keyEventCode, 0, 0, KeyCharacterMap.VIRTUAL_KEYBOARD, 0,
                 KeyEvent.FLAG_SOFT_KEYBOARD|KeyEvent.FLAG_KEEP_TOUCH_MODE));
-        ic.sendKeyEvent(new KeyEvent(SystemClock.uptimeMillis(), eventTime,
+        ic.sendKeyEvent(new KeyEvent(eventTime, SystemClock.uptimeMillis(),
                 KeyEvent.ACTION_UP, keyEventCode, 0, 0, KeyCharacterMap.VIRTUAL_KEYBOARD, 0,
                 KeyEvent.FLAG_SOFT_KEYBOARD|KeyEvent.FLAG_KEEP_TOUCH_MODE));
     }
diff --git a/core/java/android/net/DhcpInfo.java b/core/java/android/net/DhcpInfo.java
index e2660e4..2b359eb 100644
--- a/core/java/android/net/DhcpInfo.java
+++ b/core/java/android/net/DhcpInfo.java
@@ -22,16 +22,17 @@
 
 /**
  * A simple object for retrieving the results of a DHCP request.
+ * @deprecated - use LinkProperties - To be removed 11/2013
+ * STOPSHIP - make sure we expose LinkProperties through ConnectivityManager
  */
 public class DhcpInfo implements Parcelable {
     public int ipAddress;
     public int gateway;
     public int netmask;
-
     public int dns1;
     public int dns2;
-
     public int serverAddress;
+
     public int leaseDuration;
 
     public DhcpInfo() {
diff --git a/core/java/android/net/DhcpInfoInternal.java b/core/java/android/net/DhcpInfoInternal.java
deleted file mode 100644
index f3508c1..0000000
--- a/core/java/android/net/DhcpInfoInternal.java
+++ /dev/null
@@ -1,166 +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.
- */
-
-package android.net;
-
-import android.text.TextUtils;
-import android.util.Log;
-
-import java.net.Inet4Address;
-import java.net.InetAddress;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-
-/**
- * A simple object for retrieving the results of a DHCP request.
- * Replaces (internally) the IPv4-only DhcpInfo class.
- * @hide
- */
-public class DhcpInfoInternal {
-    private final static String TAG = "DhcpInfoInternal";
-    public String ipAddress;
-    public int prefixLength;
-
-    public String dns1;
-    public String dns2;
-
-    public String serverAddress;
-    public int leaseDuration;
-
-    /**
-     * Vendor specific information (from RFC 2132).
-     */
-    public String vendorInfo;
-
-    private Collection<RouteInfo> mRoutes;
-
-    public DhcpInfoInternal() {
-        mRoutes = new ArrayList<RouteInfo>();
-    }
-
-    public void addRoute(RouteInfo routeInfo) {
-        mRoutes.add(routeInfo);
-    }
-
-    public Collection<RouteInfo> getRoutes() {
-        return Collections.unmodifiableCollection(mRoutes);
-    }
-
-    private int convertToInt(String addr) {
-        if (addr != null) {
-            try {
-                InetAddress inetAddress = NetworkUtils.numericToInetAddress(addr);
-                if (inetAddress instanceof Inet4Address) {
-                    return NetworkUtils.inetAddressToInt(inetAddress);
-                }
-            } catch (IllegalArgumentException e) {}
-        }
-        return 0;
-    }
-
-    public DhcpInfo makeDhcpInfo() {
-        DhcpInfo info = new DhcpInfo();
-        info.ipAddress = convertToInt(ipAddress);
-        for (RouteInfo route : mRoutes) {
-            if (route.isDefaultRoute()) {
-                info.gateway = convertToInt(route.getGateway().getHostAddress());
-                break;
-            }
-        }
-        try {
-            InetAddress inetAddress = NetworkUtils.numericToInetAddress(ipAddress);
-            info.netmask = NetworkUtils.prefixLengthToNetmaskInt(prefixLength);
-        } catch (IllegalArgumentException e) {}
-        info.dns1 = convertToInt(dns1);
-        info.dns2 = convertToInt(dns2);
-        info.serverAddress = convertToInt(serverAddress);
-        info.leaseDuration = leaseDuration;
-        return info;
-    }
-
-    public LinkAddress makeLinkAddress() {
-        if (TextUtils.isEmpty(ipAddress)) {
-            Log.e(TAG, "makeLinkAddress with empty ipAddress");
-            return null;
-        }
-        return new LinkAddress(NetworkUtils.numericToInetAddress(ipAddress), prefixLength);
-    }
-
-    public LinkProperties makeLinkProperties() {
-        LinkProperties p = new LinkProperties();
-        p.addLinkAddress(makeLinkAddress());
-        for (RouteInfo route : mRoutes) {
-            p.addRoute(route);
-        }
-        //if empty, connectivity configures default DNS
-        if (TextUtils.isEmpty(dns1) == false) {
-            p.addDns(NetworkUtils.numericToInetAddress(dns1));
-        } else {
-            Log.d(TAG, "makeLinkProperties with empty dns1!");
-        }
-        if (TextUtils.isEmpty(dns2) == false) {
-            p.addDns(NetworkUtils.numericToInetAddress(dns2));
-        } else {
-            Log.d(TAG, "makeLinkProperties with empty dns2!");
-        }
-        return p;
-    }
-
-    /* Updates the DHCP fields that need to be retained from
-     * original DHCP request if the DHCP renewal shows them as
-     * being empty
-     */
-    public void updateFromDhcpRequest(DhcpInfoInternal orig) {
-        if (orig == null) return;
-
-        if (TextUtils.isEmpty(dns1)) {
-            dns1 = orig.dns1;
-        }
-
-        if (TextUtils.isEmpty(dns2)) {
-            dns2 = orig.dns2;
-        }
-
-        if (mRoutes.size() == 0) {
-            for (RouteInfo route : orig.getRoutes()) {
-                addRoute(route);
-            }
-        }
-    }
-
-    /**
-     * Test if this DHCP lease includes vendor hint that network link is
-     * metered, and sensitive to heavy data transfers.
-     */
-    public boolean hasMeteredHint() {
-        if (vendorInfo != null) {
-            return vendorInfo.contains("ANDROID_METERED");
-        } else {
-            return false;
-        }
-    }
-
-    public String toString() {
-        String routeString = "";
-        for (RouteInfo route : mRoutes) routeString += route.toString() + " | ";
-        return "addr: " + ipAddress + "/" + prefixLength +
-                " mRoutes: " + routeString +
-                " dns: " + dns1 + "," + dns2 +
-                " dhcpServer: " + serverAddress +
-                " leaseDuration: " + leaseDuration;
-    }
-}
diff --git a/include/diskusage/dirsize.h b/core/java/android/net/DhcpResults.aidl
similarity index 65%
rename from include/diskusage/dirsize.h
rename to core/java/android/net/DhcpResults.aidl
index 34236c0..f4db3c3 100644
--- a/include/diskusage/dirsize.h
+++ b/core/java/android/net/DhcpResults.aidl
@@ -1,6 +1,5 @@
-/*
- *
- * Copyright (C) 2010 The Android Open Source Project
+/**
+ * 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.
@@ -15,16 +14,6 @@
  * limitations under the License.
  */
 
-#ifndef __LIBDISKUSAGE_DIRSIZE_H
-#define __LIBDISKUSAGE_DIRSIZE_H
+package android.net;
 
-#include <stdint.h>
-
-__BEGIN_DECLS
-
-int64_t stat_size(struct stat *s);
-int64_t calculate_dir_size(int dfd);
-
-__END_DECLS
-
-#endif /* __LIBDISKUSAGE_DIRSIZE_H */
+parcelable DhcpResults;
diff --git a/core/java/android/net/DhcpResults.java b/core/java/android/net/DhcpResults.java
new file mode 100644
index 0000000..2f300de
--- /dev/null
+++ b/core/java/android/net/DhcpResults.java
@@ -0,0 +1,244 @@
+/*
+ * 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.net;
+
+import android.os.Parcelable;
+import android.os.Parcel;
+import android.util.Log;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+
+/**
+ * A simple object for retrieving the results of a DHCP request.
+ * Optimized (attempted) for that jni interface
+ * TODO - remove when DhcpInfo is deprecated.  Move the remaining api to LinkProperties.
+ * @hide
+ */
+public class DhcpResults implements Parcelable {
+    private static final String TAG = "DhcpResults";
+
+    public final LinkProperties linkProperties;
+
+    public InetAddress serverAddress;
+
+    /**
+     * Vendor specific information (from RFC 2132).
+     */
+    public String vendorInfo;
+
+    public int leaseDuration;
+
+    public DhcpResults() {
+        linkProperties = new LinkProperties();
+    }
+
+    /** copy constructor */
+    public DhcpResults(DhcpResults source) {
+        if (source != null) {
+            linkProperties = new LinkProperties(source.linkProperties);
+            serverAddress = source.serverAddress;
+            leaseDuration = source.leaseDuration;
+            vendorInfo = source.vendorInfo;
+        } else {
+            linkProperties = new LinkProperties();
+        }
+    }
+
+    public DhcpResults(LinkProperties lp) {
+        linkProperties = new LinkProperties(lp);
+    }
+
+    /**
+     * Updates the DHCP fields that need to be retained from
+     * original DHCP request if the current renewal shows them
+     * being empty.
+     */
+    public void updateFromDhcpRequest(DhcpResults orig) {
+        if (orig == null || orig.linkProperties == null) return;
+        if (linkProperties.getRoutes().size() == 0) {
+            for (RouteInfo r : orig.linkProperties.getRoutes()) linkProperties.addRoute(r);
+        }
+        if (linkProperties.getDnses().size() == 0) {
+            for (InetAddress d : orig.linkProperties.getDnses()) linkProperties.addDns(d);
+        }
+    }
+
+    /**
+     * Test if this DHCP lease includes vendor hint that network link is
+     * metered, and sensitive to heavy data transfers.
+     */
+    public boolean hasMeteredHint() {
+        if (vendorInfo != null) {
+            return vendorInfo.contains("ANDROID_METERED");
+        } else {
+            return false;
+        }
+    }
+
+    public void clear() {
+        linkProperties.clear();
+        serverAddress = null;
+        vendorInfo = null;
+        leaseDuration = 0;
+    }
+
+    @Override
+    public String toString() {
+        StringBuffer str = new StringBuffer(linkProperties.toString());
+
+        str.append(" DHCP server ").append(serverAddress);
+        str.append(" Vendor info ").append(vendorInfo);
+        str.append(" lease ").append(leaseDuration).append(" seconds");
+
+        return str.toString();
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) return true;
+
+        if (!(obj instanceof DhcpResults)) return false;
+
+        DhcpResults target = (DhcpResults)obj;
+
+        if (linkProperties == null) {
+            if (target.linkProperties != null) return false;
+        } else if (!linkProperties.equals(target.linkProperties)) return false;
+        if (serverAddress == null) {
+            if (target.serverAddress != null) return false;
+        } else if (!serverAddress.equals(target.serverAddress)) return false;
+        if (vendorInfo == null) {
+            if (target.vendorInfo != null) return false;
+        } else if (!vendorInfo.equals(target.vendorInfo)) return false;
+        if (leaseDuration != target.leaseDuration) return false;
+
+        return true;
+    }
+
+    /** Implement the Parcelable interface */
+    public int describeContents() {
+        return 0;
+    }
+
+    /** Implement the Parcelable interface */
+    public void writeToParcel(Parcel dest, int flags) {
+        linkProperties.writeToParcel(dest, flags);
+
+        dest.writeInt(leaseDuration);
+
+        if (serverAddress != null) {
+            dest.writeByte((byte)1);
+            dest.writeByteArray(serverAddress.getAddress());
+        } else {
+            dest.writeByte((byte)0);
+        }
+
+        dest.writeString(vendorInfo);
+    }
+
+    /** Implement the Parcelable interface */
+    public static final Creator<DhcpResults> CREATOR =
+        new Creator<DhcpResults>() {
+            public DhcpResults createFromParcel(Parcel in) {
+                DhcpResults prop = new DhcpResults((LinkProperties)in.readParcelable(null));
+
+                prop.leaseDuration = in.readInt();
+
+                if (in.readByte() == 1) {
+                    try {
+                        prop.serverAddress = InetAddress.getByAddress(in.createByteArray());
+                    } catch (UnknownHostException e) {}
+                }
+
+                prop.vendorInfo = in.readString();
+
+                return prop;
+            }
+
+            public DhcpResults[] newArray(int size) {
+                return new DhcpResults[size];
+            }
+        };
+
+    // Utils for jni population - false on success
+    public void setInterfaceName(String interfaceName) {
+        linkProperties.setInterfaceName(interfaceName);
+    }
+
+    public boolean addLinkAddress(String addrString, int prefixLength) {
+        InetAddress addr;
+        try {
+            addr = NetworkUtils.numericToInetAddress(addrString);
+        } catch (IllegalArgumentException e) {
+            Log.e(TAG, "addLinkAddress failed with addrString " + addrString);
+            return true;
+        }
+
+        LinkAddress linkAddress = new LinkAddress(addr, prefixLength);
+        linkProperties.addLinkAddress(linkAddress);
+
+        RouteInfo routeInfo = new RouteInfo(linkAddress);
+        linkProperties.addRoute(routeInfo);
+        return false;
+    }
+
+    public boolean addGateway(String addrString) {
+        try {
+            linkProperties.addRoute(new RouteInfo(NetworkUtils.numericToInetAddress(addrString)));
+        } catch (IllegalArgumentException e) {
+            Log.e(TAG, "addGateway failed with addrString " + addrString);
+            return true;
+        }
+        return false;
+    }
+
+    public boolean addDns(String addrString) {
+        try {
+            linkProperties.addDns(NetworkUtils.numericToInetAddress(addrString));
+        } catch (IllegalArgumentException e) {
+            Log.e(TAG, "addDns failed with addrString " + addrString);
+            return true;
+        }
+        return false;
+    }
+
+    public boolean setServerAddress(String addrString) {
+        try {
+            serverAddress = NetworkUtils.numericToInetAddress(addrString);
+        } catch (IllegalArgumentException e) {
+            Log.e(TAG, "setServerAddress failed with addrString " + addrString);
+            return true;
+        }
+        return false;
+    }
+
+    public void setLeaseDuration(int duration) {
+        leaseDuration = duration;
+    }
+
+    public void setVendorInfo(String info) {
+        vendorInfo = info;
+    }
+
+    public void setDomains(String domains) {
+        linkProperties.setDomains(domains);
+    }
+}
diff --git a/core/java/android/net/DhcpStateMachine.java b/core/java/android/net/DhcpStateMachine.java
index 8dc900e..fd22b10 100644
--- a/core/java/android/net/DhcpStateMachine.java
+++ b/core/java/android/net/DhcpStateMachine.java
@@ -26,7 +26,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
-import android.net.DhcpInfoInternal;
+import android.net.DhcpResults;
 import android.net.NetworkUtils;
 import android.os.Message;
 import android.os.PowerManager;
@@ -64,7 +64,7 @@
     private static final String WAKELOCK_TAG = "DHCP";
 
     //Remember DHCP configuration from first request
-    private DhcpInfoInternal mDhcpInfo;
+    private DhcpResults mDhcpResults;
 
     private static final int DHCP_RENEW = 0;
     private static final String ACTION_DHCP_RENEW = "android.net.wifi.DHCP_RENEW";
@@ -348,23 +348,21 @@
 
     private boolean runDhcp(DhcpAction dhcpAction) {
         boolean success = false;
-        DhcpInfoInternal dhcpInfoInternal = new DhcpInfoInternal();
+        DhcpResults dhcpResults = new DhcpResults();
 
         if (dhcpAction == DhcpAction.START) {
             /* Stop any existing DHCP daemon before starting new */
             NetworkUtils.stopDhcp(mInterfaceName);
             if (DBG) Log.d(TAG, "DHCP request on " + mInterfaceName);
-            success = NetworkUtils.runDhcp(mInterfaceName, dhcpInfoInternal);
-            mDhcpInfo = dhcpInfoInternal;
+            success = NetworkUtils.runDhcp(mInterfaceName, dhcpResults);
         } else if (dhcpAction == DhcpAction.RENEW) {
             if (DBG) Log.d(TAG, "DHCP renewal on " + mInterfaceName);
-            success = NetworkUtils.runDhcpRenew(mInterfaceName, dhcpInfoInternal);
-            dhcpInfoInternal.updateFromDhcpRequest(mDhcpInfo);
+            success = NetworkUtils.runDhcpRenew(mInterfaceName, dhcpResults);
+            dhcpResults.updateFromDhcpRequest(mDhcpResults);
         }
-
         if (success) {
             if (DBG) Log.d(TAG, "DHCP succeeded on " + mInterfaceName);
-            long leaseDuration = dhcpInfoInternal.leaseDuration; //int to long conversion
+            long leaseDuration = dhcpResults.leaseDuration; //int to long conversion
 
             //Sanity check for renewal
             if (leaseDuration >= 0) {
@@ -384,7 +382,8 @@
                 //infinite lease time, no renewal needed
             }
 
-            mController.obtainMessage(CMD_POST_DHCP_ACTION, DHCP_SUCCESS, 0, dhcpInfoInternal)
+            mDhcpResults = dhcpResults;
+            mController.obtainMessage(CMD_POST_DHCP_ACTION, DHCP_SUCCESS, 0, dhcpResults)
                 .sendToTarget();
         } else {
             Log.e(TAG, "DHCP failed on " + mInterfaceName + ": " +
diff --git a/core/java/android/net/EthernetDataTracker.java b/core/java/android/net/EthernetDataTracker.java
index 3a06dc0..5b98b8f 100644
--- a/core/java/android/net/EthernetDataTracker.java
+++ b/core/java/android/net/EthernetDataTracker.java
@@ -170,13 +170,12 @@
     private void runDhcp() {
         Thread dhcpThread = new Thread(new Runnable() {
             public void run() {
-                DhcpInfoInternal dhcpInfoInternal = new DhcpInfoInternal();
-                if (!NetworkUtils.runDhcp(mIface, dhcpInfoInternal)) {
+                DhcpResults dhcpResults = new DhcpResults();
+                if (!NetworkUtils.runDhcp(mIface, dhcpResults)) {
                     Log.e(TAG, "DHCP request error:" + NetworkUtils.getDhcpError());
                     return;
                 }
-                mLinkProperties = dhcpInfoInternal.makeLinkProperties();
-                mLinkProperties.setInterfaceName(mIface);
+                mLinkProperties = dhcpResults.linkProperties;
 
                 mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, mHwAddr);
                 Message msg = mCsHandler.obtainMessage(EVENT_STATE_CHANGED, mNetworkInfo);
diff --git a/core/java/android/net/LinkProperties.java b/core/java/android/net/LinkProperties.java
index 75646fd..b9362da 100644
--- a/core/java/android/net/LinkProperties.java
+++ b/core/java/android/net/LinkProperties.java
@@ -51,9 +51,10 @@
  */
 public class LinkProperties implements Parcelable {
 
-    String mIfaceName;
+    private String mIfaceName;
     private Collection<LinkAddress> mLinkAddresses = new ArrayList<LinkAddress>();
     private Collection<InetAddress> mDnses = new ArrayList<InetAddress>();
+    private String mDomains;
     private Collection<RouteInfo> mRoutes = new ArrayList<RouteInfo>();
     private ProxyProperties mHttpProxy;
 
@@ -82,9 +83,10 @@
             mIfaceName = source.getInterfaceName();
             for (LinkAddress l : source.getLinkAddresses()) mLinkAddresses.add(l);
             for (InetAddress i : source.getDnses()) mDnses.add(i);
+            mDomains = source.getDomains();
             for (RouteInfo r : source.getRoutes()) mRoutes.add(r);
             mHttpProxy = (source.getHttpProxy() == null)  ?
-                null : new ProxyProperties(source.getHttpProxy());
+                    null : new ProxyProperties(source.getHttpProxy());
         }
     }
 
@@ -120,6 +122,14 @@
         return Collections.unmodifiableCollection(mDnses);
     }
 
+    public String getDomains() {
+        return mDomains;
+    }
+
+    public void setDomains(String domains) {
+        mDomains = domains;
+    }
+
     public void addRoute(RouteInfo route) {
         if (route != null) mRoutes.add(route);
     }
@@ -138,6 +148,7 @@
         mIfaceName = null;
         mLinkAddresses.clear();
         mDnses.clear();
+        mDomains = null;
         mRoutes.clear();
         mHttpProxy = null;
     }
@@ -162,12 +173,14 @@
         for (InetAddress addr : mDnses) dns += addr.getHostAddress() + ",";
         dns += "] ";
 
-        String routes = "Routes: [";
+        String domainName = "Domains: " + mDomains;
+
+        String routes = " Routes: [";
         for (RouteInfo route : mRoutes) routes += route.toString() + ",";
         routes += "] ";
         String proxy = (mHttpProxy == null ? "" : "HttpProxy: " + mHttpProxy.toString() + " ");
 
-        return ifaceName + linkAddresses + routes + dns + proxy;
+        return ifaceName + linkAddresses + routes + dns + domainName + proxy;
     }
 
     /**
@@ -181,7 +194,7 @@
     }
 
     /**
-     * Compares this {@code LinkProperties} interface name against the target
+     * Compares this {@code LinkProperties} interface addresses against the target
      *
      * @param target LinkProperties to compare.
      * @return {@code true} if both are identical, {@code false} otherwise.
@@ -201,6 +214,12 @@
      */
     public boolean isIdenticalDnses(LinkProperties target) {
         Collection<InetAddress> targetDnses = target.getDnses();
+        String targetDomains = target.getDomains();
+        if (mDomains == null) {
+            if (targetDomains != null) return false;
+        } else {
+            if (mDomains.equals(targetDomains) == false) return false;
+        }
         return (mDnses.size() == targetDnses.size()) ?
                     mDnses.containsAll(targetDnses) : false;
     }
@@ -359,13 +378,13 @@
         return ((null == mIfaceName) ? 0 : mIfaceName.hashCode()
                 + mLinkAddresses.size() * 31
                 + mDnses.size() * 37
+                + ((null == mDomains) ? 0 : mDomains.hashCode())
                 + mRoutes.size() * 41
                 + ((null == mHttpProxy) ? 0 : mHttpProxy.hashCode()));
     }
 
     /**
      * Implement the Parcelable interface.
-     * @hide
      */
     public void writeToParcel(Parcel dest, int flags) {
         dest.writeString(getInterfaceName());
@@ -378,6 +397,7 @@
         for(InetAddress d : mDnses) {
             dest.writeByteArray(d.getAddress());
         }
+        dest.writeString(mDomains);
 
         dest.writeInt(mRoutes.size());
         for(RouteInfo route : mRoutes) {
@@ -394,19 +414,15 @@
 
     /**
      * Implement the Parcelable interface.
-     * @hide
      */
     public static final Creator<LinkProperties> CREATOR =
         new Creator<LinkProperties>() {
             public LinkProperties createFromParcel(Parcel in) {
                 LinkProperties netProp = new LinkProperties();
+
                 String iface = in.readString();
                 if (iface != null) {
-                    try {
-                        netProp.setInterfaceName(iface);
-                    } catch (Exception e) {
-                        return null;
-                    }
+                    netProp.setInterfaceName(iface);
                 }
                 int addressCount = in.readInt();
                 for (int i=0; i<addressCount; i++) {
@@ -418,6 +434,7 @@
                         netProp.addDns(InetAddress.getByAddress(in.createByteArray()));
                     } catch (UnknownHostException e) { }
                 }
+                netProp.setDomains(in.readString());
                 addressCount = in.readInt();
                 for (int i=0; i<addressCount; i++) {
                     netProp.addRoute((RouteInfo)in.readParcelable(null));
diff --git a/core/java/android/net/NetworkUtils.java b/core/java/android/net/NetworkUtils.java
index d39e741..4ab479e 100644
--- a/core/java/android/net/NetworkUtils.java
+++ b/core/java/android/net/NetworkUtils.java
@@ -62,21 +62,21 @@
      * addresses. This call blocks until it obtains a result (either success
      * or failure) from the daemon.
      * @param interfaceName the name of the interface to configure
-     * @param ipInfo if the request succeeds, this object is filled in with
+     * @param dhcpResults if the request succeeds, this object is filled in with
      * the IP address information.
      * @return {@code true} for success, {@code false} for failure
      */
-    public native static boolean runDhcp(String interfaceName, DhcpInfoInternal ipInfo);
+    public native static boolean runDhcp(String interfaceName, DhcpResults dhcpResults);
 
     /**
      * Initiate renewal on the Dhcp client daemon. This call blocks until it obtains
      * a result (either success or failure) from the daemon.
      * @param interfaceName the name of the interface to configure
-     * @param ipInfo if the request succeeds, this object is filled in with
+     * @param dhcpResults if the request succeeds, this object is filled in with
      * the IP address information.
      * @return {@code true} for success, {@code false} for failure
      */
-    public native static boolean runDhcpRenew(String interfaceName, DhcpInfoInternal ipInfo);
+    public native static boolean runDhcpRenew(String interfaceName, DhcpResults dhcpResults);
 
     /**
      * Shut down the DHCP client daemon.
@@ -124,12 +124,9 @@
      * @param inetAddr is an InetAddress corresponding to the IPv4 address
      * @return the IP address as an integer in network byte order
      */
-    public static int inetAddressToInt(InetAddress inetAddr)
+    public static int inetAddressToInt(Inet4Address inetAddr)
             throws IllegalArgumentException {
         byte [] addr = inetAddr.getAddress();
-        if (addr.length != 4) {
-            throw new IllegalArgumentException("Not an IPv4 address");
-        }
         return ((addr[3] & 0xff) << 24) | ((addr[2] & 0xff) << 16) |
                 ((addr[1] & 0xff) << 8) | (addr[0] & 0xff);
     }
diff --git a/core/java/android/net/RouteInfo.java b/core/java/android/net/RouteInfo.java
index 275f32a..112e143 100644
--- a/core/java/android/net/RouteInfo.java
+++ b/core/java/android/net/RouteInfo.java
@@ -76,6 +76,10 @@
         this(null, gateway);
     }
 
+    public RouteInfo(LinkAddress host) {
+        this(host, null);
+    }
+
     public static RouteInfo makeHostRoute(InetAddress host) {
         return makeHostRoute(host, null);
     }
diff --git a/core/java/android/net/http/AndroidHttpClient.java b/core/java/android/net/http/AndroidHttpClient.java
index c534e58..c66ab52 100644
--- a/core/java/android/net/http/AndroidHttpClient.java
+++ b/core/java/android/net/http/AndroidHttpClient.java
@@ -17,6 +17,7 @@
 package android.net.http;
 
 import com.android.internal.http.HttpDateTime;
+
 import org.apache.http.Header;
 import org.apache.http.HttpEntity;
 import org.apache.http.HttpEntityEnclosingRequest;
@@ -25,18 +26,18 @@
 import org.apache.http.HttpRequest;
 import org.apache.http.HttpRequestInterceptor;
 import org.apache.http.HttpResponse;
-import org.apache.http.entity.AbstractHttpEntity;
-import org.apache.http.entity.ByteArrayEntity;
+import org.apache.http.client.ClientProtocolException;
 import org.apache.http.client.HttpClient;
 import org.apache.http.client.ResponseHandler;
-import org.apache.http.client.ClientProtocolException;
-import org.apache.http.client.protocol.ClientContext;
 import org.apache.http.client.methods.HttpUriRequest;
 import org.apache.http.client.params.HttpClientParams;
+import org.apache.http.client.protocol.ClientContext;
 import org.apache.http.conn.ClientConnectionManager;
 import org.apache.http.conn.scheme.PlainSocketFactory;
 import org.apache.http.conn.scheme.Scheme;
 import org.apache.http.conn.scheme.SchemeRegistry;
+import org.apache.http.entity.AbstractHttpEntity;
+import org.apache.http.entity.ByteArrayEntity;
 import org.apache.http.impl.client.DefaultHttpClient;
 import org.apache.http.impl.client.RequestWrapper;
 import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
@@ -44,26 +45,26 @@
 import org.apache.http.params.HttpConnectionParams;
 import org.apache.http.params.HttpParams;
 import org.apache.http.params.HttpProtocolParams;
+import org.apache.http.protocol.BasicHttpContext;
 import org.apache.http.protocol.BasicHttpProcessor;
 import org.apache.http.protocol.HttpContext;
-import org.apache.http.protocol.BasicHttpContext;
 
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.OutputStream;
-import java.util.zip.GZIPInputStream;
-import java.util.zip.GZIPOutputStream;
-import java.net.URI;
-
-import android.content.Context;
 import android.content.ContentResolver;
+import android.content.Context;
 import android.net.SSLCertificateSocketFactory;
 import android.net.SSLSessionCache;
 import android.os.Looper;
 import android.util.Base64;
 import android.util.Log;
 
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.URI;
+import java.util.zip.GZIPInputStream;
+import java.util.zip.GZIPOutputStream;
+
 /**
  * Implementation of the Apache {@link DefaultHttpClient} that is configured with
  * reasonable default settings and registered schemes for Android, and
@@ -267,7 +268,7 @@
         return delegate.execute(target, request, context);
     }
 
-    public <T> T execute(HttpUriRequest request, 
+    public <T> T execute(HttpUriRequest request,
             ResponseHandler<? extends T> responseHandler)
             throws IOException, ClientProtocolException {
         return delegate.execute(request, responseHandler);
@@ -405,6 +406,11 @@
 
         builder.append("curl ");
 
+        // add in the method
+        builder.append("-X ");
+        builder.append(request.getMethod());
+        builder.append(" ");
+
         for (Header header: request.getAllHeaders()) {
             if (!logAuthToken
                     && (header.getName().equals("Authorization") ||
diff --git a/core/java/android/os/INetworkManagementService.aidl b/core/java/android/os/INetworkManagementService.aidl
index 2179fa1..80abd0f 100644
--- a/core/java/android/os/INetworkManagementService.aidl
+++ b/core/java/android/os/INetworkManagementService.aidl
@@ -351,7 +351,7 @@
     /**
      * Bind name servers to an interface in the DNS resolver.
      */
-    void setDnsServersForInterface(String iface, in String[] servers);
+    void setDnsServersForInterface(String iface, in String[] servers, String domains);
 
     /**
      * Flush the DNS cache associated with the default interface.
diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java
index 6d5705d..500bb2c 100644
--- a/core/java/android/service/wallpaper/WallpaperService.java
+++ b/core/java/android/service/wallpaper/WallpaperService.java
@@ -84,7 +84,7 @@
      * tag.
      */
     public static final String SERVICE_META_DATA = "android.service.wallpaper";
-    
+
     static final String TAG = "WallpaperService";
     static final boolean DEBUG = false;
     
@@ -100,7 +100,6 @@
     private static final int MSG_WINDOW_MOVED = 10035;
     private static final int MSG_TOUCH_EVENT = 10040;
     
-    private Looper mCallbackLooper;
     private final ArrayList<Engine> mActiveEngines
             = new ArrayList<Engine>();
     
@@ -961,13 +960,7 @@
         IWallpaperEngineWrapper(WallpaperService context,
                 IWallpaperConnection conn, IBinder windowToken,
                 int windowType, boolean isPreview, int reqWidth, int reqHeight) {
-            if (DEBUG && mCallbackLooper != null) {
-                mCallbackLooper.setMessageLogging(new LogPrinter(Log.VERBOSE, TAG));
-            }
-            mCaller = new HandlerCaller(context,
-                    mCallbackLooper != null
-                            ? mCallbackLooper : context.getMainLooper(),
-                    this);
+            mCaller = new HandlerCaller(context, context.getMainLooper(), this);
             mConnection = conn;
             mWindowToken = windowToken;
             mWindowType = windowType;
@@ -1105,13 +1098,14 @@
             mTarget = context;
         }
 
+        @Override
         public void attach(IWallpaperConnection conn, IBinder windowToken,
                 int windowType, boolean isPreview, int reqWidth, int reqHeight) {
             new IWallpaperEngineWrapper(mTarget, conn, windowToken,
                     windowType, isPreview, reqWidth, reqHeight);
         }
     }
-    
+
     @Override
     public void onCreate() {
         super.onCreate();
@@ -1134,20 +1128,7 @@
     public final IBinder onBind(Intent intent) {
         return new IWallpaperServiceWrapper(this);
     }
-    
-    /**
-     * This allows subclasses to change the thread that most callbacks
-     * occur on.  Currently hidden because it is mostly needed for the
-     * image wallpaper (which runs in the system process and doesn't want
-     * to get stuck running on that seriously in use main thread).  Not
-     * exposed right now because the semantics of this are not totally
-     * well defined and some callbacks can still happen on the main thread).
-     * @hide
-     */
-    public void setCallbackLooper(Looper looper) {
-        mCallbackLooper = looper;
-    }
-    
+
     /**
      * Must be implemented to return a new instance of the wallpaper's engine.
      * Note that multiple instances may be active at the same time, such as
diff --git a/core/java/android/speech/tts/ITextToSpeechService.aidl b/core/java/android/speech/tts/ITextToSpeechService.aidl
index ab63187..580d52c 100644
--- a/core/java/android/speech/tts/ITextToSpeechService.aidl
+++ b/core/java/android/speech/tts/ITextToSpeechService.aidl
@@ -131,6 +131,8 @@
     /**
      * Notifies the engine that it should load a speech synthesis language.
      *
+     * @param caller a binder representing the identity of the calling
+     *        TextToSpeech object.
      * @param lang ISO-3 language code.
      * @param country ISO-3 country code. May be empty or null.
      * @param variant Language variant. May be empty or null.
@@ -141,13 +143,14 @@
      *         {@link TextToSpeech#LANG_MISSING_DATA}
      *         {@link TextToSpeech#LANG_NOT_SUPPORTED}.
      */
-    int loadLanguage(in String lang, in String country, in String variant);
+    int loadLanguage(in IBinder caller, in String lang, in String country, in String variant);
 
     /**
      * Sets the callback that will be notified when playback of utterance from the
      * given app are completed.
      *
-     * @param callingApp Package name for the app whose utterance the callback will handle.
+     * @param caller Instance a binder representing the identity of the calling
+     *        TextToSpeech object.
      * @param cb The callback.
      */
     void setCallback(in IBinder caller, ITextToSpeechCallback cb);
diff --git a/core/java/android/speech/tts/SynthesisCallback.java b/core/java/android/speech/tts/SynthesisCallback.java
index d70c371d..f98bb09 100644
--- a/core/java/android/speech/tts/SynthesisCallback.java
+++ b/core/java/android/speech/tts/SynthesisCallback.java
@@ -22,10 +22,11 @@
  * {@link #start}, then {@link #audioAvailable} until all audio has been provided, then finally
  * {@link #done}.
  *
- *
  * {@link #error} can be called at any stage in the synthesis process to
  * indicate that an error has occurred, but if the call is made after a call
  * to {@link #done}, it might be discarded.
+ *
+ * After {@link #start} been called, {@link #done} must be called regardless of errors.
  */
 public interface SynthesisCallback {
     /**
@@ -72,6 +73,8 @@
      * This method should only be called on the synthesis thread,
      * while in {@link TextToSpeechService#onSynthesizeText}.
      *
+     * This method has to be called if {@link #start} was called.
+     *
      * @return {@link TextToSpeech#SUCCESS} or {@link TextToSpeech#ERROR}.
      */
     public int done();
diff --git a/core/java/android/speech/tts/TextToSpeech.java b/core/java/android/speech/tts/TextToSpeech.java
index 5e367cb..cb5e0cd 100644
--- a/core/java/android/speech/tts/TextToSpeech.java
+++ b/core/java/android/speech/tts/TextToSpeech.java
@@ -24,6 +24,7 @@
 import android.content.ServiceConnection;
 import android.media.AudioManager;
 import android.net.Uri;
+import android.os.AsyncTask;
 import android.os.Bundle;
 import android.os.IBinder;
 import android.os.RemoteException;
@@ -793,10 +794,16 @@
     }
 
     /**
-     * Speaks the string using the specified queuing strategy and speech
-     * parameters.
+     * Speaks the string using the specified queuing strategy and speech parameters.
+     * This method is asynchronous, i.e. the method just adds the request to the queue of TTS
+     * requests and then returns. The synthesis might not have finished (or even started!) at the
+     * time when this method returns. In order to reliably detect errors during synthesis,
+     * we recommend setting an utterance progress listener (see
+     * {@link #setOnUtteranceProgressListener}) and using the
+     * {@link Engine#KEY_PARAM_UTTERANCE_ID} parameter.
      *
-     * @param text The string of text to be spoken.
+     * @param text The string of text to be spoken. No longer than
+     *            {@link #getMaxSpeechInputLength()} characters.
      * @param queueMode The queuing strategy to use, {@link #QUEUE_ADD} or {@link #QUEUE_FLUSH}.
      * @param params Parameters for the request. Can be null.
      *            Supported parameter names:
@@ -809,7 +816,7 @@
      *            the keys "com.svox.pico_foo" and "com.svox.pico:bar" will be passed to the
      *            engine named "com.svox.pico" if it is being used.
      *
-     * @return {@link #ERROR} or {@link #SUCCESS}.
+     * @return {@link #ERROR} or {@link #SUCCESS} of <b>queuing</b> the speak operation.
      */
     public int speak(final String text, final int queueMode, final HashMap<String, String> params) {
         return runAction(new Action<Integer>() {
@@ -830,6 +837,12 @@
      * Plays the earcon using the specified queueing mode and parameters.
      * The earcon must already have been added with {@link #addEarcon(String, String)} or
      * {@link #addEarcon(String, String, int)}.
+     * This method is asynchronous, i.e. the method just adds the request to the queue of TTS
+     * requests and then returns. The synthesis might not have finished (or even started!) at the
+     * time when this method returns. In order to reliably detect errors during synthesis,
+     * we recommend setting an utterance progress listener (see
+     * {@link #setOnUtteranceProgressListener}) and using the
+     * {@link Engine#KEY_PARAM_UTTERANCE_ID} parameter.
      *
      * @param earcon The earcon that should be played
      * @param queueMode {@link #QUEUE_ADD} or {@link #QUEUE_FLUSH}.
@@ -842,7 +855,7 @@
      *            the keys "com.svox.pico_foo" and "com.svox.pico:bar" will be passed to the
      *            engine named "com.svox.pico" if it is being used.
      *
-     * @return {@link #ERROR} or {@link #SUCCESS}.
+     * @return {@link #ERROR} or {@link #SUCCESS} of <b>queuing</b> the playEarcon operation.
      */
     public int playEarcon(final String earcon, final int queueMode,
             final HashMap<String, String> params) {
@@ -862,6 +875,12 @@
     /**
      * Plays silence for the specified amount of time using the specified
      * queue mode.
+     * This method is asynchronous, i.e. the method just adds the request to the queue of TTS
+     * requests and then returns. The synthesis might not have finished (or even started!) at the
+     * time when this method returns. In order to reliably detect errors during synthesis,
+     * we recommend setting an utterance progress listener (see
+     * {@link #setOnUtteranceProgressListener}) and using the
+     * {@link Engine#KEY_PARAM_UTTERANCE_ID} parameter.
      *
      * @param durationInMs The duration of the silence.
      * @param queueMode {@link #QUEUE_ADD} or {@link #QUEUE_FLUSH}.
@@ -873,7 +892,7 @@
      *            the keys "com.svox.pico_foo" and "com.svox.pico:bar" will be passed to the
      *            engine named "com.svox.pico" if it is being used.
      *
-     * @return {@link #ERROR} or {@link #SUCCESS}.
+     * @return {@link #ERROR} or {@link #SUCCESS} of <b>queuing</b> the playSilence operation.
      */
     public int playSilence(final long durationInMs, final int queueMode,
             final HashMap<String, String> params) {
@@ -1031,7 +1050,8 @@
                 // the available parts.
                 // Note that the language is not actually set here, instead it is cached so it
                 // will be associated with all upcoming utterances.
-                int result = service.loadLanguage(language, country, variant);
+
+                int result = service.loadLanguage(getCallerIdentity(), language, country, variant);
                 if (result >= LANG_AVAILABLE){
                     if (result < LANG_COUNTRY_VAR_AVAILABLE) {
                         variant = "";
@@ -1049,21 +1069,30 @@
     }
 
     /**
-     * Returns a Locale instance describing the language currently being used by the TextToSpeech
-     * engine.
+     * Returns a Locale instance describing the language currently being used for synthesis
+     * requests sent to the TextToSpeech engine.
      *
-     * @return language, country (if any) and variant (if any) used by the engine stored in a Locale
-     *     instance, or {@code null} on error.
+     * In Android 4.2 and before (API <= 17) this function returns the language that is currently
+     * being used by the TTS engine. That is the last language set by this or any other
+     * client by a {@link TextToSpeech#setLanguage} call to the same engine.
+     *
+     * In Android versions after 4.2 this function returns the language that is currently being
+     * used for the synthesis requests sent from this client. That is the last language set
+     * by a {@link TextToSpeech#setLanguage} call on this instance.
+     *
+     * @return language, country (if any) and variant (if any) used by the client stored in a
+     *     Locale instance, or {@code null} on error.
      */
     public Locale getLanguage() {
         return runAction(new Action<Locale>() {
             @Override
-            public Locale run(ITextToSpeechService service) throws RemoteException {
-                String[] locStrings = service.getLanguage();
-                if (locStrings != null && locStrings.length == 3) {
-                    return new Locale(locStrings[0], locStrings[1], locStrings[2]);
-                }
-                return null;
+            public Locale run(ITextToSpeechService service) {
+                /* No service call, but we're accessing mParams, hence need for
+                   wrapping it as an Action instance */
+                String lang = mParams.getString(Engine.KEY_PARAM_LANGUAGE, "");
+                String country = mParams.getString(Engine.KEY_PARAM_COUNTRY, "");
+                String variant = mParams.getString(Engine.KEY_PARAM_VARIANT, "");
+                return new Locale(lang, country, variant);
             }
         }, null, "getLanguage");
     }
@@ -1089,8 +1118,15 @@
 
     /**
      * Synthesizes the given text to a file using the specified parameters.
+     * This method is asynchronous, i.e. the method just adds the request to the queue of TTS
+     * requests and then returns. The synthesis might not have finished (or even started!) at the
+     * time when this method returns. In order to reliably detect errors during synthesis,
+     * we recommend setting an utterance progress listener (see
+     * {@link #setOnUtteranceProgressListener}) and using the
+     * {@link Engine#KEY_PARAM_UTTERANCE_ID} parameter.
      *
-     * @param text The text that should be synthesized
+     * @param text The text that should be synthesized. No longer than
+     *            {@link #getMaxSpeechInputLength()} characters.
      * @param params Parameters for the request. Can be null.
      *            Supported parameter names:
      *            {@link Engine#KEY_PARAM_UTTERANCE_ID}.
@@ -1101,7 +1137,7 @@
      * @param filename Absolute file filename to write the generated audio data to.It should be
      *            something like "/sdcard/myappsounds/mysound.wav".
      *
-     * @return {@link #ERROR} or {@link #SUCCESS}.
+     * @return {@link #ERROR} or {@link #SUCCESS} of <b>queuing</b> the synthesizeToFile operation.
      */
     public int synthesizeToFile(final String text, final HashMap<String, String> params,
             final String filename) {
@@ -1253,9 +1289,11 @@
         return mEnginesHelper.getEngines();
     }
 
-
     private class Connection implements ServiceConnection {
         private ITextToSpeechService mService;
+
+        private OnServiceConnectedAsyncTask mOnServiceConnectedAsyncTask;
+
         private final ITextToSpeechCallback.Stub mCallback = new ITextToSpeechCallback.Stub() {
             @Override
             public void onDone(String utteranceId) {
@@ -1282,23 +1320,59 @@
             }
         };
 
+        private class OnServiceConnectedAsyncTask extends AsyncTask<Void, Void, Integer> {
+            private final ComponentName mName;
+            private final ITextToSpeechService mConnectedService;
+
+            public OnServiceConnectedAsyncTask(ComponentName name, IBinder service) {
+                mName = name;
+                mConnectedService = ITextToSpeechService.Stub.asInterface(service);
+            }
+
+            @Override
+            protected Integer doInBackground(Void... params) {
+                synchronized(mStartLock) {
+                    if (isCancelled()) {
+                        return null;
+                    }
+
+                    try {
+                        mConnectedService.setCallback(getCallerIdentity(), mCallback);
+                        Log.i(TAG, "Setuped connection to " + mName);
+                        return SUCCESS;
+                    } catch (RemoteException re) {
+                        Log.e(TAG, "Error connecting to service, setCallback() failed");
+                        return ERROR;
+                    }
+                }
+            }
+
+            @Override
+            protected void onPostExecute(Integer result) {
+                synchronized(mStartLock) {
+                    if (mOnServiceConnectedAsyncTask == this) {
+                        mOnServiceConnectedAsyncTask = null;
+                    }
+
+                    mServiceConnection = Connection.this;
+                    mService = mConnectedService;
+
+                    dispatchOnInit(result);
+                }
+            }
+        }
+
         @Override
         public void onServiceConnected(ComponentName name, IBinder service) {
-            Log.i(TAG, "Connected to " + name);
             synchronized(mStartLock) {
-                if (mServiceConnection != null) {
-                    // Disconnect any previous service connection
-                    mServiceConnection.disconnect();
+                Log.i(TAG, "Connected to " + name);
+
+                if (mOnServiceConnectedAsyncTask != null) {
+                    mOnServiceConnectedAsyncTask.cancel(false);
                 }
-                mServiceConnection = this;
-                mService = ITextToSpeechService.Stub.asInterface(service);
-                try {
-                    mService.setCallback(getCallerIdentity(), mCallback);
-                    dispatchOnInit(SUCCESS);
-                } catch (RemoteException re) {
-                    Log.e(TAG, "Error connecting to service, setCallback() failed");
-                    dispatchOnInit(ERROR);
-                }
+
+                mOnServiceConnectedAsyncTask = new OnServiceConnectedAsyncTask(name, service);
+                mOnServiceConnectedAsyncTask.execute();
             }
         }
 
@@ -1306,28 +1380,45 @@
             return mCallback;
         }
 
-        @Override
-        public void onServiceDisconnected(ComponentName name) {
+        /**
+         * Clear connection related fields and cancel mOnServiceConnectedAsyncTask if set.
+         *
+         * @return true if we cancel mOnServiceConnectedAsyncTask in progress.
+         */
+        private boolean clearServiceConnection() {
             synchronized(mStartLock) {
+                boolean result = false;
+                if (mOnServiceConnectedAsyncTask != null) {
+                    result = mOnServiceConnectedAsyncTask.cancel(false);
+                    mOnServiceConnectedAsyncTask = null;
+                }
+
                 mService = null;
                 // If this is the active connection, clear it
                 if (mServiceConnection == this) {
                     mServiceConnection = null;
                 }
+                return result;
+            }
+        }
+
+        @Override
+        public void onServiceDisconnected(ComponentName name) {
+            Log.i(TAG, "Asked to disconnect from " + name);
+            if (clearServiceConnection()) {
+                /* We need to protect against a rare case where engine
+                 * dies just after successful connection - and we process onServiceDisconnected
+                 * before OnServiceConnectedAsyncTask.onPostExecute. onServiceDisconnected cancels
+                 * OnServiceConnectedAsyncTask.onPostExecute and we don't call dispatchOnInit
+                 * with ERROR as argument.
+                 */
+                dispatchOnInit(ERROR);
             }
         }
 
         public void disconnect() {
             mContext.unbindService(this);
-
-            synchronized (mStartLock) {
-                mService = null;
-                // If this is the active connection, clear it
-                if (mServiceConnection == this) {
-                    mServiceConnection = null;
-                }
-
-            }
+            clearServiceConnection();
         }
 
         public <R> R runAction(Action<R> action, R errorResult, String method, boolean reconnect) {
@@ -1394,4 +1485,13 @@
 
     }
 
+    /**
+     * Limit of length of input string passed to speak and synthesizeToFile.
+     *
+     * @see #speak
+     * @see #synthesizeToFile
+     */
+    public static int getMaxSpeechInputLength() {
+        return 4000;
+    }
 }
diff --git a/core/java/android/speech/tts/TextToSpeechService.java b/core/java/android/speech/tts/TextToSpeechService.java
index d124e68..458350d 100644
--- a/core/java/android/speech/tts/TextToSpeechService.java
+++ b/core/java/android/speech/tts/TextToSpeechService.java
@@ -34,7 +34,6 @@
 import android.util.Log;
 
 import java.io.File;
-import java.io.IOException;
 import java.util.HashMap;
 import java.util.Locale;
 import java.util.Set;
@@ -74,7 +73,7 @@
     private static final boolean DBG = false;
     private static final String TAG = "TextToSpeechService";
 
-    private static final int MAX_SPEECH_ITEM_CHAR_LENGTH = 4000;
+
     private static final String SYNTH_THREAD_NAME = "SynthThread";
 
     private SynthHandler mSynthHandler;
@@ -129,6 +128,8 @@
      *
      * Can be called on multiple threads.
      *
+     * Its return values HAVE to be consistent with onLoadLanguage.
+     *
      * @param lang ISO-3 language code.
      * @param country ISO-3 country code. May be empty or null.
      * @param variant Language variant. May be empty or null.
@@ -163,6 +164,8 @@
      * at some point in the future.
      *
      * Can be called on multiple threads.
+     * In <= Android 4.2 (<= API 17) can be called on main and service binder threads.
+     * In > Android 4.2 (> API 17) can be called on main and synthesis threads.
      *
      * @param lang ISO-3 language code.
      * @param country ISO-3 country code. May be empty or null.
@@ -256,7 +259,6 @@
     }
 
     private class SynthHandler extends Handler {
-
         private SpeechItem mCurrentSpeechItem = null;
 
         public SynthHandler(Looper looper) {
@@ -275,7 +277,7 @@
 
         private synchronized SpeechItem maybeRemoveCurrentSpeechItem(Object callerIdentity) {
             if (mCurrentSpeechItem != null &&
-                    mCurrentSpeechItem.getCallerIdentity() == callerIdentity) {
+                    (mCurrentSpeechItem.getCallerIdentity() == callerIdentity)) {
                 SpeechItem current = mCurrentSpeechItem;
                 mCurrentSpeechItem = null;
                 return current;
@@ -296,7 +298,6 @@
             if (current != null) {
                 current.stop();
             }
-
             // The AudioPlaybackHandler will be destroyed by the caller.
         }
 
@@ -306,8 +307,15 @@
          * Called on a service binder thread.
          */
         public int enqueueSpeechItem(int queueMode, final SpeechItem speechItem) {
+            UtteranceProgressDispatcher utterenceProgress = null;
+            if (speechItem instanceof UtteranceProgressDispatcher) {
+                utterenceProgress = (UtteranceProgressDispatcher) speechItem;
+            }
+
             if (!speechItem.isValid()) {
-                speechItem.dispatchOnError();
+                if (utterenceProgress != null) {
+                    utterenceProgress.dispatchOnError();
+                }
                 return TextToSpeech.ERROR;
             }
 
@@ -325,6 +333,7 @@
                 }
             };
             Message msg = Message.obtain(this, runnable);
+
             // The obj is used to remove all callbacks from the given app in
             // stopForApp(String).
             //
@@ -334,7 +343,9 @@
                 return TextToSpeech.SUCCESS;
             } else {
                 Log.w(TAG, "SynthThread has quit");
-                speechItem.dispatchOnError();
+                if (utterenceProgress != null) {
+                    utterenceProgress.dispatchOnError();
+                }
                 return TextToSpeech.ERROR;
             }
         }
@@ -370,7 +381,7 @@
         }
 
         public int stopAll() {
-            // Stop the current speech item unconditionally.
+            // Stop the current speech item unconditionally .
             SpeechItem current = setCurrentSpeechItem(null);
             if (current != null) {
                 current.stop();
@@ -393,7 +404,7 @@
     /**
      * An item in the synth thread queue.
      */
-    private abstract class SpeechItem implements UtteranceProgressDispatcher {
+    private abstract class SpeechItem {
         private final Object mCallerIdentity;
         protected final Bundle mParams;
         private final int mCallerUid;
@@ -412,6 +423,15 @@
             return mCallerIdentity;
         }
 
+
+        public int getCallerUid() {
+            return mCallerUid;
+        }
+
+        public int getCallerPid() {
+            return mCallerPid;
+        }
+
         /**
          * Checker whether the item is valid. If this method returns false, the item should not
          * be played.
@@ -436,6 +456,8 @@
             return playImpl();
         }
 
+        protected abstract int playImpl();
+
         /**
          * Stops the speech item.
          * Must not be called more than once.
@@ -452,6 +474,23 @@
             stopImpl();
         }
 
+        protected abstract void stopImpl();
+
+        protected synchronized boolean isStopped() {
+             return mStopped;
+        }
+    }
+
+    /**
+     * An item in the synth thread queue that process utterance.
+     */
+    private abstract class UtteranceSpeechItem extends SpeechItem
+        implements UtteranceProgressDispatcher  {
+
+        public UtteranceSpeechItem(Object caller, int callerUid, int callerPid, Bundle params) {
+            super(caller, callerUid, callerPid, params);
+        }
+
         @Override
         public void dispatchOnDone() {
             final String utteranceId = getUtteranceId();
@@ -476,22 +515,6 @@
             }
         }
 
-        public int getCallerUid() {
-            return mCallerUid;
-        }
-
-        public int getCallerPid() {
-            return mCallerPid;
-        }
-
-        protected synchronized boolean isStopped() {
-             return mStopped;
-        }
-
-        protected abstract int playImpl();
-
-        protected abstract void stopImpl();
-
         public int getStreamType() {
             return getIntParam(Engine.KEY_PARAM_STREAM, Engine.DEFAULT_STREAM);
         }
@@ -519,9 +542,10 @@
         protected float getFloatParam(String key, float defaultValue) {
             return mParams == null ? defaultValue : mParams.getFloat(key, defaultValue);
         }
+
     }
 
-    class SynthesisSpeechItem extends SpeechItem {
+    class SynthesisSpeechItem extends UtteranceSpeechItem {
         // Never null.
         private final String mText;
         private final SynthesisRequest mSynthesisRequest;
@@ -552,7 +576,7 @@
                 Log.e(TAG, "null synthesis text");
                 return false;
             }
-            if (mText.length() >= MAX_SPEECH_ITEM_CHAR_LENGTH) {
+            if (mText.length() >= TextToSpeech.getMaxSpeechInputLength()) {
                 Log.w(TAG, "Text too long: " + mText.length() + " chars");
                 return false;
             }
@@ -658,7 +682,7 @@
         }
     }
 
-    private class AudioSpeechItem extends SpeechItem {
+    private class AudioSpeechItem extends UtteranceSpeechItem {
         private final AudioPlaybackQueueItem mItem;
         public AudioSpeechItem(Object callerIdentity, int callerUid, int callerPid,
                 Bundle params, Uri uri) {
@@ -684,7 +708,7 @@
         }
     }
 
-    private class SilenceSpeechItem extends SpeechItem {
+    private class SilenceSpeechItem extends UtteranceSpeechItem {
         private final long mDuration;
 
         public SilenceSpeechItem(Object callerIdentity, int callerUid, int callerPid,
@@ -711,6 +735,41 @@
         }
     }
 
+    private class LoadLanguageItem extends SpeechItem {
+        private final String mLanguage;
+        private final String mCountry;
+        private final String mVariant;
+
+        public LoadLanguageItem(Object callerIdentity, int callerUid, int callerPid,
+                Bundle params, String language, String country, String variant) {
+            super(callerIdentity, callerUid, callerPid, params);
+            mLanguage = language;
+            mCountry = country;
+            mVariant = variant;
+        }
+
+        @Override
+        public boolean isValid() {
+            return true;
+        }
+
+        @Override
+        protected int playImpl() {
+            int result = TextToSpeechService.this.onLoadLanguage(mLanguage, mCountry, mVariant);
+            if (result == TextToSpeech.LANG_AVAILABLE ||
+                    result == TextToSpeech.LANG_COUNTRY_AVAILABLE ||
+                    result == TextToSpeech.LANG_COUNTRY_VAR_AVAILABLE) {
+                return TextToSpeech.SUCCESS;
+            }
+            return TextToSpeech.ERROR;
+        }
+
+        @Override
+        protected void stopImpl() {
+            // No-op
+        }
+    }
+
     @Override
     public IBinder onBind(Intent intent) {
         if (TextToSpeech.Engine.INTENT_ACTION_TTS_SERVICE.equals(intent.getAction())) {
@@ -822,12 +881,25 @@
          * are enforced.
          */
         @Override
-        public int loadLanguage(String lang, String country, String variant) {
+        public int loadLanguage(IBinder caller, String lang, String country, String variant) {
             if (!checkNonNull(lang)) {
                 return TextToSpeech.ERROR;
             }
+            int retVal = onIsLanguageAvailable(lang, country, variant);
 
-            return onLoadLanguage(lang, country, variant);
+            if (retVal == TextToSpeech.LANG_AVAILABLE ||
+                    retVal == TextToSpeech.LANG_COUNTRY_AVAILABLE ||
+                    retVal == TextToSpeech.LANG_COUNTRY_VAR_AVAILABLE) {
+
+                SpeechItem item = new LoadLanguageItem(caller, Binder.getCallingUid(),
+                    Binder.getCallingPid(), null, lang, country, variant);
+
+                if (mSynthHandler.enqueueSpeechItem(TextToSpeech.QUEUE_ADD, item) !=
+                        TextToSpeech.SUCCESS) {
+                    return TextToSpeech.ERROR;
+                }
+            }
+            return retVal;
         }
 
         @Override
diff --git a/core/java/android/text/method/DigitsKeyListener.java b/core/java/android/text/method/DigitsKeyListener.java
index 3d9daed..c95df46 100644
--- a/core/java/android/text/method/DigitsKeyListener.java
+++ b/core/java/android/text/method/DigitsKeyListener.java
@@ -49,13 +49,22 @@
      * @see KeyEvent#getMatch
      * @see #getAcceptedChars
      */
-    private static final char[][] CHARACTERS = new char[][] {
-        new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' },
-        new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-' },
-        new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '.' },
-        new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-', '.' },
+    private static final char[][] CHARACTERS = {
+        { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' },
+        { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-', '+' },
+        { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '.' },
+        { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-', '+', '.' },
     };
 
+    private static boolean isSignChar(final char c) {
+        return c == '-' || c == '+';
+    }
+
+    // TODO: Needs internationalization
+    private static boolean isDecimalPointChar(final char c) {
+        return c == '.';
+    }
+
     /**
      * Allocates a DigitsKeyListener that accepts the digits 0 through 9.
      */
@@ -145,32 +154,32 @@
         int dlen = dest.length();
 
         /*
-         * Find out if the existing text has '-' or '.' characters.
+         * Find out if the existing text has a sign or decimal point characters.
          */
 
         for (int i = 0; i < dstart; i++) {
             char c = dest.charAt(i);
 
-            if (c == '-') {
+            if (isSignChar(c)) {
                 sign = i;
-            } else if (c == '.') {
+            } else if (isDecimalPointChar(c)) {
                 decimal = i;
             }
         }
         for (int i = dend; i < dlen; i++) {
             char c = dest.charAt(i);
 
-            if (c == '-') {
-                return "";    // Nothing can be inserted in front of a '-'.
-            } else if (c == '.') {
+            if (isSignChar(c)) {
+                return "";    // Nothing can be inserted in front of a sign character.
+            } else if (isDecimalPointChar(c)) {
                 decimal = i;
             }
         }
 
         /*
          * If it does, we must strip them out from the source.
-         * In addition, '-' must be the very first character,
-         * and nothing can be inserted before an existing '-'.
+         * In addition, a sign character must be the very first character,
+         * and nothing can be inserted before an existing sign character.
          * Go in reverse order so the offsets are stable.
          */
 
@@ -180,7 +189,7 @@
             char c = source.charAt(i);
             boolean strip = false;
 
-            if (c == '-') {
+            if (isSignChar(c)) {
                 if (i != start || dstart != 0) {
                     strip = true;
                 } else if (sign >= 0) {
@@ -188,7 +197,7 @@
                 } else {
                     sign = i;
                 }
-            } else if (c == '.') {
+            } else if (isDecimalPointChar(c)) {
                 if (decimal >= 0) {
                     strip = true;
                 } else {
diff --git a/core/java/android/text/style/SuggestionSpan.java b/core/java/android/text/style/SuggestionSpan.java
index 5dc206f..0ec7e84 100644
--- a/core/java/android/text/style/SuggestionSpan.java
+++ b/core/java/android/text/style/SuggestionSpan.java
@@ -17,6 +17,7 @@
 package android.text.style;
 
 import android.content.Context;
+import android.content.Intent;
 import android.content.res.TypedArray;
 import android.graphics.Color;
 import android.os.Parcel;
@@ -26,6 +27,7 @@
 import android.text.TextPaint;
 import android.text.TextUtils;
 import android.util.Log;
+import android.view.inputmethod.InputMethodManager;
 import android.widget.TextView;
 
 import java.util.Arrays;
@@ -45,6 +47,8 @@
  */
 public class SuggestionSpan extends CharacterStyle implements ParcelableSpan {
 
+    private static final String TAG = "SuggestionSpan";
+
     /**
      * Sets this flag if the suggestions should be easily accessible with few interactions.
      * This flag should be set for every suggestions that the user is likely to use.
@@ -82,6 +86,7 @@
     private final String[] mSuggestions;
     private final String mLocaleString;
     private final String mNotificationTargetClassName;
+    private final String mNotificationTargetPackageName;
     private final int mHashCode;
 
     private float mEasyCorrectUnderlineThickness;
@@ -134,6 +139,12 @@
             mLocaleString = "";
         }
 
+        if (context != null) {
+            mNotificationTargetPackageName = context.getPackageName();
+        } else {
+            mNotificationTargetPackageName = null;
+        }
+
         if (notificationTargetClass != null) {
             mNotificationTargetClassName = notificationTargetClass.getCanonicalName();
         } else {
@@ -185,6 +196,7 @@
         mFlags = src.readInt();
         mLocaleString = src.readString();
         mNotificationTargetClassName = src.readString();
+        mNotificationTargetPackageName = src.readString();
         mHashCode = src.readInt();
         mEasyCorrectUnderlineColor = src.readInt();
         mEasyCorrectUnderlineThickness = src.readFloat();
@@ -240,6 +252,7 @@
         dest.writeInt(mFlags);
         dest.writeString(mLocaleString);
         dest.writeString(mNotificationTargetClassName);
+        dest.writeString(mNotificationTargetPackageName);
         dest.writeInt(mHashCode);
         dest.writeInt(mEasyCorrectUnderlineColor);
         dest.writeFloat(mEasyCorrectUnderlineThickness);
@@ -325,4 +338,40 @@
         }
         return 0;
     }
+
+    /**
+     * Notifies a suggestion selection.
+     *
+     * @hide
+     */
+    public void notifySelection(Context context, String original, int index) {
+        final Intent intent = new Intent();
+
+        if (context == null || mNotificationTargetClassName == null) {
+            return;
+        }
+        // Ensures that only a class in the original IME package will receive the
+        // notification.
+        if (mSuggestions == null || index < 0 || index >= mSuggestions.length) {
+            Log.w(TAG, "Unable to notify the suggestion as the index is out of range index=" + index
+                    + " length=" + mSuggestions.length);
+            return;
+        }
+
+        // The package name is not mandatory (legacy from JB), and if the package name
+        // is missing, we try to notify the suggestion through the input method manager.
+        if (mNotificationTargetPackageName != null) {
+            intent.setClassName(mNotificationTargetPackageName, mNotificationTargetClassName);
+            intent.setAction(SuggestionSpan.ACTION_SUGGESTION_PICKED);
+            intent.putExtra(SuggestionSpan.SUGGESTION_SPAN_PICKED_BEFORE, original);
+            intent.putExtra(SuggestionSpan.SUGGESTION_SPAN_PICKED_AFTER, mSuggestions[index]);
+            intent.putExtra(SuggestionSpan.SUGGESTION_SPAN_PICKED_HASHCODE, hashCode());
+            context.sendBroadcast(intent);
+        } else {
+            InputMethodManager imm = InputMethodManager.peekInstance();
+            if (imm != null) {
+                imm.notifySuggestionPicked(this, original, index);
+            }
+        }
+    }
 }
diff --git a/core/java/android/util/PropertyValueModel.java b/core/java/android/util/PropertyValueModel.java
new file mode 100755
index 0000000..eb9c47d
--- /dev/null
+++ b/core/java/android/util/PropertyValueModel.java
@@ -0,0 +1,143 @@
+/*
+ * 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.util;
+
+/**
+ * A value model for a {@link Property property} of a host object. This class can be used for
+ * both reflective and non-reflective property implementations.
+ *
+ * @param <H> the host type, where the host is the object that holds this property
+ * @param <T> the value type
+ *
+ * @see Property
+ * @see ValueModel
+ */
+public class PropertyValueModel<H, T> extends ValueModel<T> {
+    private final H mHost;
+    private final Property<H, T> mProperty;
+
+    private PropertyValueModel(H host, Property<H, T> property) {
+        mProperty = property;
+        mHost = host;
+    }
+
+    /**
+     * Returns the host.
+     *
+     * @return the host
+     */
+    public H getHost() {
+        return mHost;
+    }
+
+    /**
+     * Returns the property.
+     *
+     * @return the property
+     */
+    public Property<H, T> getProperty() {
+        return mProperty;
+    }
+
+    @Override
+    public Class<T> getType() {
+        return mProperty.getType();
+    }
+
+    @Override
+    public T get() {
+        return mProperty.get(mHost);
+    }
+
+    @Override
+    public void set(T value) {
+        mProperty.set(mHost, value);
+    }
+
+    /**
+     * Return an appropriate PropertyValueModel for this host and property.
+     *
+     * @param host the host
+     * @param property the property
+     * @return the value model
+     */
+    public static <H, T> PropertyValueModel<H, T> of(H host, Property<H, T> property) {
+        return new PropertyValueModel<H, T>(host, property);
+    }
+
+    /**
+     * Return a PropertyValueModel for this {@code host} and a
+     * reflective property, constructed from this {@code propertyType} and {@code propertyName}.
+     *
+     * @param host
+     * @param propertyType the property type
+     * @param propertyName the property name
+     * @return a value model with this host and a reflective property with this type and name
+     *
+     * @see Property#of
+     */
+    public static <H, T> PropertyValueModel<H, T> of(H host, Class<T> propertyType,
+            String propertyName) {
+        return of(host, Property.of((Class<H>) host.getClass(), propertyType, propertyName));
+    }
+
+    private static Class getNullaryMethodReturnType(Class c, String name) {
+        try {
+            return c.getMethod(name).getReturnType();
+        } catch (NoSuchMethodException e) {
+            return null;
+        }
+    }
+
+    private static Class getFieldType(Class c, String name) {
+        try {
+            return c.getField(name).getType();
+        } catch (NoSuchFieldException e) {
+            return null;
+        }
+    }
+
+    private static String capitalize(String name) {
+        if (name.isEmpty()) {
+            return name;
+        }
+        return Character.toUpperCase(name.charAt(0)) + name.substring(1);
+    }
+
+    /**
+     * Return a PropertyValueModel for this {@code host} and and {@code propertyName}.
+     *
+     * @param host the host
+     * @param propertyName the property name
+     * @return a value model with this host and a reflective property with this name
+     */
+    public static PropertyValueModel of(Object host, String propertyName) {
+        Class clazz = host.getClass();
+        String suffix = capitalize(propertyName);
+        Class propertyType = getNullaryMethodReturnType(clazz, "get" + suffix);
+        if (propertyType == null) {
+            propertyType = getNullaryMethodReturnType(clazz, "is" + suffix);
+        } 
+        if (propertyType == null) {
+            propertyType = getFieldType(clazz, propertyName); 
+        }         
+        if (propertyType == null) {
+            throw new NoSuchPropertyException(propertyName); 
+        }
+        return of(host, propertyType, propertyName);
+    }
+}
diff --git a/core/java/android/util/SparseLongArray.java b/core/java/android/util/SparseLongArray.java
index a08d5cb..2f7a6fe 100644
--- a/core/java/android/util/SparseLongArray.java
+++ b/core/java/android/util/SparseLongArray.java
@@ -22,8 +22,6 @@
  * SparseLongArrays map integers to longs.  Unlike a normal array of longs,
  * there can be gaps in the indices.  It is intended to be more efficient
  * than using a HashMap to map Integers to Longs.
- *
- * @hide
  */
 public class SparseLongArray implements Cloneable {
 
diff --git a/core/java/android/util/ValueModel.java b/core/java/android/util/ValueModel.java
new file mode 100755
index 0000000..4789682
--- /dev/null
+++ b/core/java/android/util/ValueModel.java
@@ -0,0 +1,74 @@
+/*
+ * 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.util;
+
+/**
+ * A ValueModel is an abstraction for a 'slot' or place in memory in which a value
+ * may be stored and retrieved. A common implementation of ValueModel is a regular property of
+ * an object, whose value may be retrieved by calling the appropriate <em>getter</em>
+ * method and set by calling the corresponding <em>setter</em> method.
+ *
+ * @param <T> the value type
+ *
+ * @see PropertyValueModel
+ */
+public abstract class ValueModel<T> {
+    /**
+     * The empty model should be used in place of {@code null} to indicate that a
+     * model has not been set. The empty model has no value and does nothing when it is set.
+     */
+    public static final ValueModel EMPTY = new ValueModel() {
+        @Override
+        public Class getType() {
+            return Object.class;
+        }
+
+        @Override
+        public Object get() {
+            return null;
+        }
+
+        @Override
+        public void set(Object value) {
+
+        }
+    };
+
+    protected ValueModel() {
+    }
+
+    /**
+     * Returns the type of this property.
+     *
+     * @return the property type
+     */
+    public abstract Class<T> getType();
+
+    /**
+     * Returns the value of this property.
+     *
+     * @return the property value
+     */
+    public abstract T get();
+
+    /**
+     * Sets the value of this property.
+     *
+     * @param value the new value for this property
+     */
+    public abstract void set(T value);
+}
\ No newline at end of file
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 1747627..7799bb9 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -13978,6 +13978,25 @@
     }
 
     /**
+     * Return true if o is a ViewGroup that is laying out using optical bounds.
+     * @hide
+     */
+    public static boolean isLayoutModeOptical(Object o) {
+        return o instanceof ViewGroup && ((ViewGroup) o).isLayoutModeOptical();
+    }
+
+    private boolean setOpticalFrame(int left, int top, int right, int bottom) {
+        Insets parentInsets = mParent instanceof View ?
+                ((View) mParent).getOpticalInsets() : Insets.NONE;
+        Insets childInsets = getOpticalInsets();
+        return setFrame(
+                left   + parentInsets.left - childInsets.left,
+                top    + parentInsets.top  - childInsets.top,
+                right  + parentInsets.left + childInsets.right,
+                bottom + parentInsets.top  + childInsets.bottom);
+    }
+
+    /**
      * Assign a size and position to a view and all of its
      * descendants
      *
@@ -14003,7 +14022,8 @@
         int oldT = mTop;
         int oldB = mBottom;
         int oldR = mRight;
-        boolean changed = setFrame(l, t, r, b);
+        boolean changed = isLayoutModeOptical(mParent) ?
+                setOpticalFrame(l, t, r, b) : setFrame(l, t, r, b);
         if (changed || (mPrivateFlags & PFLAG_LAYOUT_REQUIRED) == PFLAG_LAYOUT_REQUIRED) {
             onLayout(changed, l, t, r, b);
             mPrivateFlags &= ~PFLAG_LAYOUT_REQUIRED;
@@ -14819,6 +14839,10 @@
         return (mUserPaddingStart != UNDEFINED_PADDING || mUserPaddingEnd != UNDEFINED_PADDING);
     }
 
+    Insets computeOpticalInsets() {
+        return (mBackground == null) ? Insets.NONE : mBackground.getOpticalInsets();
+    }
+
     /**
      * @hide
      */
@@ -14842,19 +14866,12 @@
      */
     public Insets getOpticalInsets() {
         if (mLayoutInsets == null) {
-            mLayoutInsets = (mBackground == null) ? Insets.NONE : mBackground.getLayoutInsets();
+            mLayoutInsets = computeOpticalInsets();
         }
         return mLayoutInsets;
     }
 
     /**
-     * @hide
-     */
-    public void setLayoutInsets(Insets layoutInsets) {
-        mLayoutInsets = layoutInsets;
-    }
-
-    /**
      * Changes the selection state of this view. A view can be selected or not.
      * Note that selection is not the same as focus. Views are typically
      * selected in the context of an AdapterView like ListView or GridView;
@@ -15461,11 +15478,34 @@
     }
 
     /**
+     * Returns whether the view hierarchy is currently undergoing a layout pass. This
+     * information is useful to avoid situations such as calling {@link #requestLayout()} during
+     * a layout pass.
+     *
+     * @return whether the view hierarchy is currently undergoing a layout pass
+     */
+    public boolean isInLayout() {
+        ViewRootImpl viewRoot = getViewRootImpl();
+        return (viewRoot != null && viewRoot.isInLayout());
+    }
+
+    /**
      * Call this when something has changed which has invalidated the
      * layout of this view. This will schedule a layout pass of the view
-     * tree.
+     * tree. This should not be called while the view hierarchy is currently in a layout
+     * pass ({@link #isInLayout()}. If layout is happening, the request may be honored at the
+     * end of the current layout pass (and then layout will run again) or after the current
+     * frame is drawn and the next layout occurs.
+     *
+     * <p>Subclasses which override this method should call the superclass method to
+     * handle possible request-during-layout errors correctly.</p>
      */
     public void requestLayout() {
+        ViewRootImpl viewRoot = getViewRootImpl();
+        if (viewRoot != null && viewRoot.isInLayout()) {
+            viewRoot.requestLayoutDuringLayout(this);
+            return;
+        }
         mPrivateFlags |= PFLAG_FORCE_LAYOUT;
         mPrivateFlags |= PFLAG_INVALIDATED;
 
@@ -15505,6 +15545,14 @@
      * @see #onMeasure(int, int)
      */
     public final void measure(int widthMeasureSpec, int heightMeasureSpec) {
+        boolean optical = isLayoutModeOptical(this);
+        if (optical != isLayoutModeOptical(mParent)) {
+            Insets insets = getOpticalInsets();
+            int oWidth  = insets.left + insets.right;
+            int oHeight = insets.top  + insets.bottom;
+            widthMeasureSpec  = MeasureSpec.adjust(widthMeasureSpec,  optical ? -oWidth  : oWidth);
+            heightMeasureSpec = MeasureSpec.adjust(heightMeasureSpec, optical ? -oHeight : oHeight);
+        }
         if ((mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT ||
                 widthMeasureSpec != mOldWidthMeasureSpec ||
                 heightMeasureSpec != mOldHeightMeasureSpec) {
@@ -15596,6 +15644,15 @@
      * {@link #MEASURED_STATE_TOO_SMALL}.
      */
     protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) {
+        boolean optical = isLayoutModeOptical(this);
+        if (optical != isLayoutModeOptical(mParent)) {
+            Insets insets = getOpticalInsets();
+            int opticalWidth  = insets.left + insets.right;
+            int opticalHeight = insets.top  + insets.bottom;
+
+            measuredWidth  += optical ? opticalWidth  : -opticalWidth;
+            measuredHeight += optical ? opticalHeight : -opticalHeight;
+        }
         mMeasuredWidth = measuredWidth;
         mMeasuredHeight = measuredHeight;
 
@@ -17272,7 +17329,7 @@
          * @return the measure specification based on size and mode
          */
         public static int makeMeasureSpec(int size, int mode) {
-            return size + mode;
+            return (size & ~MODE_MASK) | (mode & MODE_MASK);
         }
 
         /**
@@ -17297,6 +17354,10 @@
             return (measureSpec & ~MODE_MASK);
         }
 
+        static int adjust(int measureSpec, int delta) {
+            return makeMeasureSpec(getSize(measureSpec + delta), getMode(measureSpec));
+        }
+
         /**
          * Returns a String representation of the specified measure
          * specification.
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 00723f3..ad28f7b 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -23,9 +23,11 @@
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.Color;
+import android.graphics.DashPathEffect;
 import android.graphics.Insets;
 import android.graphics.Matrix;
 import android.graphics.Paint;
+import android.graphics.PathEffect;
 import android.graphics.PointF;
 import android.graphics.Rect;
 import android.graphics.RectF;
@@ -83,6 +85,8 @@
     private static final String TAG = "ViewGroup";
 
     private static final boolean DBG = false;
+    /** @hide */
+    public static boolean DEBUG_DRAW = false;
 
     /**
      * Views which have been hidden or removed which need to be animated on
@@ -180,10 +184,10 @@
     })
     protected int mGroupFlags;
 
-    /*
-     * The layout mode: either {@link #CLIP_BOUNDS} or {@link #OPTICAL_BOUNDS}
+    /**
+     * Either {@link #LAYOUT_MODE_CLIP_BOUNDS} or {@link #LAYOUT_MODE_OPTICAL_BOUNDS}.
      */
-    private int mLayoutMode = CLIP_BOUNDS;
+    private int mLayoutMode = DEFAULT_LAYOUT_MODE;
 
     /**
      * NOTE: If you change the flags below make sure to reflect the changes
@@ -356,20 +360,19 @@
      * This constant is a {@link #setLayoutMode(int) layoutMode}.
      * Clip bounds are the raw values of {@link #getLeft() left}, {@link #getTop() top},
      * {@link #getRight() right} and {@link #getBottom() bottom}.
-     *
-     * @hide
      */
-    public static final int CLIP_BOUNDS = 0;
+    public static final int LAYOUT_MODE_CLIP_BOUNDS = 0;
 
     /**
      * This constant is a {@link #setLayoutMode(int) layoutMode}.
      * Optical bounds describe where a widget appears to be. They sit inside the clip
      * bounds which need to cover a larger area to allow other effects,
      * such as shadows and glows, to be drawn.
-     *
-     * @hide
      */
-    public static final int OPTICAL_BOUNDS = 1;
+    public static final int LAYOUT_MODE_OPTICAL_BOUNDS = 1;
+
+    /** @hide */
+    public static int DEFAULT_LAYOUT_MODE = LAYOUT_MODE_CLIP_BOUNDS;
 
     /**
      * We clip to padding when FLAG_CLIP_TO_PADDING and FLAG_PADDING_NOT_NULL
@@ -434,7 +437,7 @@
     }
 
     private boolean debugDraw() {
-        return mAttachInfo != null && mAttachInfo.mDebugLayout;
+        return DEBUG_DRAW || mAttachInfo != null && mAttachInfo.mDebugLayout;
     }
 
     private void initViewGroup() {
@@ -504,6 +507,9 @@
                         setLayoutTransition(new LayoutTransition());
                     }
                     break;
+                case R.styleable.ViewGroup_layoutMode:
+                    setLayoutMode(a.getInt(attr, DEFAULT_LAYOUT_MODE));
+                    break;
             }
         }
 
@@ -2420,7 +2426,7 @@
         for (int i = 0; i < count; i++) {
             final View child = children[i];
             child.dispatchAttachedToWindow(info,
-                    visibility | (child.mViewFlags&VISIBILITY_MASK));
+                    visibility | (child.mViewFlags & VISIBILITY_MASK));
         }
     }
 
@@ -2682,20 +2688,89 @@
         return b;
     }
 
-    private static void drawRect(Canvas canvas, int x1, int y1, int x2, int y2, int color) {
-        Paint paint = getDebugPaint();
-        paint.setColor(color);
+    /** Return true if this ViewGroup is laying out using optical bounds. */
+    boolean isLayoutModeOptical() {
+        return mLayoutMode == LAYOUT_MODE_OPTICAL_BOUNDS;
+    }
 
-        canvas.drawLines(getDebugLines(x1, y1, x2, y2), paint);
+    Insets computeOpticalInsets() {
+        if (isLayoutModeOptical()) {
+            int left = 0;
+            int top = 0;
+            int right = 0;
+            int bottom = 0;
+            for (int i = 0; i < mChildrenCount; i++) {
+                View child = getChildAt(i);
+                if (child.getVisibility() == VISIBLE) {
+                    Insets insets = child.getOpticalInsets();
+                    left =   Math.max(left,   insets.left);
+                    top =    Math.max(top,    insets.top);
+                    right =  Math.max(right,  insets.right);
+                    bottom = Math.max(bottom, insets.bottom);
+                }
+            }
+            return Insets.of(left, top, right, bottom);
+        } else {
+            return Insets.NONE;
+        }
+    }
+
+    private static void fillRect(Canvas canvas, Paint paint, int x1, int y1, int x2, int y2) {
+        if (x1 != x2 && y1 != y2) {
+            if (x1 > x2) {
+                int tmp = x1; x1 = x2; x2 = tmp;
+            }
+            if (y1 > y2) {
+                int tmp = y1; y1 = y2; y2 = tmp;
+            }
+            canvas.drawRect(x1, y1, x2, y2, paint);
+        }
+    }
+
+    private static int sign(int x) {
+        return (x >= 0) ? 1 : -1;
+    }
+
+    private static void drawCorner(Canvas c, Paint paint, int x1, int y1, int dx, int dy, int lw) {
+        fillRect(c, paint, x1, y1, x1 + dx, y1 + lw * sign(dy));
+        fillRect(c, paint, x1, y1, x1 + lw * sign(dx), y1 + dy);
+    }
+
+    private int dipsToPixels(int dips) {
+        float scale = getContext().getResources().getDisplayMetrics().density;
+        return (int) (dips * scale + 0.5f);
+    }
+
+    private void drawRectCorners(Canvas canvas, int x1, int y1, int x2, int y2, Paint paint,
+                                 int lineLength, int lineWidth) {
+        drawCorner(canvas, paint, x1, y1, lineLength, lineLength, lineWidth);
+        drawCorner(canvas, paint, x1, y2, lineLength, -lineLength, lineWidth);
+        drawCorner(canvas, paint, x2, y1, -lineLength, lineLength, lineWidth);
+        drawCorner(canvas, paint, x2, y2, -lineLength, -lineLength, lineWidth);
+    }
+
+    private static void fillDifference(Canvas canvas,
+            int x2, int y2, int x3, int y3,
+            int dx1, int dy1, int dx2, int dy2, Paint paint) {
+        int x1 = x2 - dx1;
+        int y1 = y2 - dy1;
+
+        int x4 = x3 + dx2;
+        int y4 = y3 + dy2;
+
+        fillRect(canvas, paint, x1, y1, x4, y2);
+        fillRect(canvas, paint, x1, y2, x2, y3);
+        fillRect(canvas, paint, x3, y2, x4, y3);
+        fillRect(canvas, paint, x1, y3, x4, y4);
     }
 
     /**
      * @hide
      */
-    protected void onDebugDrawMargins(Canvas canvas) {
+    protected void onDebugDrawMargins(Canvas canvas, Paint paint) {
         for (int i = 0; i < getChildCount(); i++) {
             View c = getChildAt(i);
-            c.getLayoutParams().onDebugDraw(c, canvas);
+            c.getLayoutParams().onDebugDraw(c, canvas, paint);
         }
     }
 
@@ -2703,26 +2778,45 @@
      * @hide
      */
     protected void onDebugDraw(Canvas canvas) {
+        Paint paint = getDebugPaint();
+
         // Draw optical bounds
-        if (getLayoutMode() == OPTICAL_BOUNDS) {
+        {
+            paint.setColor(Color.RED);
+            paint.setStyle(Paint.Style.STROKE);
+
             for (int i = 0; i < getChildCount(); i++) {
                 View c = getChildAt(i);
                 Insets insets = c.getOpticalInsets();
-                drawRect(canvas,
-                        c.getLeft() + insets.left,
-                        c.getTop() + insets.top,
-                        c.getRight() - insets.right,
-                        c.getBottom() - insets.bottom, Color.RED);
+
+                drawRect(canvas, paint,
+                        c.getLeft()   + insets.left,
+                        c.getTop()    + insets.top,
+                        c.getRight()  - insets.right  - 1,
+                        c.getBottom() - insets.bottom - 1);
             }
         }
 
         // Draw margins
-        onDebugDrawMargins(canvas);
+        {
+            paint.setColor(Color.argb(63, 255, 0, 255));
+            paint.setStyle(Paint.Style.FILL);
 
-        // Draw bounds
-        for (int i = 0; i < getChildCount(); i++) {
-            View c = getChildAt(i);
-            drawRect(canvas, c.getLeft(), c.getTop(), c.getRight(), c.getBottom(), Color.BLUE);
+            onDebugDrawMargins(canvas, paint);
+        }
+
+        // Draw clip bounds
+        {
+            paint.setColor(Color.rgb(63, 127, 255));
+            paint.setStyle(Paint.Style.FILL);
+
+            int lineLength = dipsToPixels(8);
+            int lineWidth = dipsToPixels(1);
+            for (int i = 0; i < getChildCount(); i++) {
+                View c = getChildAt(i);
+                drawRectCorners(canvas, c.getLeft(), c.getTop(), c.getRight(), c.getBottom(),
+                        paint, lineLength, lineWidth);
+            }
         }
     }
 
@@ -4612,13 +4706,11 @@
 
     /**
      * Returns the basis of alignment during layout operations on this view group:
-     * either {@link #CLIP_BOUNDS} or {@link #OPTICAL_BOUNDS}.
+     * either {@link #LAYOUT_MODE_CLIP_BOUNDS} or {@link #LAYOUT_MODE_OPTICAL_BOUNDS}.
      *
      * @return the layout mode to use during layout operations
      *
      * @see #setLayoutMode(int)
-     *
-     * @hide
      */
     public int getLayoutMode() {
         return mLayoutMode;
@@ -4626,15 +4718,14 @@
 
     /**
      * Sets the basis of alignment during the layout of this view group.
-     * Valid values are either {@link #CLIP_BOUNDS} or {@link #OPTICAL_BOUNDS}.
+     * Valid values are either {@link #LAYOUT_MODE_CLIP_BOUNDS} or
+     * {@link #LAYOUT_MODE_OPTICAL_BOUNDS}.
      * <p>
-     * The default is {@link #CLIP_BOUNDS}.
+     * The default is {@link #LAYOUT_MODE_CLIP_BOUNDS}.
      *
      * @param layoutMode the layout mode to use during layout operations
      *
      * @see #getLayoutMode()
-     *
-     * @hide
      */
     public void setLayoutMode(int layoutMode) {
         if (mLayoutMode != layoutMode) {
@@ -5667,7 +5758,7 @@
          *
          * @hide
          */
-        public void onDebugDraw(View view, Canvas canvas) {
+        public void onDebugDraw(View view, Canvas canvas, Paint paint) {
         }
 
         /**
@@ -6015,12 +6106,19 @@
          * @hide
          */
         @Override
-        public void onDebugDraw(View view, Canvas canvas) {
-            drawRect(canvas,
-                    view.getLeft() - leftMargin,
-                    view.getTop() - topMargin,
-                    view.getRight() + rightMargin,
-                    view.getBottom() + bottomMargin, Color.MAGENTA);
+        public void onDebugDraw(View view, Canvas canvas, Paint paint) {
+            Insets oi = isLayoutModeOptical(view.mParent) ? view.getOpticalInsets() : Insets.NONE;
+
+            fillDifference(canvas,
+                    view.getLeft()   + oi.left,
+                    view.getTop()    + oi.top,
+                    view.getRight()  - oi.right,
+                    view.getBottom() - oi.bottom,
+                    leftMargin,
+                    topMargin,
+                    rightMargin,
+                    bottomMargin,
+                    paint);
         }
     }
 
@@ -6354,14 +6452,11 @@
         return sDebugPaint;
     }
 
-    private static float[] getDebugLines(int x1, int y1, int x2, int y2) {
+    private void drawRect(Canvas canvas, Paint paint, int x1, int y1, int x2, int y2) {
         if (sDebugLines== null) {
             sDebugLines = new float[16];
         }
 
-        x2--;
-        y2--;
-
         sDebugLines[0] = x1;
         sDebugLines[1] = y1;
         sDebugLines[2] = x2;
@@ -6370,18 +6465,18 @@
         sDebugLines[4] = x2;
         sDebugLines[5] = y1;
         sDebugLines[6] = x2;
-        sDebugLines[7] = y2 + 1;
+        sDebugLines[7] = y2;
 
-        sDebugLines[8] = x2 + 1;
+        sDebugLines[8] = x2;
         sDebugLines[9] = y2;
         sDebugLines[10] = x1;
         sDebugLines[11] = y2;
 
-        sDebugLines[12]  = x1;
-        sDebugLines[13]  = y2;
+        sDebugLines[12] = x1;
+        sDebugLines[13] = y2;
         sDebugLines[14] = x1;
         sDebugLines[15] = y1;
 
-        return sDebugLines;
+        canvas.drawLines(sDebugLines, paint);
     }
 }
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 27d770b..fbaec71 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -317,6 +317,10 @@
     private final int mDensity;
     private final int mNoncompatDensity;
 
+    private boolean mInLayout = false;
+    ArrayList<View> mLayoutRequesters = new ArrayList<View>();
+    boolean mHandlingLayoutInLayoutRequest = false;
+
     private int mViewLayoutDirectionInitial;
 
     /**
@@ -1879,9 +1883,49 @@
         }
     }
 
+    /**
+     * Called by {@link android.view.View#isInLayout()} to determine whether the view hierarchy
+     * is currently undergoing a layout pass.
+     *
+     * @return whether the view hierarchy is currently undergoing a layout pass
+     */
+    boolean isInLayout() {
+        return mInLayout;
+    }
+
+    /**
+     * Called by {@link android.view.View#requestLayout()} if the view hiearchy is currently
+     * undergoing a layout pass. requestLayout() should not be called during layout, but if it
+     * is called anyway, we handle the situation here rather than leave the hierarchy in an
+     * indeterminate state. The solution is to queue up all requests during layout, apply those
+     * requests as soon as layout is complete, and then run layout once more immediately. If
+     * more requestLayout() calls are received during that second layout pass, we post those
+     * requests to the next frame, to avoid possible infinite loops.
+     *
+     * @param view the view that requested the layout.
+     */
+    void requestLayoutDuringLayout(final View view) {
+        if (!mHandlingLayoutInLayoutRequest) {
+            if (!mLayoutRequesters.contains(view)) {
+                Log.w("View", "requestLayout() called by " + view + " during layout pass");
+                mLayoutRequesters.add(view);
+            }
+        } else {
+            Log.w("View", "requestLayout() called by " + view + " during second layout pass: " +
+                    "posting to next frame");
+            view.post(new Runnable() {
+                @Override
+                public void run() {
+                    view.requestLayout();
+                }
+            });
+        }
+    }
+
     private void performLayout() {
         mLayoutRequested = false;
         mScrollMayChange = true;
+        mInLayout = true;
 
         final View host = mView;
         if (DEBUG_ORIENTATION || DEBUG_LAYOUT) {
@@ -1892,9 +1936,24 @@
         Trace.traceBegin(Trace.TRACE_TAG_VIEW, "layout");
         try {
             host.layout(0, 0, host.getMeasuredWidth(), host.getMeasuredHeight());
+            mInLayout = false;
+            int numViewsRequestingLayout = mLayoutRequesters.size();
+            if (numViewsRequestingLayout > 0) {
+                // requestLayout() was called during layout: unusual, but try to handle correctly
+                mHandlingLayoutInLayoutRequest = true;
+                for (int i = 0; i < numViewsRequestingLayout; ++i) {
+                    mLayoutRequesters.get(i).requestLayout();
+                }
+                // Now run layout one more time
+                mInLayout = true;
+                host.layout(0, 0, host.getMeasuredWidth(), host.getMeasuredHeight());
+                mHandlingLayoutInLayoutRequest = false;
+                mLayoutRequesters.clear();
+            }
         } finally {
             Trace.traceEnd(Trace.TRACE_TAG_VIEW);
         }
+        mInLayout = false;
     }
 
     public void requestTransparentRegion(View child) {
diff --git a/core/java/android/view/accessibility/AccessibilityEvent.java b/core/java/android/view/accessibility/AccessibilityEvent.java
index 1500905..03288ba 100644
--- a/core/java/android/view/accessibility/AccessibilityEvent.java
+++ b/core/java/android/view/accessibility/AccessibilityEvent.java
@@ -1137,54 +1137,176 @@
      * @return The string representation.
      */
     public static String eventTypeToString(int eventType) {
-        switch (eventType) {
-            case TYPE_VIEW_CLICKED:
-                return "TYPE_VIEW_CLICKED";
-            case TYPE_VIEW_LONG_CLICKED:
-                return "TYPE_VIEW_LONG_CLICKED";
-            case TYPE_VIEW_SELECTED:
-                return "TYPE_VIEW_SELECTED";
-            case TYPE_VIEW_FOCUSED:
-                return "TYPE_VIEW_FOCUSED";
-            case TYPE_VIEW_TEXT_CHANGED:
-                return "TYPE_VIEW_TEXT_CHANGED";
-            case TYPE_WINDOW_STATE_CHANGED:
-                return "TYPE_WINDOW_STATE_CHANGED";
-            case TYPE_VIEW_HOVER_ENTER:
-                return "TYPE_VIEW_HOVER_ENTER";
-            case TYPE_VIEW_HOVER_EXIT:
-                return "TYPE_VIEW_HOVER_EXIT";
-            case TYPE_NOTIFICATION_STATE_CHANGED:
-                return "TYPE_NOTIFICATION_STATE_CHANGED";  
-            case TYPE_TOUCH_EXPLORATION_GESTURE_START:
-                return "TYPE_TOUCH_EXPLORATION_GESTURE_START";
-            case TYPE_TOUCH_EXPLORATION_GESTURE_END:
-                return "TYPE_TOUCH_EXPLORATION_GESTURE_END";
-            case TYPE_WINDOW_CONTENT_CHANGED:
-                return "TYPE_WINDOW_CONTENT_CHANGED";
-            case TYPE_VIEW_TEXT_SELECTION_CHANGED:
-                return "TYPE_VIEW_TEXT_SELECTION_CHANGED";
-            case TYPE_VIEW_SCROLLED:
-                return "TYPE_VIEW_SCROLLED";
-            case TYPE_ANNOUNCEMENT:
-                return "TYPE_ANNOUNCEMENT";
-            case TYPE_VIEW_ACCESSIBILITY_FOCUSED:
-                return "TYPE_VIEW_ACCESSIBILITY_FOCUSED";
-            case TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED:
-                return "TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED";
-            case TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY:
-                return "TYPE_CURRENT_AT_GRANULARITY_MOVEMENT_CHANGED";
-            case TYPE_GESTURE_DETECTION_START:
-                return "TYPE_GESTURE_DETECTION_START";
-            case TYPE_GESTURE_DETECTION_END:
-                return "TYPE_GESTURE_DETECTION_END";
-            case TYPE_TOUCH_INTERACTION_START:
-                return "TYPE_TOUCH_INTERACTION_START";
-            case TYPE_TOUCH_INTERACTION_END:
-                return "TYPE_TOUCH_INTERACTION_END";
-            default:
-                return null;
+        if (eventType == TYPES_ALL_MASK) {
+            return "TYPES_ALL_MASK";
         }
+        StringBuilder builder = new StringBuilder();
+        int eventTypeCount = 0;
+        while (eventType != 0) {
+            final int eventTypeFlag = 1 << Integer.numberOfTrailingZeros(eventType);
+            eventType &= ~eventTypeFlag;
+            switch (eventTypeFlag) {
+                case TYPE_VIEW_CLICKED: {
+                    if (eventTypeCount > 0) {
+                        builder.append(", ");
+                    }
+                    builder.append("TYPE_VIEW_CLICKED");
+                    eventTypeCount++;
+                } break;
+                case TYPE_VIEW_LONG_CLICKED: {
+                    if (eventTypeCount > 0) {
+                        builder.append(", ");
+                    }
+                    builder.append("TYPE_VIEW_LONG_CLICKED");
+                    eventTypeCount++;
+                } break;
+                case TYPE_VIEW_SELECTED: {
+                    if (eventTypeCount > 0) {
+                        builder.append(", ");
+                    }
+                    builder.append("TYPE_VIEW_SELECTED");
+                    eventTypeCount++;
+                } break;
+                case TYPE_VIEW_FOCUSED: {
+                    if (eventTypeCount > 0) {
+                        builder.append(", ");
+                    }
+                    builder.append("TYPE_VIEW_FOCUSED");
+                    eventTypeCount++;
+                } break;
+                case TYPE_VIEW_TEXT_CHANGED: {
+                    if (eventTypeCount > 0) {
+                        builder.append(", ");
+                    }
+                    builder.append("TYPE_VIEW_TEXT_CHANGED");
+                    eventTypeCount++;
+                } break;
+                case TYPE_WINDOW_STATE_CHANGED: {
+                    if (eventTypeCount > 0) {
+                        builder.append(", ");
+                    }
+                    builder.append("TYPE_WINDOW_STATE_CHANGED");
+                    eventTypeCount++;
+                } break;
+                case TYPE_VIEW_HOVER_ENTER: {
+                    if (eventTypeCount > 0) {
+                        builder.append(", ");
+                    }
+                    builder.append("TYPE_VIEW_HOVER_ENTER");
+                    eventTypeCount++;
+                } break;
+                case TYPE_VIEW_HOVER_EXIT: {
+                    if (eventTypeCount > 0) {
+                        builder.append(", ");
+                    }
+                    builder.append("TYPE_VIEW_HOVER_EXIT");
+                    eventTypeCount++;
+                } break;
+                case TYPE_NOTIFICATION_STATE_CHANGED: {
+                    if (eventTypeCount > 0) {
+                        builder.append(", ");
+                    }
+                    builder.append("TYPE_NOTIFICATION_STATE_CHANGED");
+                    eventTypeCount++;
+                } break;
+                case TYPE_TOUCH_EXPLORATION_GESTURE_START: {
+                    if (eventTypeCount > 0) {
+                        builder.append(", ");
+                    }
+                    builder.append("TYPE_TOUCH_EXPLORATION_GESTURE_START");
+                    eventTypeCount++;
+                } break;
+                case TYPE_TOUCH_EXPLORATION_GESTURE_END: {
+                    if (eventTypeCount > 0) {
+                        builder.append(", ");
+                    }
+                    builder.append("TYPE_TOUCH_EXPLORATION_GESTURE_END");
+                    eventTypeCount++;
+                } break;
+                case TYPE_WINDOW_CONTENT_CHANGED: {
+                    if (eventTypeCount > 0) {
+                        builder.append(", ");
+                    }
+                    builder.append("TYPE_WINDOW_CONTENT_CHANGED");
+                    eventTypeCount++;
+                } break;
+                case TYPE_VIEW_TEXT_SELECTION_CHANGED: {
+                    if (eventTypeCount > 0) {
+                        builder.append(", ");
+                    }
+                    builder.append("TYPE_VIEW_TEXT_SELECTION_CHANGED");
+                    eventTypeCount++;
+                } break;
+                case TYPE_VIEW_SCROLLED: {
+                    if (eventTypeCount > 0) {
+                        builder.append(", ");
+                    }
+                    builder.append("TYPE_VIEW_SCROLLED");
+                    eventTypeCount++;
+                } break;
+                case TYPE_ANNOUNCEMENT: {
+                    if (eventTypeCount > 0) {
+                        builder.append(", ");
+                    }
+                    builder.append("TYPE_ANNOUNCEMENT");
+                    eventTypeCount++;
+                } break;
+                case TYPE_VIEW_ACCESSIBILITY_FOCUSED: {
+                    if (eventTypeCount > 0) {
+                        builder.append(", ");
+                    }
+                    builder.append("TYPE_VIEW_ACCESSIBILITY_FOCUSED");
+                    eventTypeCount++;
+                } break;
+                case TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED: {
+                    if (eventTypeCount > 0) {
+                        builder.append(", ");
+                    }
+                    builder.append("TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED");
+                    eventTypeCount++;
+                } break;
+                case TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY: {
+                    if (eventTypeCount > 0) {
+                        builder.append(", ");
+                    }
+                    builder.append("TYPE_CURRENT_AT_GRANULARITY_MOVEMENT_CHANGED");
+                    eventTypeCount++;
+                } break;
+                case TYPE_GESTURE_DETECTION_START: {
+                    if (eventTypeCount > 0) {
+                        builder.append(", ");
+                    }
+                    builder.append("TYPE_GESTURE_DETECTION_START");
+                    eventTypeCount++;
+                } break;
+                case TYPE_GESTURE_DETECTION_END: {
+                    if (eventTypeCount > 0) {
+                        builder.append(", ");
+                    }
+                    builder.append("TYPE_GESTURE_DETECTION_END");
+                    eventTypeCount++;
+                } break;
+                case TYPE_TOUCH_INTERACTION_START: {
+                    if (eventTypeCount > 0) {
+                        builder.append(", ");
+                    }
+                    builder.append("TYPE_TOUCH_INTERACTION_START");
+                    eventTypeCount++;
+                } break;
+                case TYPE_TOUCH_INTERACTION_END: {
+                    if (eventTypeCount > 0) {
+                        builder.append(", ");
+                    }
+                    builder.append("TYPE_TOUCH_INTERACTION_END");
+                    eventTypeCount++;
+                } break;
+            }
+        }
+        if (eventTypeCount > 1) {
+            builder.insert(0, '[');
+            builder.append(']');
+        }
+        return builder.toString();
     }
 
     /**
diff --git a/core/java/android/webkit/BrowserFrame.java b/core/java/android/webkit/BrowserFrame.java
index 4dbca23..6fb8bdf 100644
--- a/core/java/android/webkit/BrowserFrame.java
+++ b/core/java/android/webkit/BrowserFrame.java
@@ -226,8 +226,6 @@
             } else {
                 sJavaBridge.setCacheSize(4 * 1024 * 1024);
             }
-            // initialize CacheManager
-            CacheManager.init(appContext);
             // create CookieSyncManager with current Context
             CookieSyncManager.createInstance(appContext);
             // create PluginManager with current Context
diff --git a/core/java/android/webkit/CacheManager.java b/core/java/android/webkit/CacheManager.java
index 52f41e6..bbd3f2b 100644
--- a/core/java/android/webkit/CacheManager.java
+++ b/core/java/android/webkit/CacheManager.java
@@ -45,14 +45,6 @@
 // CacheManager may only be used if your activity contains a WebView.
 @Deprecated
 public final class CacheManager {
-
-    private static final String LOGTAG = "cache";
-
-    static final String HEADER_KEY_IFMODIFIEDSINCE = "if-modified-since";
-    static final String HEADER_KEY_IFNONEMATCH = "if-none-match";
-
-    private static File mBaseDir;
-    
     /**
      * Represents a resource stored in the HTTP cache. Instances of this class
      * can be obtained by calling
@@ -239,39 +231,23 @@
     }
 
     /**
-     * Initializes the HTTP cache. This method must be called before any
-     * CacheManager methods are used. Note that this is called automatically
-     * when a {@link WebView} is created.
-     *
-     * @param context the application context
-     */
-    static void init(Context context) {
-        // This isn't actually where the real cache lives, but where we put files for the
-        // purpose of getCacheFile().
-        mBaseDir = new File(context.getCacheDir(), "webviewCacheChromiumStaging");
-        if (!mBaseDir.exists()) {
-            mBaseDir.mkdirs();
-        }
-    }
-
-    /**
      * Gets the base directory in which the files used to store the contents of
      * cache entries are placed. See
      * {@link CacheManager.CacheResult#getLocalPath CacheManager.CacheResult.getLocalPath()}.
      *
      * @return the base directory of the cache
-     * @deprecated Access to the HTTP cache will be removed in a future release.
+     * @deprecated This method no longer has any effect and always returns null.
      */
     @Deprecated
     public static File getCacheFileBaseDir() {
-        return mBaseDir;
+        return null;
     }
 
     /**
      * Gets whether the HTTP cache is disabled.
      *
      * @return true if the HTTP cache is disabled
-     * @deprecated Access to the HTTP cache will be removed in a future release.
+     * @deprecated This method no longer has any effect and always returns false.
      */
     @Deprecated
     public static boolean cacheDisabled() {
@@ -314,73 +290,11 @@
      * @param headers a map from HTTP header name to value, to be populated
      *                for the returned cache entry
      * @return the cache entry for the specified URL
-     * @deprecated Access to the HTTP cache will be removed in a future release.
+     * @deprecated This method no longer has any effect and always returns null.
      */
     @Deprecated
     public static CacheResult getCacheFile(String url,
             Map<String, String> headers) {
-        return getCacheFile(url, 0, headers);
-    }
-
-    static CacheResult getCacheFile(String url, long postIdentifier,
-            Map<String, String> headers) {
-        CacheResult result = nativeGetCacheResult(url);
-        if (result == null) {
-            return null;
-        }
-        // A temporary local file will have been created native side and localPath set
-        // appropriately.
-        File src = new File(mBaseDir, result.localPath);
-        try {
-            // Open the file here so that even if it is deleted, the content
-            // is still readable by the caller until close() is called.
-            result.inStream = new FileInputStream(src);
-        } catch (FileNotFoundException e) {
-            Log.v(LOGTAG, "getCacheFile(): Failed to open file: " + e);
-            // TODO: The files in the cache directory can be removed by the
-            // system. If it is gone, what should we do?
-            return null;
-        }
-
-        // A null value for headers is used by CACHE_MODE_CACHE_ONLY to imply
-        // that we should provide the cache result even if it is expired.
-        // Note that a negative expires value means a time in the far future.
-        if (headers != null && result.expires >= 0
-                && result.expires <= System.currentTimeMillis()) {
-            if (result.lastModified == null && result.etag == null) {
-                return null;
-            }
-            // Return HEADER_KEY_IFNONEMATCH or HEADER_KEY_IFMODIFIEDSINCE
-            // for requesting validation.
-            if (result.etag != null) {
-                headers.put(HEADER_KEY_IFNONEMATCH, result.etag);
-            }
-            if (result.lastModified != null) {
-                headers.put(HEADER_KEY_IFMODIFIEDSINCE, result.lastModified);
-            }
-        }
-
-        if (DebugFlags.CACHE_MANAGER) {
-            Log.v(LOGTAG, "getCacheFile for url " + url);
-        }
-
-        return result;
-    }
-
-    /**
-     * Given a URL and its full headers, gets a CacheResult if a local cache
-     * can be stored. Otherwise returns null. The mimetype is passed in so that
-     * the function can use the mimetype that will be passed to WebCore which
-     * could be different from the mimetype defined in the headers.
-     * forceCache is for out-of-package callers to force creation of a
-     * CacheResult, and is used to supply surrogate responses for URL
-     * interception.
-     *
-     * @return a CacheResult for a given URL
-     */
-    static CacheResult createCacheFile(String url, int statusCode,
-            Headers headers, String mimeType, boolean forceCache) {
-        // This method is public but hidden. We break functionality.
         return null;
     }
 
@@ -424,36 +338,4 @@
         // use, we should already have thrown an exception above.
         assert false;
     }
-
-    /**
-     * Removes all cache files.
-     *
-     * @return whether the removal succeeded
-     */
-    static boolean removeAllCacheFiles() {
-        // delete cache files in a separate thread to not block UI.
-        final Runnable clearCache = new Runnable() {
-            public void run() {
-                // delete all cache files
-                try {
-                    String[] files = mBaseDir.list();
-                    // if mBaseDir doesn't exist, files can be null.
-                    if (files != null) {
-                        for (int i = 0; i < files.length; i++) {
-                            File f = new File(mBaseDir, files[i]);
-                            if (!f.delete()) {
-                                Log.e(LOGTAG, f.getPath() + " delete failed.");
-                            }
-                        }
-                    }
-                } catch (SecurityException e) {
-                    // Ignore SecurityExceptions.
-                }
-            }
-        };
-        new Thread(clearCache).start();
-        return true;
-    }
-
-    private static native CacheResult nativeGetCacheResult(String url);
 }
diff --git a/core/java/android/webkit/EventLogTags.logtags b/core/java/android/webkit/EventLogTags.logtags
index 082a437..b0b5493 100644
--- a/core/java/android/webkit/EventLogTags.logtags
+++ b/core/java/android/webkit/EventLogTags.logtags
@@ -8,4 +8,3 @@
 # 70103- used by the browser app itself
 
 70150 browser_snap_center
-70151 browser_text_size_change (oldSize|1|5), (newSize|1|5)
diff --git a/core/java/android/webkit/WebSettings.java b/core/java/android/webkit/WebSettings.java
index aa68904..7f6fa1a 100644
--- a/core/java/android/webkit/WebSettings.java
+++ b/core/java/android/webkit/WebSettings.java
@@ -89,6 +89,14 @@
         ZoomDensity(int size) {
             value = size;
         }
+
+        /**
+         * @hide Only for use by WebViewProvider implementations
+         */
+        public int getValue() {
+            return value;
+        }
+
         int value;
     }
 
@@ -936,6 +944,9 @@
      * access to content from other file scheme URLs. See
      * {@link #setAllowFileAccessFromFileURLs}. To enable the most restrictive,
      * and therefore secure policy, this setting should be disabled.
+     * Note that this setting affects only JavaScript access to file scheme
+     * resources. Other access to such resources, for example, from image HTML
+     * elements, is unaffected.
      * <p>
      * The default value is true for API level
      * {@link android.os.Build.VERSION_CODES#ICE_CREAM_SANDWICH_MR1} and below,
@@ -953,6 +964,9 @@
      * enable the most restrictive, and therefore secure policy, this setting
      * should be disabled. Note that the value of this setting is ignored if
      * the value of {@link #getAllowUniversalAccessFromFileURLs} is true.
+     * Note too, that this setting affects only JavaScript access to file scheme
+     * resources. Other access to such resources, for example, from image HTML
+     * elements, is unaffected.
      * <p>
      * The default value is true for API level
      * {@link android.os.Build.VERSION_CODES#ICE_CREAM_SANDWICH_MR1} and below,
@@ -1121,9 +1135,22 @@
     }
 
     /**
-     * Sets whether Geolocation is enabled. The default is true. See also
-     * {@link #setGeolocationDatabasePath} for how to correctly set up
-     * Geolocation.
+     * Sets whether Geolocation is enabled. The default is true.
+     * <p>
+     * Please note that in order for the Geolocation API to be usable
+     * by a page in the WebView, the following requirements must be met:
+     * <ul>
+     *   <li>an application must have permission to access the device location,
+     *   see {@link android.Manifest.permission#ACCESS_COARSE_LOCATION},
+     *   {@link android.Manifest.permission#ACCESS_FINE_LOCATION};
+     *   <li>an application must provide an implementation of the
+     *   {@link WebChromeClient#onGeolocationPermissionsShowPrompt} callback
+     *   to receive notifications that a page is requesting access to location
+     *   via the JavaScript Geolocation API.
+     * </ul>
+     * <p>
+     * As an option, it is possible to store previous locations and web origin
+     * permissions in a database. See {@link #setGeolocationDatabasePath}.
      *
      * @param flag whether Geolocation should be enabled
      */
@@ -1295,7 +1322,7 @@
      * and content is re-validated as needed. When navigating back, content is
      * not revalidated, instead the content is just retrieved from the cache.
      * This method allows the client to override this behavior by specifying
-     * one of {@link #LOAD_DEFAULT}, {@link #LOAD_NORMAL},
+     * one of {@link #LOAD_DEFAULT},
      * {@link #LOAD_CACHE_ELSE_NETWORK}, {@link #LOAD_NO_CACHE} or
      * {@link #LOAD_CACHE_ONLY}. The default value is {@link #LOAD_DEFAULT}.
      *
diff --git a/core/java/android/webkit/WebSettingsClassic.java b/core/java/android/webkit/WebSettingsClassic.java
index 1bbe7bb..e3d095f 100644
--- a/core/java/android/webkit/WebSettingsClassic.java
+++ b/core/java/android/webkit/WebSettingsClassic.java
@@ -647,10 +647,6 @@
     @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();
         }
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 6df7820..6aadaf9 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -2137,4 +2137,10 @@
         super.setLayerType(layerType, paint);
         mProvider.getViewDelegate().setLayerType(layerType, paint);
     }
+
+    @Override
+    protected void dispatchDraw(Canvas canvas) {
+        mProvider.getViewDelegate().preDispatchDraw(canvas);
+        super.dispatchDraw(canvas);
+    }
 }
diff --git a/core/java/android/webkit/WebViewClassic.java b/core/java/android/webkit/WebViewClassic.java
index ae56e6b..9a83964 100644
--- a/core/java/android/webkit/WebViewClassic.java
+++ b/core/java/android/webkit/WebViewClassic.java
@@ -8560,6 +8560,11 @@
         updateHwAccelerated();
     }
 
+    @Override
+    public void preDispatchDraw(Canvas canvas) {
+        // no-op for WebViewClassic.
+    }
+
     private void updateHwAccelerated() {
         if (mNativeClass == 0) {
             return;
diff --git a/core/java/android/webkit/WebViewClient.java b/core/java/android/webkit/WebViewClient.java
index 08a046a..556b2d2 100644
--- a/core/java/android/webkit/WebViewClient.java
+++ b/core/java/android/webkit/WebViewClient.java
@@ -31,6 +31,7 @@
      * proper handler for the url. If WebViewClient is provided, return true
      * means the host application handles the url, while return false means the
      * current WebView handles the url.
+     * This method is not called for requests using the POST "method".
      *
      * @param view The WebView that is initiating the callback.
      * @param url The url to be loaded.
@@ -82,9 +83,9 @@
      * Notify the host application of a resource request and allow the
      * application to return the data.  If the return value is null, the WebView
      * will continue to load the resource as usual.  Otherwise, the return
-     * response and data will be used.  NOTE: This method is called by the
-     * network thread so clients should exercise caution when accessing private
-     * data.
+     * response and data will be used.  NOTE: This method is called on a thread
+     * other than the UI thread so clients should exercise caution
+     * when accessing private data or the view system.
      *
      * @param view The {@link android.webkit.WebView} that is requesting the
      *             resource.
diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java
index 3fb3ec6..9e5a326 100644
--- a/core/java/android/webkit/WebViewCore.java
+++ b/core/java/android/webkit/WebViewCore.java
@@ -2001,9 +2001,6 @@
 
     private void clearCache(boolean includeDiskFiles) {
         mBrowserFrame.clearCache();
-        if (includeDiskFiles) {
-            CacheManager.removeAllCacheFiles();
-        }
     }
 
     private void loadUrl(String url, Map<String, String> extraHeaders) {
diff --git a/core/java/android/webkit/WebViewFactory.java b/core/java/android/webkit/WebViewFactory.java
index b833a01..18df0b1 100644
--- a/core/java/android/webkit/WebViewFactory.java
+++ b/core/java/android/webkit/WebViewFactory.java
@@ -31,7 +31,7 @@
     // TODO: When the Chromium powered WebView is ready, it should be the default factory class.
     private static final String DEFAULT_WEBVIEW_FACTORY = "android.webkit.WebViewClassic$Factory";
     private static final String CHROMIUM_WEBVIEW_FACTORY =
-            "com.android.webviewchromium.WebViewChromiumFactoryProvider";
+            "com.android.webview.chromium.WebViewChromiumFactoryProvider";
     private static final String CHROMIUM_WEBVIEW_JAR = "/system/framework/webviewchromium.jar";
 
     private static final String LOGTAG = "WebViewFactory";
diff --git a/core/java/android/webkit/WebViewProvider.java b/core/java/android/webkit/WebViewProvider.java
index c9f9fbd..1020634 100644
--- a/core/java/android/webkit/WebViewProvider.java
+++ b/core/java/android/webkit/WebViewProvider.java
@@ -341,6 +341,8 @@
         public void setBackgroundColor(int color);
 
         public void setLayerType(int layerType, Paint paint);
+
+        public void preDispatchDraw(Canvas canvas);
     }
 
     interface ScrollDelegate {
diff --git a/core/java/android/widget/CheckBox.java b/core/java/android/widget/CheckBox.java
index f1804f8..41ab5f2 100644
--- a/core/java/android/widget/CheckBox.java
+++ b/core/java/android/widget/CheckBox.java
@@ -20,6 +20,7 @@
 import android.util.AttributeSet;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityNodeInfo;
+import android.util.ValueModel;
 
 
 /**
@@ -55,7 +56,9 @@
  * {@link android.R.styleable#View View Attributes}
  * </p>
  */
-public class CheckBox extends CompoundButton {
+public class CheckBox extends CompoundButton implements ValueEditor<Boolean> {
+    private ValueModel<Boolean> mValueModel = ValueModel.EMPTY;
+
     public CheckBox(Context context) {
         this(context, null);
     }
@@ -79,4 +82,22 @@
         super.onInitializeAccessibilityNodeInfo(info);
         info.setClassName(CheckBox.class.getName());
     }
+
+    @Override
+    public ValueModel<Boolean> getValueModel() {
+        return mValueModel;
+    }
+
+    @Override
+    public void setValueModel(ValueModel<Boolean> valueModel) {
+        mValueModel = valueModel;
+        setChecked(mValueModel.get());
+    }
+
+    @Override
+    public boolean performClick() {
+        boolean handled = super.performClick();
+        mValueModel.set(isChecked());
+        return handled;
+    }
 }
diff --git a/core/java/android/widget/EditText.java b/core/java/android/widget/EditText.java
index 57e51c2..ec81214 100644
--- a/core/java/android/widget/EditText.java
+++ b/core/java/android/widget/EditText.java
@@ -17,6 +17,7 @@
 package android.widget;
 
 import android.content.Context;
+import android.graphics.Rect;
 import android.text.Editable;
 import android.text.Selection;
 import android.text.Spannable;
@@ -24,6 +25,7 @@
 import android.text.method.ArrowKeyMovementMethod;
 import android.text.method.MovementMethod;
 import android.util.AttributeSet;
+import android.util.ValueModel;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityNodeInfo;
 
@@ -47,7 +49,9 @@
  * {@link android.R.styleable#TextView TextView Attributes},
  * {@link android.R.styleable#View View Attributes}
  */
-public class EditText extends TextView {
+public class EditText extends TextView implements ValueEditor<CharSequence> {
+    private ValueModel<CharSequence> mValueModel = ValueModel.EMPTY;
+
     public EditText(Context context) {
         this(context, null);
     }
@@ -128,4 +132,21 @@
         super.onInitializeAccessibilityNodeInfo(info);
         info.setClassName(EditText.class.getName());
     }
+
+    @Override
+    public ValueModel<CharSequence> getValueModel() {
+        return mValueModel;
+    }
+
+    @Override
+    public void setValueModel(ValueModel<CharSequence> valueModel) {
+        mValueModel = valueModel;
+        setText(mValueModel.get());
+    }
+
+    @Override
+    void sendAfterTextChanged(Editable text) {
+        super.sendAfterTextChanged(text);
+        mValueModel.set(text);
+    }
 }
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index 85972c3..217bedb 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -2638,15 +2638,10 @@
                         suggestionStart, suggestionEnd).toString();
                 mTextView.replaceText_internal(spanStart, spanEnd, suggestion);
 
-                // Notify source IME of the suggestion pick. Do this before swaping texts.
-                if (!TextUtils.isEmpty(
-                        suggestionInfo.suggestionSpan.getNotificationTargetClassName())) {
-                    InputMethodManager imm = InputMethodManager.peekInstance();
-                    if (imm != null) {
-                        imm.notifySuggestionPicked(suggestionInfo.suggestionSpan, originalText,
-                                suggestionInfo.suggestionIndex);
-                    }
-                }
+                // Notify source IME of the suggestion pick. Do this before
+                // swaping texts.
+                suggestionInfo.suggestionSpan.notifySelection(
+                        mTextView.getContext(), originalText, suggestionInfo.suggestionIndex);
 
                 // Swap text content between actual text and Suggestion span
                 String[] suggestions = suggestionInfo.suggestionSpan.getSuggestions();
diff --git a/core/java/android/widget/GridLayout.java b/core/java/android/widget/GridLayout.java
index 772d748..85ed8db 100644
--- a/core/java/android/widget/GridLayout.java
+++ b/core/java/android/widget/GridLayout.java
@@ -605,7 +605,7 @@
     }
 
     private int getDefaultMargin(View c, boolean isAtEdge, boolean horizontal, boolean leading) {
-        return isAtEdge ? DEFAULT_CONTAINER_MARGIN : getDefaultMargin(c, horizontal, leading);
+        return /*isAtEdge ? DEFAULT_CONTAINER_MARGIN :*/ getDefaultMargin(c, horizontal, leading);
     }
 
     private int getDefaultMargin(View c, LayoutParams p, boolean horizontal, boolean leading) {
@@ -824,13 +824,11 @@
     // Draw grid
 
     private void drawLine(Canvas graphics, int x1, int y1, int x2, int y2, Paint paint) {
-        int dx = getPaddingLeft();
-        int dy = getPaddingTop();
         if (isLayoutRtl()) {
             int width = getWidth();
-            graphics.drawLine(width - dx - x1, dy + y1, width - dx - x2, dy + y2, paint);
+            graphics.drawLine(width - x1, y1, width - x2, y2, paint);
         } else {
-            graphics.drawLine(dx + x1, dy + y1, dx + x2, dy + y2, paint);
+            graphics.drawLine(x1, y1, x2, y2, paint);
         }
     }
 
@@ -838,18 +836,17 @@
      * @hide
      */
     @Override
-    protected void onDebugDrawMargins(Canvas canvas) {
+    protected void onDebugDrawMargins(Canvas canvas, Paint paint) {
         // Apply defaults, so as to remove UNDEFINED values
         LayoutParams lp = new LayoutParams();
         for (int i = 0; i < getChildCount(); i++) {
             View c = getChildAt(i);
-            Insets insets = getLayoutMode() == OPTICAL_BOUNDS ? c.getOpticalInsets() : Insets.NONE;
             lp.setMargins(
-                    getMargin1(c, true, true) - insets.left,
-                    getMargin1(c, false, true) - insets.top,
-                    getMargin1(c, true, false) - insets.right,
-                    getMargin1(c, false, false) - insets.bottom);
-            lp.onDebugDraw(c, canvas);
+                    getMargin1(c, true, true),
+                    getMargin1(c, false, true),
+                    getMargin1(c, true, false),
+                    getMargin1(c, false, false));
+            lp.onDebugDraw(c, canvas, paint);
         }
     }
 
@@ -858,26 +855,30 @@
      */
     @Override
     protected void onDebugDraw(Canvas canvas) {
-        int height = getHeight() - getPaddingTop() - getPaddingBottom();
-        int width = getWidth() - getPaddingLeft() - getPaddingRight();
-
         Paint paint = new Paint();
         paint.setStyle(Paint.Style.STROKE);
         paint.setColor(Color.argb(50, 255, 255, 255));
 
+        Insets insets = getOpticalInsets();
+
+        int top    =               getPaddingTop()    + insets.top;
+        int left   =               getPaddingLeft()   + insets.left;
+        int right  = getWidth()  - getPaddingRight()  - insets.right;
+        int bottom = getHeight() - getPaddingBottom() - insets.bottom;
+
         int[] xs = horizontalAxis.locations;
         if (xs != null) {
             for (int i = 0, length = xs.length; i < length; i++) {
-                int x = xs[i];
-                drawLine(canvas, x, 0, x, height - 1, paint);
+                int x = left + xs[i];
+                drawLine(canvas, x, top, x, bottom, paint);
             }
         }
 
         int[] ys = verticalAxis.locations;
         if (ys != null) {
             for (int i = 0, length = ys.length; i < length; i++) {
-                int y = ys[i];
-                drawLine(canvas, 0, y, width - 1, y, paint);
+                int y = top + ys[i];
+                drawLine(canvas, left, y, right, y, paint);
             }
         }
 
@@ -1013,12 +1014,7 @@
     }
 
     private int getMeasurement(View c, boolean horizontal) {
-        int result = horizontal ? c.getMeasuredWidth() : c.getMeasuredHeight();
-        if (getLayoutMode() == OPTICAL_BOUNDS) {
-            Insets insets = c.getOpticalInsets();
-            return result - (horizontal ? insets.left + insets.right : insets.top + insets.bottom);
-        }
-        return result;
+        return horizontal ? c.getMeasuredWidth() : c.getMeasuredHeight();
     }
 
     final int getMeasurementIncludingMargin(View c, boolean horizontal) {
@@ -1124,14 +1120,6 @@
                     targetWidth - width - paddingRight - rightMargin - dx;
             int cy = paddingTop + y1 + gravityOffsetY + alignmentOffsetY + topMargin;
 
-            boolean useLayoutBounds = getLayoutMode() == OPTICAL_BOUNDS;
-            if (useLayoutBounds) {
-                Insets insets = c.getOpticalInsets();
-                cx -= insets.left;
-                cy -= insets.top;
-                width += (insets.left + insets.right);
-                height += (insets.top + insets.bottom);
-            }
             if (width != c.getMeasuredWidth() || height != c.getMeasuredHeight()) {
                 c.measure(makeMeasureSpec(width, EXACTLY), makeMeasureSpec(height, EXACTLY));
             }
@@ -2418,6 +2406,8 @@
      *     <li> {@code spec.span = [start, start + size]} </li>
      *     <li> {@code spec.alignment = alignment} </li>
      * </ul>
+     * <p>
+     * To leave the start index undefined, use the value {@link #UNDEFINED}.
      *
      * @param start     the start
      * @param size      the size
@@ -2433,9 +2423,13 @@
      *     <li> {@code spec.span = [start, start + 1]} </li>
      *     <li> {@code spec.alignment = alignment} </li>
      * </ul>
+     * <p>
+     * To leave the start index undefined, use the value {@link #UNDEFINED}.
      *
      * @param start     the start index
      * @param alignment the alignment
+     *
+     * @see #spec(int, int, Alignment)
      */
     public static Spec spec(int start, Alignment alignment) {
         return spec(start, 1, alignment);
@@ -2446,9 +2440,13 @@
      * <ul>
      *     <li> {@code spec.span = [start, start + size]} </li>
      * </ul>
+     * <p>
+     * To leave the start index undefined, use the value {@link #UNDEFINED}.
      *
      * @param start     the start
      * @param size      the size
+     *
+     * @see #spec(int, Alignment)
      */
     public static Spec spec(int start, int size) {
         return spec(start, size, UNDEFINED_ALIGNMENT);
@@ -2459,8 +2457,12 @@
      * <ul>
      *     <li> {@code spec.span = [start, start + 1]} </li>
      * </ul>
+     * <p>
+     * To leave the start index undefined, use the value {@link #UNDEFINED}.
      *
      * @param start     the start index
+     *
+     * @see #spec(int, int)
      */
     public static Spec spec(int start) {
         return spec(start, 1);
@@ -2654,14 +2656,7 @@
         @Override
         public int getAlignmentValue(View view, int viewSize, int mode) {
             int baseline = view.getBaseline();
-            if (baseline == -1) {
-                return UNDEFINED;
-            } else {
-                if (mode == OPTICAL_BOUNDS) {
-                    return baseline - view.getOpticalInsets().top;
-                }
-                return baseline;
-            }
+            return baseline == -1 ? UNDEFINED : baseline;
         }
 
         @Override
diff --git a/core/java/android/widget/ImageView.java b/core/java/android/widget/ImageView.java
index 87396fb..1d465ce 100644
--- a/core/java/android/widget/ImageView.java
+++ b/core/java/android/widget/ImageView.java
@@ -789,6 +789,12 @@
                     if (resizeWidth) {
                         int newWidth = (int)(desiredAspect * (heightSize - ptop - pbottom)) +
                                 pleft + pright;
+
+                        // Allow the width to outgrow its original estimate if height is fixed.
+                        if (!resizeHeight) {
+                            widthSize = resolveAdjustedSize(newWidth, mMaxWidth, widthMeasureSpec);
+                        }
+
                         if (newWidth <= widthSize) {
                             widthSize = newWidth;
                             done = true;
@@ -799,6 +805,13 @@
                     if (!done && resizeHeight) {
                         int newHeight = (int)((widthSize - pleft - pright) / desiredAspect) +
                                 ptop + pbottom;
+
+                        // Allow the height to outgrow its original estimate if width is fixed.
+                        if (!resizeWidth) {
+                            heightSize = resolveAdjustedSize(newHeight, mMaxHeight,
+                                    heightMeasureSpec);
+                        }
+
                         if (newHeight <= heightSize) {
                             heightSize = newHeight;
                         }
diff --git a/core/java/android/widget/LinearLayout.java b/core/java/android/widget/LinearLayout.java
index b6f0862..ea8ee79 100644
--- a/core/java/android/widget/LinearLayout.java
+++ b/core/java/android/widget/LinearLayout.java
@@ -1431,9 +1431,9 @@
     @Override
     protected void onLayout(boolean changed, int l, int t, int r, int b) {
         if (mOrientation == VERTICAL) {
-            layoutVertical();
+            layoutVertical(l, t, r, b);
         } else {
-            layoutHorizontal();
+            layoutHorizontal(l, t, r, b);
         }
     }
 
@@ -1444,15 +1444,19 @@
      * @see #getOrientation()
      * @see #setOrientation(int)
      * @see #onLayout(boolean, int, int, int, int)
+     * @param left
+     * @param top
+     * @param right
+     * @param bottom
      */
-    void layoutVertical() {
+    void layoutVertical(int left, int top, int right, int bottom) {
         final int paddingLeft = mPaddingLeft;
 
         int childTop;
         int childLeft;
         
         // Where right end of child should go
-        final int width = mRight - mLeft;
+        final int width = right - left;
         int childRight = width - mPaddingRight;
         
         // Space available for child
@@ -1466,12 +1470,12 @@
         switch (majorGravity) {
            case Gravity.BOTTOM:
                // mTotalLength contains the padding already
-               childTop = mPaddingTop + mBottom - mTop - mTotalLength;
+               childTop = mPaddingTop + bottom - top - mTotalLength;
                break;
 
                // mTotalLength contains the padding already
            case Gravity.CENTER_VERTICAL:
-               childTop = mPaddingTop + (mBottom - mTop - mTotalLength) / 2;
+               childTop = mPaddingTop + (bottom - top - mTotalLength) / 2;
                break;
 
            case Gravity.TOP:
@@ -1534,8 +1538,12 @@
      * @see #getOrientation()
      * @see #setOrientation(int)
      * @see #onLayout(boolean, int, int, int, int)
+     * @param left
+     * @param top
+     * @param right
+     * @param bottom
      */
-    void layoutHorizontal() {
+    void layoutHorizontal(int left, int top, int right, int bottom) {
         final boolean isLayoutRtl = isLayoutRtl();
         final int paddingTop = mPaddingTop;
 
@@ -1543,7 +1551,7 @@
         int childLeft;
         
         // Where bottom of child should go
-        final int height = mBottom - mTop;
+        final int height = bottom - top;
         int childBottom = height - mPaddingBottom; 
         
         // Space available for child
@@ -1563,12 +1571,12 @@
         switch (Gravity.getAbsoluteGravity(majorGravity, layoutDirection)) {
             case Gravity.RIGHT:
                 // mTotalLength contains the padding already
-                childLeft = mPaddingLeft + mRight - mLeft - mTotalLength;
+                childLeft = mPaddingLeft + right - left - mTotalLength;
                 break;
 
             case Gravity.CENTER_HORIZONTAL:
                 // mTotalLength contains the padding already
-                childLeft = mPaddingLeft + (mRight - mLeft - mTotalLength) / 2;
+                childLeft = mPaddingLeft + (right - left - mTotalLength) / 2;
                 break;
 
             case Gravity.LEFT:
diff --git a/core/java/android/widget/MediaController.java b/core/java/android/widget/MediaController.java
index f76ab2b..ee1bf18 100644
--- a/core/java/android/widget/MediaController.java
+++ b/core/java/android/widget/MediaController.java
@@ -149,7 +149,7 @@
     private void initFloatingWindowLayout() {
         mDecorLayoutParams = new WindowManager.LayoutParams();
         WindowManager.LayoutParams p = mDecorLayoutParams;
-        p.gravity = Gravity.TOP;
+        p.gravity = Gravity.TOP | Gravity.LEFT;
         p.height = LayoutParams.WRAP_CONTENT;
         p.x = 0;
         p.format = PixelFormat.TRANSLUCENT;
@@ -167,9 +167,15 @@
         int [] anchorPos = new int[2];
         mAnchor.getLocationOnScreen(anchorPos);
 
+        // we need to know the size of the controller so we can properly position it
+        // within its space
+        mDecor.measure(MeasureSpec.makeMeasureSpec(mAnchor.getWidth(), MeasureSpec.AT_MOST),
+                MeasureSpec.makeMeasureSpec(mAnchor.getHeight(), MeasureSpec.AT_MOST));
+
         WindowManager.LayoutParams p = mDecorLayoutParams;
         p.width = mAnchor.getWidth();
-        p.y = anchorPos[1] + mAnchor.getHeight();
+        p.x = anchorPos[0] + (mAnchor.getWidth() - p.width) / 2;
+        p.y = anchorPos[1] + mAnchor.getHeight() - mDecor.getMeasuredHeight();
     }
 
     // This is called whenever mAnchor's layout bound changes
@@ -204,6 +210,8 @@
     /**
      * Set the view that acts as the anchor for the control view.
      * This can for example be a VideoView, or your Activity's main view.
+     * When VideoView calls this method, it will use the VideoView's parent
+     * as the anchor.
      * @param view The view to which to anchor the controller when it is visible.
      */
     public void setAnchorView(View view) {
diff --git a/core/java/android/widget/RelativeLayout.java b/core/java/android/widget/RelativeLayout.java
index e52e84d..3d1b6b3 100644
--- a/core/java/android/widget/RelativeLayout.java
+++ b/core/java/android/widget/RelativeLayout.java
@@ -369,10 +369,10 @@
         int width = 0;
         int height = 0;
 
-        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
-        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
-        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
-        int heightSize = MeasureSpec.getSize(heightMeasureSpec);
+        final int widthMode = MeasureSpec.getMode(widthMeasureSpec);
+        final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
+        final int widthSize = MeasureSpec.getSize(widthMeasureSpec);
+        final int heightSize = MeasureSpec.getSize(heightMeasureSpec);
 
         // Record our dimensions if they are known;
         if (widthMode != MeasureSpec.UNSPECIFIED) {
@@ -637,7 +637,12 @@
                 mPaddingLeft, mPaddingRight,
                 myWidth);
         int childHeightMeasureSpec;
-        if (params.width == LayoutParams.MATCH_PARENT) {
+        if (myHeight < 0) {
+            // Negative values in a mySize/myWidth/myWidth value in RelativeLayout measurement
+            // is code for, "we got an unspecified mode in the RelativeLayout's measurespec."
+            // Carry it forward.
+            childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
+        } else if (params.width == LayoutParams.MATCH_PARENT) {
             childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(myHeight, MeasureSpec.EXACTLY);
         } else {
             childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(myHeight, MeasureSpec.AT_MOST);
@@ -664,6 +669,13 @@
     private int getChildMeasureSpec(int childStart, int childEnd,
             int childSize, int startMargin, int endMargin, int startPadding,
             int endPadding, int mySize) {
+        if (mySize < 0) {
+            // Negative values in a mySize/myWidth/myWidth value in RelativeLayout measurement
+            // is code for, "we got an unspecified mode in the RelativeLayout's measurespec."
+            // Carry it forward.
+            return MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
+        }
+
         int childSpecMode = 0;
         int childSpecSize = 0;
 
diff --git a/core/java/android/widget/SeekBar.java b/core/java/android/widget/SeekBar.java
index 2737f94..a6486a8 100644
--- a/core/java/android/widget/SeekBar.java
+++ b/core/java/android/widget/SeekBar.java
@@ -18,6 +18,7 @@
 
 import android.content.Context;
 import android.util.AttributeSet;
+import android.util.ValueModel;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityNodeInfo;
 
@@ -33,7 +34,7 @@
  *
  * @attr ref android.R.styleable#SeekBar_thumb
  */
-public class SeekBar extends AbsSeekBar {
+public class SeekBar extends AbsSeekBar implements ValueEditor<Integer> {
 
     /**
      * A callback that notifies clients when the progress level has been
@@ -69,8 +70,9 @@
         void onStopTrackingTouch(SeekBar seekBar);
     }
 
+    private ValueModel<Integer> mValueModel = ValueModel.EMPTY;
     private OnSeekBarChangeListener mOnSeekBarChangeListener;
-    
+
     public SeekBar(Context context) {
         this(context, null);
     }
@@ -89,9 +91,23 @@
 
         if (mOnSeekBarChangeListener != null) {
             mOnSeekBarChangeListener.onProgressChanged(this, getProgress(), fromUser);
+            if (fromUser) {
+                mValueModel.set(getProgress());
+            }
         }
     }
 
+    @Override
+    public ValueModel<Integer> getValueModel() {
+        return mValueModel;
+    }
+
+    @Override
+    public void setValueModel(ValueModel<Integer> valueModel) {
+        mValueModel = valueModel;
+        setProgress(mValueModel.get());
+    }
+
     /**
      * Sets a listener to receive notifications of changes to the SeekBar's progress level. Also
      * provides notifications of when the user starts and stops a touch gesture within the SeekBar.
diff --git a/core/java/android/widget/TableLayout.java b/core/java/android/widget/TableLayout.java
index 399b4fa..f4b2ce0 100644
--- a/core/java/android/widget/TableLayout.java
+++ b/core/java/android/widget/TableLayout.java
@@ -445,7 +445,7 @@
     @Override
     protected void onLayout(boolean changed, int l, int t, int r, int b) {
         // enforce vertical layout
-        layoutVertical();
+        layoutVertical(l, t, r, b);
     }
 
     /**
diff --git a/core/java/android/widget/TableRow.java b/core/java/android/widget/TableRow.java
index 35927e0..fe3631a 100644
--- a/core/java/android/widget/TableRow.java
+++ b/core/java/android/widget/TableRow.java
@@ -120,7 +120,7 @@
     @Override
     protected void onLayout(boolean changed, int l, int t, int r, int b) {
         // enforce horizontal layout
-        layoutHorizontal();
+        layoutHorizontal(l, t, r, b);
     }
 
     /**
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 0a16a66..6f19f66 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -26,6 +26,7 @@
 import android.content.res.TypedArray;
 import android.content.res.XmlResourceParser;
 import android.graphics.Canvas;
+import android.graphics.Insets;
 import android.graphics.Paint;
 import android.graphics.Path;
 import android.graphics.Rect;
@@ -4349,6 +4350,14 @@
 
     /////////////////////////////////////////////////////////////////////////
 
+    private int getBoxHeight(Layout l) {
+        Insets opticalInsets = isLayoutModeOptical(mParent) ? getOpticalInsets() : Insets.NONE;
+        int padding = (l == mHintLayout) ?
+                getCompoundPaddingTop() + getCompoundPaddingBottom() :
+                getExtendedPaddingTop() + getExtendedPaddingBottom();
+        return getMeasuredHeight() - padding + opticalInsets.top + opticalInsets.bottom;
+    }
+
     int getVerticalOffset(boolean forceNormal) {
         int voffset = 0;
         final int gravity = mGravity & Gravity.VERTICAL_GRAVITY_MASK;
@@ -4359,15 +4368,7 @@
         }
 
         if (gravity != Gravity.TOP) {
-            int boxht;
-
-            if (l == mHintLayout) {
-                boxht = getMeasuredHeight() - getCompoundPaddingTop() -
-                        getCompoundPaddingBottom();
-            } else {
-                boxht = getMeasuredHeight() - getExtendedPaddingTop() -
-                        getExtendedPaddingBottom();
-            }
+            int boxht = getBoxHeight(l);
             int textht = l.getHeight();
 
             if (textht < boxht) {
@@ -4390,15 +4391,7 @@
         }
 
         if (gravity != Gravity.BOTTOM) {
-            int boxht;
-
-            if (l == mHintLayout) {
-                boxht = getMeasuredHeight() - getCompoundPaddingTop() -
-                        getCompoundPaddingBottom();
-            } else {
-                boxht = getMeasuredHeight() - getExtendedPaddingTop() -
-                        getExtendedPaddingBottom();
-            }
+            int boxht = getBoxHeight(l);
             int textht = l.getHeight();
 
             if (textht < boxht) {
@@ -5134,6 +5127,10 @@
             voffset = getVerticalOffset(true);
         }
 
+        if (isLayoutModeOptical(mParent)) {
+            voffset -= getOpticalInsets().top;
+        }
+
         return getExtendedPaddingTop() + voffset + mLayout.getLineBaseline(0);
     }
 
diff --git a/core/java/android/widget/ValueEditor.java b/core/java/android/widget/ValueEditor.java
new file mode 100755
index 0000000..2b91abf
--- /dev/null
+++ b/core/java/android/widget/ValueEditor.java
@@ -0,0 +1,53 @@
+/*
+ * 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.widget;
+
+import android.util.ValueModel;
+
+/**
+ * An interface for editors of simple values. Classes implementing this interface are normally
+ * UI controls (subclasses of {@link android.view.View View}) that can provide a suitable
+ * user interface to display and edit values of the specified type. This interface is
+ * intended to describe editors for simple types, like {@code boolean}, {@code int} or
+ * {@code String}, where the values themselves are immutable.
+ * <p>
+ * For example, {@link android.widget.CheckBox CheckBox} implements
+ * this interface for the Boolean type as it is capable of providing an appropriate
+ * mechanism for displaying and changing the value of a Boolean property.
+ *
+ * @param <T> the value type that this editor supports
+ */
+public interface ValueEditor<T> {
+    /**
+     * Return the last value model that was set. If no value model has been set, the editor
+     * should return the value {@link android.util.ValueModel#EMPTY}.
+     *
+     * @return the value model
+     */
+    public ValueModel<T> getValueModel();
+
+    /**
+     * Sets the value model for this editor. When the value model is set, the editor should
+     * retrieve the value from the value model, using {@link android.util.ValueModel#get()},
+     * and set its internal state accordingly. Likewise, when the editor's internal state changes
+     * it should update the value model by calling  {@link android.util.ValueModel#set(T)}
+     * with the appropriate value.
+     *
+     * @param valueModel the new value model for this editor.
+     */
+    public void setValueModel(ValueModel<T> valueModel);
+}
diff --git a/core/java/android/widget/VideoView.java b/core/java/android/widget/VideoView.java
index 7c8196d..05b11cf 100644
--- a/core/java/android/widget/VideoView.java
+++ b/core/java/android/widget/VideoView.java
@@ -35,6 +35,7 @@
 import android.view.SurfaceHolder;
 import android.view.SurfaceView;
 import android.view.View;
+import android.view.View.MeasureSpec;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityNodeInfo;
 import android.widget.MediaController.MediaPlayerControl;
@@ -108,23 +109,65 @@
 
     @Override
     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
-        //Log.i("@@@@", "onMeasure");
+        //Log.i("@@@@", "onMeasure(" + MeasureSpec.toString(widthMeasureSpec) + ", "
+        //        + MeasureSpec.toString(heightMeasureSpec) + ")");
+
         int width = getDefaultSize(mVideoWidth, widthMeasureSpec);
         int height = getDefaultSize(mVideoHeight, heightMeasureSpec);
         if (mVideoWidth > 0 && mVideoHeight > 0) {
-            if ( mVideoWidth * height  > width * mVideoHeight ) {
-                //Log.i("@@@", "image too tall, correcting");
+
+            int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);
+            int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec);
+            int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);
+            int heightSpecSize = MeasureSpec.getSize(heightMeasureSpec);
+
+            if (widthSpecMode == MeasureSpec.EXACTLY && heightSpecMode == MeasureSpec.EXACTLY) {
+                // the size is fixed
+                width = widthSpecSize;
+                height = heightSpecSize;
+
+                // for compatibility, we adjust size based on aspect ratio
+                if ( mVideoWidth * height  < width * mVideoHeight ) {
+                    //Log.i("@@@", "image too wide, correcting");
+                    width = height * mVideoWidth / mVideoHeight;
+                } else if ( mVideoWidth * height  > width * mVideoHeight ) {
+                    //Log.i("@@@", "image too tall, correcting");
+                    height = width * mVideoHeight / mVideoWidth;
+                }
+            } else if (widthSpecMode == MeasureSpec.EXACTLY) {
+                // only the width is fixed, adjust the height to match aspect ratio if possible
+                width = widthSpecSize;
                 height = width * mVideoHeight / mVideoWidth;
-            } else if ( mVideoWidth * height  < width * mVideoHeight ) {
-                //Log.i("@@@", "image too wide, correcting");
+                if (heightSpecMode == MeasureSpec.AT_MOST && height > heightSpecSize) {
+                    // couldn't match aspect ratio within the constraints
+                    height = heightSpecSize;
+                }
+            } else if (heightSpecMode == MeasureSpec.EXACTLY) {
+                // only the height is fixed, adjust the width to match aspect ratio if possible
+                height = heightSpecSize;
                 width = height * mVideoWidth / mVideoHeight;
+                if (widthSpecMode == MeasureSpec.AT_MOST && width > widthSpecSize) {
+                    // couldn't match aspect ratio within the constraints
+                    width = widthSpecSize;
+                }
             } else {
-                //Log.i("@@@", "aspect ratio is correct: " +
-                        //width+"/"+height+"="+
-                        //mVideoWidth+"/"+mVideoHeight);
+                // neither the width nor the height are fixed, try to use actual video size
+                width = mVideoWidth;
+                height = mVideoHeight;
+                if (heightSpecMode == MeasureSpec.AT_MOST && height > heightSpecSize) {
+                    // too tall, decrease both width and height
+                    height = heightSpecSize;
+                    width = height * mVideoWidth / mVideoHeight;
+                }
+                if (widthSpecMode == MeasureSpec.AT_MOST && width > widthSpecSize) {
+                    // too wide, decrease both width and height
+                    width = widthSpecSize;
+                    height = width * mVideoHeight / mVideoWidth;
+                }
             }
+        } else {
+            // no size yet, just adopt the given spec sizes
         }
-        //Log.i("@@@@@@@@@@", "setting size: " + width + 'x' + height);
         setMeasuredDimension(width, height);
     }
 
@@ -141,33 +184,8 @@
     }
 
     public int resolveAdjustedSize(int desiredSize, int measureSpec) {
-        int result = desiredSize;
-        int specMode = MeasureSpec.getMode(measureSpec);
-        int specSize =  MeasureSpec.getSize(measureSpec);
-
-        switch (specMode) {
-            case MeasureSpec.UNSPECIFIED:
-                /* Parent says we can be as big as we want. Just don't be larger
-                 * than max size imposed on ourselves.
-                 */
-                result = desiredSize;
-                break;
-
-            case MeasureSpec.AT_MOST:
-                /* Parent says we can be as big as we want, up to specSize.
-                 * Don't be larger than specSize, and don't be larger than
-                 * the max size imposed on ourselves.
-                 */
-                result = Math.min(desiredSize, specSize);
-                break;
-
-            case MeasureSpec.EXACTLY:
-                // No choice. Do what we are told.
-                result = specSize;
-                break;
-        }
-        return result;
-}
+        return getDefaultSize(desiredSize, measureSpec);
+    }
 
     private void initVideoView() {
         mVideoWidth = 0;
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index 9b95be1..d3ba11a 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -203,7 +203,6 @@
 	libicuuc \
 	libicui18n \
 	libmedia \
-	libmedia_native \
 	libwpa_client \
 	libjpeg \
 	libusbhost \
diff --git a/core/jni/android/graphics/BitmapFactory.cpp b/core/jni/android/graphics/BitmapFactory.cpp
index 8823328..1fb8c91 100644
--- a/core/jni/android/graphics/BitmapFactory.cpp
+++ b/core/jni/android/graphics/BitmapFactory.cpp
@@ -210,19 +210,28 @@
     JavaPixelAllocator javaAllocator(env);
 
     SkBitmap* bitmap;
+    bool useExistingBitmap = false;
     if (javaBitmap == NULL) {
         bitmap = new SkBitmap;
     } else {
         if (sampleSize != 1) {
             return nullObjectReturn("SkImageDecoder: Cannot reuse bitmap with sampleSize != 1");
         }
+
         bitmap = (SkBitmap*) env->GetIntField(javaBitmap, gBitmap_nativeBitmapFieldID);
-        // config of supplied bitmap overrules config set in options
-        prefConfig = bitmap->getConfig();
+        // only reuse the provided bitmap if it is immutable
+        if (!bitmap->isImmutable()) {
+            useExistingBitmap = true;
+            // config of supplied bitmap overrules config set in options
+            prefConfig = bitmap->getConfig();
+        } else {
+            ALOGW("Unable to reuse an immutable bitmap as an image decoder target.");
+            bitmap = new SkBitmap;
+        }
     }
 
     SkAutoTDelete<SkImageDecoder> add(decoder);
-    SkAutoTDelete<SkBitmap> adb(bitmap, javaBitmap == NULL);
+    SkAutoTDelete<SkBitmap> adb(bitmap, !useExistingBitmap);
 
     decoder->setPeeker(&peeker);
     if (!isPurgeable) {
@@ -383,7 +392,7 @@
     // detach bitmap from its autodeleter, since we want to own it now
     adb.detach();
 
-    if (javaBitmap != NULL) {
+    if (useExistingBitmap) {
         // If a java bitmap was passed in for reuse, pass it back
         return javaBitmap;
     }
diff --git a/core/jni/android/graphics/SurfaceTexture.cpp b/core/jni/android/graphics/SurfaceTexture.cpp
index c48b974..842c557 100644
--- a/core/jni/android/graphics/SurfaceTexture.cpp
+++ b/core/jni/android/graphics/SurfaceTexture.cpp
@@ -40,6 +40,7 @@
 
 struct fields_t {
     jfieldID  surfaceTexture;
+    jfieldID  frameAvailableListener;
     jmethodID postEvent;
 };
 static fields_t fields;
@@ -60,11 +61,25 @@
     env->SetIntField(thiz, fields.surfaceTexture, (int)surfaceTexture.get());
 }
 
-sp<SurfaceTexture> SurfaceTexture_getSurfaceTexture(JNIEnv* env, jobject thiz)
+static void SurfaceTexture_setFrameAvailableListener(JNIEnv* env,
+        jobject thiz, sp<SurfaceTexture::FrameAvailableListener> listener)
 {
-    sp<SurfaceTexture> surfaceTexture(
-        (SurfaceTexture*)env->GetIntField(thiz, fields.surfaceTexture));
-    return surfaceTexture;
+    SurfaceTexture::FrameAvailableListener* const p =
+        (SurfaceTexture::FrameAvailableListener*)
+            env->GetIntField(thiz, fields.frameAvailableListener);
+    if (listener.get()) {
+        listener->incStrong(thiz);
+    }
+    if (p) {
+        p->decStrong(thiz);
+    }
+    env->SetIntField(thiz, fields.frameAvailableListener, (int)listener.get());
+}
+
+sp<SurfaceTexture> SurfaceTexture_getSurfaceTexture(JNIEnv* env,
+        jobject thiz)
+{
+    return (SurfaceTexture*)env->GetIntField(thiz, fields.surfaceTexture);
 }
 
 sp<ANativeWindow> android_SurfaceTexture_getNativeWindow(
@@ -168,6 +183,12 @@
         ALOGE("can't find android/graphics/SurfaceTexture.%s",
                 ANDROID_GRAPHICS_SURFACETEXTURE_JNI_ID);
     }
+    fields.frameAvailableListener = env->GetFieldID(clazz,
+            ANDROID_GRAPHICS_FRAMEAVAILABLELISTENER_JNI_ID, "I");
+    if (fields.frameAvailableListener == NULL) {
+        ALOGE("can't find android/graphics/SurfaceTexture.%s",
+                ANDROID_GRAPHICS_FRAMEAVAILABLELISTENER_JNI_ID);
+    }
 
     fields.postEvent = env->GetStaticMethodID(clazz, "postEventFromNative",
             "(Ljava/lang/Object;)V");
@@ -197,12 +218,14 @@
     sp<JNISurfaceTextureContext> ctx(new JNISurfaceTextureContext(env, weakThiz,
             clazz));
     surfaceTexture->setFrameAvailableListener(ctx);
+    SurfaceTexture_setFrameAvailableListener(env, thiz, ctx);
 }
 
 static void SurfaceTexture_finalize(JNIEnv* env, jobject thiz)
 {
     sp<SurfaceTexture> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, thiz));
     surfaceTexture->setFrameAvailableListener(0);
+    SurfaceTexture_setFrameAvailableListener(env, thiz, 0);
     SurfaceTexture_setSurfaceTexture(env, thiz, 0);
 }
 
diff --git a/core/jni/android/graphics/TextLayoutCache.cpp b/core/jni/android/graphics/TextLayoutCache.cpp
index 4669c37..dce48a3 100644
--- a/core/jni/android/graphics/TextLayoutCache.cpp
+++ b/core/jni/android/graphics/TextLayoutCache.cpp
@@ -16,6 +16,8 @@
 
 #define LOG_TAG "TextLayoutCache"
 
+#include <utils/JenkinsHash.h>
+
 #include "TextLayoutCache.h"
 #include "TextLayout.h"
 #include "SkFontHost.h"
@@ -38,7 +40,7 @@
 
 TextLayoutCache::TextLayoutCache(TextLayoutShaper* shaper) :
         mShaper(shaper),
-        mCache(GenerationCache<TextLayoutCacheKey, sp<TextLayoutValue> >::kUnlimitedCapacity),
+        mCache(LruCache<TextLayoutCacheKey, sp<TextLayoutValue> >::kUnlimitedCapacity),
         mSize(0), mMaxSize(MB(DEFAULT_TEXT_LAYOUT_CACHE_SIZE_IN_MB)),
         mCacheHitCount(0), mNanosecondsSaved(0) {
     init();
@@ -199,11 +201,7 @@
     float remainingPercent = 100 * ((mMaxSize - mSize) / ((float)mMaxSize));
     float timeRunningInSec = (systemTime(SYSTEM_TIME_MONOTONIC) - mCacheStartTime) / 1000000000;
 
-    size_t bytes = 0;
     size_t cacheSize = mCache.size();
-    for (size_t i = 0; i < cacheSize; i++) {
-        bytes += mCache.getKeyAt(i).getSize() + mCache.getValueAt(i)->getSize();
-    }
 
     ALOGD("------------------------------------------------");
     ALOGD("Cache stats");
@@ -212,7 +210,7 @@
     ALOGD("running   : %.0f seconds", timeRunningInSec);
     ALOGD("entries   : %d", cacheSize);
     ALOGD("max size  : %d bytes", mMaxSize);
-    ALOGD("used      : %d bytes according to mSize, %d bytes actual", mSize, bytes);
+    ALOGD("used      : %d bytes according to mSize", mSize);
     ALOGD("remaining : %d bytes or %2.2f percent", mMaxSize - mSize, remainingPercent);
     ALOGD("hits      : %d", mCacheHitCount);
     ALOGD("saved     : %0.6f ms", mNanosecondsSaved * 0.000001f);
@@ -302,6 +300,23 @@
     return sizeof(TextLayoutCacheKey) + sizeof(UChar) * contextCount;
 }
 
+hash_t TextLayoutCacheKey::hash() const {
+    uint32_t hash = JenkinsHashMix(0, start);
+    hash = JenkinsHashMix(hash, count);
+    /* contextCount not needed because it's included in text, below */
+    hash = JenkinsHashMix(hash, hash_type(typeface));
+    hash = JenkinsHashMix(hash, hash_type(textSize));
+    hash = JenkinsHashMix(hash, hash_type(textSkewX));
+    hash = JenkinsHashMix(hash, hash_type(textScaleX));
+    hash = JenkinsHashMix(hash, flags);
+    hash = JenkinsHashMix(hash, hinting);
+    hash = JenkinsHashMix(hash, variant);
+    // Note: leaving out language is not problematic, as equality comparisons
+    // are still valid - the only bad thing that could happen is collisions.
+    hash = JenkinsHashMixShorts(hash, getText(), contextCount);
+    return JenkinsHashWhiten(hash);
+}
+
 /**
  * TextLayoutCacheValue
  */
diff --git a/core/jni/android/graphics/TextLayoutCache.h b/core/jni/android/graphics/TextLayoutCache.h
index 9994393..22de523 100644
--- a/core/jni/android/graphics/TextLayoutCache.h
+++ b/core/jni/android/graphics/TextLayoutCache.h
@@ -22,7 +22,7 @@
 #include <stddef.h>
 #include <utils/threads.h>
 #include <utils/String16.h>
-#include <utils/GenerationCache.h>
+#include <utils/LruCache.h>
 #include <utils/KeyedVector.h>
 #include <utils/Compare.h>
 #include <utils/RefBase.h>
@@ -85,6 +85,15 @@
 
     inline const UChar* getText() const { return textCopy.string(); }
 
+    bool operator==(const TextLayoutCacheKey& other) const {
+        return compare(*this, other) == 0;
+    }
+
+    bool operator!=(const TextLayoutCacheKey& other) const {
+        return compare(*this, other) != 0;
+    }
+
+    hash_t hash() const;
 private:
     String16 textCopy;
     size_t start;
@@ -110,6 +119,10 @@
     return TextLayoutCacheKey::compare(lhs, rhs);
 }
 
+inline hash_t hash_type(const TextLayoutCacheKey& key) {
+    return key.hash();
+}
+
 /*
  * TextLayoutValue is the Cache value
  */
@@ -276,7 +289,7 @@
     Mutex mLock;
     bool mInitialized;
 
-    GenerationCache<TextLayoutCacheKey, sp<TextLayoutValue> > mCache;
+    LruCache<TextLayoutCacheKey, sp<TextLayoutValue> > mCache;
 
     uint32_t mSize;
     uint32_t mMaxSize;
diff --git a/core/jni/android_hardware_Camera.cpp b/core/jni/android_hardware_Camera.cpp
index 67d831c..d39f565c 100644
--- a/core/jni/android_hardware_Camera.cpp
+++ b/core/jni/android_hardware_Camera.cpp
@@ -22,6 +22,7 @@
 #include "jni.h"
 #include "JNIHelp.h"
 #include "android_runtime/AndroidRuntime.h"
+#include <android_runtime/android_graphics_SurfaceTexture.h>
 
 #include <cutils/properties.h>
 #include <utils/Vector.h>
@@ -36,7 +37,6 @@
 struct fields_t {
     jfieldID    context;
     jfieldID    surface;
-    jfieldID    surfaceTexture;
     jfieldID    facing;
     jfieldID    orientation;
     jfieldID    canDisableShutterSound;
@@ -555,8 +555,8 @@
 
     sp<BufferQueue> bufferQueue = NULL;
     if (jSurfaceTexture != NULL) {
-        sp<SurfaceTexture> surfaceTexture = reinterpret_cast<SurfaceTexture*>(env->GetIntField(
-                jSurfaceTexture, fields.surfaceTexture));
+        sp<SurfaceTexture> surfaceTexture =
+            SurfaceTexture_getSurfaceTexture(env, jSurfaceTexture);
         if (surfaceTexture != NULL) {
             bufferQueue = surfaceTexture->getBufferQueue();
         }
@@ -966,8 +966,6 @@
     field fields_to_find[] = {
         { "android/hardware/Camera", "mNativeContext",   "I", &fields.context },
         { "android/view/Surface",    ANDROID_VIEW_SURFACE_JNI_ID, "I", &fields.surface },
-        { "android/graphics/SurfaceTexture",
-          ANDROID_GRAPHICS_SURFACETEXTURE_JNI_ID, "I", &fields.surfaceTexture },
         { "android/hardware/Camera$CameraInfo", "facing",   "I", &fields.facing },
         { "android/hardware/Camera$CameraInfo", "orientation",   "I", &fields.orientation },
         { "android/hardware/Camera$CameraInfo", "canDisableShutterSound",   "Z",
diff --git a/core/jni/android_media_AudioRecord.cpp b/core/jni/android_media_AudioRecord.cpp
index c76cb64..d6d5dde 100644
--- a/core/jni/android_media_AudioRecord.cpp
+++ b/core/jni/android_media_AudioRecord.cpp
@@ -511,7 +511,7 @@
     ALOGV(">> android_media_AudioRecord_get_min_buff_size(%d, %d, %d)",
           sampleRateInHertz, nbChannels, audioFormat);
 
-    int frameCount = 0;
+    size_t frameCount = 0;
     status_t result = AudioRecord::getMinFrameCount(&frameCount,
             sampleRateInHertz,
             (audioFormat == javaAudioRecordFields.PCM16 ?
diff --git a/core/jni/android_media_AudioTrack.cpp b/core/jni/android_media_AudioTrack.cpp
index 7e5263d..24e4cd7 100644
--- a/core/jni/android_media_AudioTrack.cpp
+++ b/core/jni/android_media_AudioTrack.cpp
@@ -206,8 +206,8 @@
 {
     ALOGV("sampleRate=%d, audioFormat(from Java)=%d, channel mask=%x, buffSize=%d",
         sampleRateInHertz, audioFormat, javaChannelMask, buffSizeInBytes);
-    int afSampleRate;
-    int afFrameCount;
+    uint32_t afSampleRate;
+    size_t afFrameCount;
 
     if (AudioSystem::getOutputFrameCount(&afFrameCount, (audio_stream_type_t) streamType) != NO_ERROR) {
         ALOGE("Error creating AudioTrack: Could not get AudioSystem frame count.");
@@ -750,7 +750,7 @@
 // ----------------------------------------------------------------------------
 static jint android_media_AudioTrack_get_output_sample_rate(JNIEnv *env,  jobject thiz,
         jint javaStreamType) {
-    int afSamplingRate;
+    uint32_t afSamplingRate;
     // convert the stream type from Java to native value
     // FIXME: code duplication with android_media_AudioTrack_native_setup()
     audio_stream_type_t nativeStreamType;
@@ -786,7 +786,7 @@
 static jint android_media_AudioTrack_get_min_buff_size(JNIEnv *env,  jobject thiz,
     jint sampleRateInHertz, jint nbChannels, jint audioFormat) {
 
-    int frameCount = 0;
+    size_t frameCount = 0;
     if (AudioTrack::getMinFrameCount(&frameCount, AUDIO_STREAM_DEFAULT,
             sampleRateInHertz) != NO_ERROR) {
         return -1;
diff --git a/core/jni/android_net_NetUtils.cpp b/core/jni/android_net_NetUtils.cpp
index 1f2b1ae..296add3 100644
--- a/core/jni/android_net_NetUtils.cpp
+++ b/core/jni/android_net_NetUtils.cpp
@@ -36,7 +36,8 @@
                     const char *dns2,
                     const char *server,
                     uint32_t *lease,
-                    const char *vendorInfo);
+                    const char *vendorInfo,
+                    const char *domains);
 
 int dhcp_do_request_renew(const char *ifname,
                     const char *ipaddr,
@@ -46,7 +47,8 @@
                     const char *dns2,
                     const char *server,
                     uint32_t *lease,
-                    const char *vendorInfo);
+                    const char *vendorInfo,
+                    const char *domains);
 
 int dhcp_stop(const char *ifname);
 int dhcp_release_lease(const char *ifname);
@@ -63,15 +65,16 @@
  * to look them up every time.
  */
 static struct fieldIds {
-    jmethodID constructorId;
-    jfieldID ipaddress;
-    jfieldID prefixLength;
-    jfieldID dns1;
-    jfieldID dns2;
-    jfieldID serverAddress;
-    jfieldID leaseDuration;
-    jfieldID vendorInfo;
-} dhcpInfoInternalFieldIds;
+    jmethodID clear;
+    jmethodID setInterfaceName;
+    jmethodID addLinkAddress;
+    jmethodID addGateway;
+    jmethodID addDns;
+    jmethodID setDomains;
+    jmethodID setServerAddress;
+    jmethodID setLeaseDuration;
+    jmethodID setVendorInfo;
+} dhcpResultsFieldIds;
 
 static jint android_net_utils_enableInterface(JNIEnv* env, jobject clazz, jstring ifname)
 {
@@ -109,7 +112,7 @@
 }
 
 static jboolean android_net_utils_runDhcpCommon(JNIEnv* env, jobject clazz, jstring ifname,
-        jobject info, bool renew)
+        jobject dhcpResults, bool renew)
 {
     int result;
     char  ipaddr[PROPERTY_VALUE_MAX];
@@ -120,56 +123,72 @@
     char  server[PROPERTY_VALUE_MAX];
     uint32_t lease;
     char vendorInfo[PROPERTY_VALUE_MAX];
+    char domains[PROPERTY_VALUE_MAX];
 
     const char *nameStr = env->GetStringUTFChars(ifname, NULL);
     if (nameStr == NULL) return (jboolean)false;
 
     if (renew) {
         result = ::dhcp_do_request_renew(nameStr, ipaddr, gateway, &prefixLength,
-                dns1, dns2, server, &lease, vendorInfo);
+                dns1, dns2, server, &lease, vendorInfo, domains);
     } else {
         result = ::dhcp_do_request(nameStr, ipaddr, gateway, &prefixLength,
-                dns1, dns2, server, &lease, vendorInfo);
+                dns1, dns2, server, &lease, vendorInfo, domains);
     }
-
     env->ReleaseStringUTFChars(ifname, nameStr);
     if (result == 0) {
-        env->SetObjectField(info, dhcpInfoInternalFieldIds.ipaddress, env->NewStringUTF(ipaddr));
+        env->CallVoidMethod(dhcpResults, dhcpResultsFieldIds.clear);
 
+        // set mIfaceName
+        // dhcpResults->setInterfaceName(ifname)
+        env->CallVoidMethod(dhcpResults, dhcpResultsFieldIds.setInterfaceName, ifname);
+
+        // set the linkAddress
+        // dhcpResults->addLinkAddress(inetAddress, prefixLength)
+        result = env->CallBooleanMethod(dhcpResults, dhcpResultsFieldIds.addLinkAddress,
+                env->NewStringUTF(ipaddr), prefixLength);
+    }
+
+    if (result == 0) {
         // set the gateway
-        jclass cls = env->FindClass("java/net/InetAddress");
-        jmethodID method = env->GetStaticMethodID(cls, "getByName",
-                "(Ljava/lang/String;)Ljava/net/InetAddress;");
-        jvalue args[1];
-        args[0].l = env->NewStringUTF(gateway);
-        jobject inetAddressObject = env->CallStaticObjectMethodA(cls, method, args);
+        // dhcpResults->addGateway(gateway)
+        result = env->CallBooleanMethod(dhcpResults,
+                dhcpResultsFieldIds.addGateway, env->NewStringUTF(gateway));
+    }
 
-        if (!env->ExceptionOccurred()) {
-            cls = env->FindClass("android/net/RouteInfo");
-            method = env->GetMethodID(cls, "<init>", "(Ljava/net/InetAddress;)V");
-            args[0].l = inetAddressObject;
-            jobject routeInfoObject = env->NewObjectA(cls, method, args);
+    if (result == 0) {
+        // dhcpResults->addDns(new InetAddress(dns1))
+        result = env->CallBooleanMethod(dhcpResults,
+                dhcpResultsFieldIds.addDns, env->NewStringUTF(dns1));
+    }
 
-            cls = env->FindClass("android/net/DhcpInfoInternal");
-            method = env->GetMethodID(cls, "addRoute", "(Landroid/net/RouteInfo;)V");
-            args[0].l = routeInfoObject;
-            env->CallVoidMethodA(info, method, args);
-        } else {
-            // if we have an exception (host not found perhaps), just don't add the route
-            env->ExceptionClear();
-        }
+    if (result == 0) {
+        env->CallVoidMethod(dhcpResults, dhcpResultsFieldIds.setDomains,
+                env->NewStringUTF(domains));
 
-        env->SetIntField(info, dhcpInfoInternalFieldIds.prefixLength, prefixLength);
-        env->SetObjectField(info, dhcpInfoInternalFieldIds.dns1, env->NewStringUTF(dns1));
-        env->SetObjectField(info, dhcpInfoInternalFieldIds.dns2, env->NewStringUTF(dns2));
-        env->SetObjectField(info, dhcpInfoInternalFieldIds.serverAddress,
+        result = env->CallBooleanMethod(dhcpResults,
+                dhcpResultsFieldIds.addDns, env->NewStringUTF(dns2));
+    }
+
+    if (result == 0) {
+        // dhcpResults->setServerAddress(new InetAddress(server))
+        result = env->CallBooleanMethod(dhcpResults, dhcpResultsFieldIds.setServerAddress,
                 env->NewStringUTF(server));
-        env->SetIntField(info, dhcpInfoInternalFieldIds.leaseDuration, lease);
-        env->SetObjectField(info, dhcpInfoInternalFieldIds.vendorInfo, env->NewStringUTF(vendorInfo));
+    }
+
+    if (result == 0) {
+        // dhcpResults->setLeaseDuration(lease)
+        env->CallVoidMethod(dhcpResults,
+                dhcpResultsFieldIds.setLeaseDuration, lease);
+
+        // dhcpResults->setVendorInfo(vendorInfo)
+        env->CallVoidMethod(dhcpResults, dhcpResultsFieldIds.setVendorInfo,
+                env->NewStringUTF(vendorInfo));
     }
     return (jboolean)(result == 0);
 }
 
+
 static jboolean android_net_utils_runDhcp(JNIEnv* env, jobject clazz, jstring ifname, jobject info)
 {
     return android_net_utils_runDhcpCommon(env, clazz, ifname, info, false);
@@ -217,8 +236,8 @@
     { "enableInterface", "(Ljava/lang/String;)I",  (void *)android_net_utils_enableInterface },
     { "disableInterface", "(Ljava/lang/String;)I",  (void *)android_net_utils_disableInterface },
     { "resetConnections", "(Ljava/lang/String;I)I",  (void *)android_net_utils_resetConnections },
-    { "runDhcp", "(Ljava/lang/String;Landroid/net/DhcpInfoInternal;)Z",  (void *)android_net_utils_runDhcp },
-    { "runDhcpRenew", "(Ljava/lang/String;Landroid/net/DhcpInfoInternal;)Z",  (void *)android_net_utils_runDhcpRenew },
+    { "runDhcp", "(Ljava/lang/String;Landroid/net/DhcpResults;)Z",  (void *)android_net_utils_runDhcp },
+    { "runDhcpRenew", "(Ljava/lang/String;Landroid/net/DhcpResults;)Z",  (void *)android_net_utils_runDhcpRenew },
     { "stopDhcp", "(Ljava/lang/String;)Z",  (void *)android_net_utils_stopDhcp },
     { "releaseDhcpLease", "(Ljava/lang/String;)Z",  (void *)android_net_utils_releaseDhcpLease },
     { "getDhcpError", "()Ljava/lang/String;", (void*) android_net_utils_getDhcpError },
@@ -226,16 +245,26 @@
 
 int register_android_net_NetworkUtils(JNIEnv* env)
 {
-    jclass dhcpInfoInternalClass = env->FindClass("android/net/DhcpInfoInternal");
-    LOG_FATAL_IF(dhcpInfoInternalClass == NULL, "Unable to find class android/net/DhcpInfoInternal");
-    dhcpInfoInternalFieldIds.constructorId = env->GetMethodID(dhcpInfoInternalClass, "<init>", "()V");
-    dhcpInfoInternalFieldIds.ipaddress = env->GetFieldID(dhcpInfoInternalClass, "ipAddress", "Ljava/lang/String;");
-    dhcpInfoInternalFieldIds.prefixLength = env->GetFieldID(dhcpInfoInternalClass, "prefixLength", "I");
-    dhcpInfoInternalFieldIds.dns1 = env->GetFieldID(dhcpInfoInternalClass, "dns1", "Ljava/lang/String;");
-    dhcpInfoInternalFieldIds.dns2 = env->GetFieldID(dhcpInfoInternalClass, "dns2", "Ljava/lang/String;");
-    dhcpInfoInternalFieldIds.serverAddress = env->GetFieldID(dhcpInfoInternalClass, "serverAddress", "Ljava/lang/String;");
-    dhcpInfoInternalFieldIds.leaseDuration = env->GetFieldID(dhcpInfoInternalClass, "leaseDuration", "I");
-    dhcpInfoInternalFieldIds.vendorInfo = env->GetFieldID(dhcpInfoInternalClass, "vendorInfo", "Ljava/lang/String;");
+    jclass dhcpResultsClass = env->FindClass("android/net/DhcpResults");
+    LOG_FATAL_IF(dhcpResultsClass == NULL, "Unable to find class android/net/DhcpResults");
+    dhcpResultsFieldIds.clear =
+            env->GetMethodID(dhcpResultsClass, "clear", "()V");
+    dhcpResultsFieldIds.setInterfaceName =
+            env->GetMethodID(dhcpResultsClass, "setInterfaceName", "(Ljava/lang/String;)V");
+    dhcpResultsFieldIds.addLinkAddress =
+            env->GetMethodID(dhcpResultsClass, "addLinkAddress", "(Ljava/lang/String;I)Z");
+    dhcpResultsFieldIds.addGateway =
+            env->GetMethodID(dhcpResultsClass, "addGateway", "(Ljava/lang/String;)Z");
+    dhcpResultsFieldIds.addDns =
+            env->GetMethodID(dhcpResultsClass, "addDns", "(Ljava/lang/String;)Z");
+    dhcpResultsFieldIds.setDomains =
+            env->GetMethodID(dhcpResultsClass, "setDomains", "(Ljava/lang/String;)V");
+    dhcpResultsFieldIds.setServerAddress =
+            env->GetMethodID(dhcpResultsClass, "setServerAddress", "(Ljava/lang/String;)Z");
+    dhcpResultsFieldIds.setLeaseDuration =
+            env->GetMethodID(dhcpResultsClass, "setLeaseDuration", "(I)V");
+    dhcpResultsFieldIds.setVendorInfo =
+            env->GetMethodID(dhcpResultsClass, "setVendorInfo", "(Ljava/lang/String;)V");
 
     return AndroidRuntime::registerNativeMethods(env,
             NETUTILS_PKG_NAME, gNetworkUtilMethods, NELEM(gNetworkUtilMethods));
diff --git a/core/jni/android_view_DisplayEventReceiver.cpp b/core/jni/android_view_DisplayEventReceiver.cpp
index 3d9d005..64fb27b 100644
--- a/core/jni/android_view_DisplayEventReceiver.cpp
+++ b/core/jni/android_view_DisplayEventReceiver.cpp
@@ -62,7 +62,7 @@
     bool mWaitingForVsync;
 
     virtual int handleEvent(int receiveFd, int events, void* data);
-    bool readLastVsyncMessage(nsecs_t* outTimestamp, int32_t* id, uint32_t* outCount);
+    bool processPendingEvents(nsecs_t* outTimestamp, int32_t* id, uint32_t* outCount);
     void dispatchVsync(nsecs_t timestamp, int32_t id, uint32_t count);
     void dispatchHotplug(nsecs_t timestamp, int32_t id, bool connected);
 };
@@ -111,7 +111,7 @@
         nsecs_t vsyncTimestamp;
         int32_t vsyncDisplayId;
         uint32_t vsyncCount;
-        readLastVsyncMessage(&vsyncTimestamp, &vsyncDisplayId, &vsyncCount);
+        processPendingEvents(&vsyncTimestamp, &vsyncDisplayId, &vsyncCount);
 
         status_t status = mReceiver.requestNextVsync();
         if (status) {
@@ -141,43 +141,47 @@
     nsecs_t vsyncTimestamp;
     int32_t vsyncDisplayId;
     uint32_t vsyncCount;
-    if (!readLastVsyncMessage(&vsyncTimestamp, &vsyncDisplayId, &vsyncCount)) {
-        ALOGV("receiver %p ~ Woke up but there was no vsync pulse!", this);
-        return 1; // keep the callback, did not obtain a vsync pulse
+    if (processPendingEvents(&vsyncTimestamp, &vsyncDisplayId, &vsyncCount)) {
+        ALOGV("receiver %p ~ Vsync pulse: timestamp=%lld, id=%d, count=%d",
+                this, vsyncTimestamp, vsyncDisplayId, vsyncCount);
+        mWaitingForVsync = false;
+        dispatchVsync(vsyncTimestamp, vsyncDisplayId, vsyncCount);
     }
 
-    ALOGV("receiver %p ~ Vsync pulse: timestamp=%lld, id=%d, count=%d",
-            this, vsyncTimestamp, vsyncDisplayId, vsyncCount);
-    mWaitingForVsync = false;
-
-    dispatchVsync(vsyncTimestamp, vsyncDisplayId, vsyncCount);
     return 1; // keep the callback
 }
 
-bool NativeDisplayEventReceiver::readLastVsyncMessage(
+bool NativeDisplayEventReceiver::processPendingEvents(
         nsecs_t* outTimestamp, int32_t* outId, uint32_t* outCount) {
+    bool gotVsync = false;
     DisplayEventReceiver::Event buf[EVENT_BUFFER_SIZE];
     ssize_t n;
     while ((n = mReceiver.getEvents(buf, EVENT_BUFFER_SIZE)) > 0) {
         ALOGV("receiver %p ~ Read %d events.", this, int(n));
-        while (n-- > 0) {
-            const DisplayEventReceiver::Event& ev = buf[n];
-            if (ev.header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) {
+        for (ssize_t i = 0; i < n; i++) {
+            const DisplayEventReceiver::Event& ev = buf[i];
+            switch (ev.header.type) {
+            case DisplayEventReceiver::DISPLAY_EVENT_VSYNC:
+                // Later vsync events will just overwrite the info from earlier
+                // ones. That's fine, we only care about the most recent.
+                gotVsync = true;
                 *outTimestamp = ev.header.timestamp;
                 *outId = ev.header.id;
                 *outCount = ev.vsync.count;
-                return true; // stop at last vsync in the buffer
-            }
-
-            if (ev.header.type == DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG) {
+                break;
+            case DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG:
                 dispatchHotplug(ev.header.timestamp, ev.header.id, ev.hotplug.connected);
+                break;
+            default:
+                ALOGW("receiver %p ~ ignoring unknown event type %#x", this, ev.header.type);
+                break;
             }
         }
     }
     if (n < 0) {
         ALOGW("Failed to get events from display event receiver, status=%d", status_t(n));
     }
-    return false;
+    return gotVsync;
 }
 
 void NativeDisplayEventReceiver::dispatchVsync(nsecs_t timestamp, int32_t id, uint32_t count) {
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index 0fa1b13..4d5a019 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -810,6 +810,7 @@
     <string name="lockscreen_access_pattern_cleared" msgid="5583479721001639579">"Patroon uitgevee"</string>
     <string name="lockscreen_access_pattern_cell_added" msgid="6756031208359292487">"Sel bygevoeg"</string>
     <string name="lockscreen_access_pattern_detected" msgid="4988730895554057058">"Patroon klaar"</string>
+    <string name="keyguard_accessibility_widget_changed" msgid="5678624624681400191">"%1$s. Legstuk %2$d van %3$d."</string>
     <string name="keyguard_accessibility_add_widget" msgid="8273277058724924654">"Voeg legstuk by."</string>
     <string name="keyguard_accessibility_widget_empty_slot" msgid="1281505703307930757">"Leeg"</string>
     <string name="keyguard_accessibility_unlock_area_expanded" msgid="2278106022311170299">"Ontsluitruimte uitgevou."</string>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index e326639..c929f96 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -810,6 +810,7 @@
     <string name="lockscreen_access_pattern_cleared" msgid="5583479721001639579">"ንድፍ ጸድቷል"</string>
     <string name="lockscreen_access_pattern_cell_added" msgid="6756031208359292487">"ሕዋስ ታክሏል"</string>
     <string name="lockscreen_access_pattern_detected" msgid="4988730895554057058">"ንድፍ ተጠናቋል"</string>
+    <string name="keyguard_accessibility_widget_changed" msgid="5678624624681400191">"%1$s። ምግብር %2$d ከ%3$d።"</string>
     <string name="keyguard_accessibility_add_widget" msgid="8273277058724924654">"ንዑስ ፕሮግራም አክል"</string>
     <string name="keyguard_accessibility_widget_empty_slot" msgid="1281505703307930757">"ባዶ"</string>
     <string name="keyguard_accessibility_unlock_area_expanded" msgid="2278106022311170299">"የመክፈቻ አካባቢ ተስፋፍቷል።"</string>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index 82902c4..7b40a26 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -810,6 +810,7 @@
     <string name="lockscreen_access_pattern_cleared" msgid="5583479721001639579">"تم محو النمط"</string>
     <string name="lockscreen_access_pattern_cell_added" msgid="6756031208359292487">"تمت إضافة الخلية"</string>
     <string name="lockscreen_access_pattern_detected" msgid="4988730895554057058">"اكتمل النمط"</string>
+    <string name="keyguard_accessibility_widget_changed" msgid="5678624624681400191">"%1$s. الأداة %2$d من %3$d."</string>
     <string name="keyguard_accessibility_add_widget" msgid="8273277058724924654">"إضافة أداة."</string>
     <string name="keyguard_accessibility_widget_empty_slot" msgid="1281505703307930757">"فارغة"</string>
     <string name="keyguard_accessibility_unlock_area_expanded" msgid="2278106022311170299">"تم توسيع منطقة إلغاء القفل."</string>
diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml
index 711dc46..adbcace 100644
--- a/core/res/res/values-be/strings.xml
+++ b/core/res/res/values-be/strings.xml
@@ -810,6 +810,7 @@
     <string name="lockscreen_access_pattern_cleared" msgid="5583479721001639579">"Ключ выдалены"</string>
     <string name="lockscreen_access_pattern_cell_added" msgid="6756031208359292487">"Сотавы дададзены"</string>
     <string name="lockscreen_access_pattern_detected" msgid="4988730895554057058">"Ключ завершаны"</string>
+    <string name="keyguard_accessibility_widget_changed" msgid="5678624624681400191">"%1$s. ВIджэт %2$d з %3$d."</string>
     <string name="keyguard_accessibility_add_widget" msgid="8273277058724924654">"Дадаць віджэт"</string>
     <string name="keyguard_accessibility_widget_empty_slot" msgid="1281505703307930757">"Пусты"</string>
     <string name="keyguard_accessibility_unlock_area_expanded" msgid="2278106022311170299">"Вобласць разблакіроўкі разгарнута."</string>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index 859614f..a3d9e76 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -810,6 +810,7 @@
     <string name="lockscreen_access_pattern_cleared" msgid="5583479721001639579">"Фигурата е изчистена"</string>
     <string name="lockscreen_access_pattern_cell_added" msgid="6756031208359292487">"Клетката е добавена"</string>
     <string name="lockscreen_access_pattern_detected" msgid="4988730895554057058">"Фигурата е завършена"</string>
+    <string name="keyguard_accessibility_widget_changed" msgid="5678624624681400191">"%1$s. Приспособление %2$d от %3$d."</string>
     <string name="keyguard_accessibility_add_widget" msgid="8273277058724924654">"Добавяне на приспособление."</string>
     <string name="keyguard_accessibility_widget_empty_slot" msgid="1281505703307930757">"Празно"</string>
     <string name="keyguard_accessibility_unlock_area_expanded" msgid="2278106022311170299">"Областта за отключване е разгъната."</string>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index 20ae9dd..212bff8 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -810,6 +810,7 @@
     <string name="lockscreen_access_pattern_cleared" msgid="5583479721001639579">"Patró esborrat"</string>
     <string name="lockscreen_access_pattern_cell_added" msgid="6756031208359292487">"S\'ha afegit una cel·la"</string>
     <string name="lockscreen_access_pattern_detected" msgid="4988730895554057058">"Patró completat"</string>
+    <string name="keyguard_accessibility_widget_changed" msgid="5678624624681400191">"%1$s. Widget %2$d de %3$d."</string>
     <string name="keyguard_accessibility_add_widget" msgid="8273277058724924654">"Afegeix un widget"</string>
     <string name="keyguard_accessibility_widget_empty_slot" msgid="1281505703307930757">"Buit"</string>
     <string name="keyguard_accessibility_unlock_area_expanded" msgid="2278106022311170299">"S\'ha ampliat l\'àrea de desbloqueig."</string>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index f5ccf1e..5710c25 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -810,6 +810,7 @@
     <string name="lockscreen_access_pattern_cleared" msgid="5583479721001639579">"Bezpečnostní gesto vymazáno"</string>
     <string name="lockscreen_access_pattern_cell_added" msgid="6756031208359292487">"Buňka přidána"</string>
     <string name="lockscreen_access_pattern_detected" msgid="4988730895554057058">"Bezpečnostní gesto dokončeno"</string>
+    <string name="keyguard_accessibility_widget_changed" msgid="5678624624681400191">"%1$s. Widget %2$d z %3$d."</string>
     <string name="keyguard_accessibility_add_widget" msgid="8273277058724924654">"Přidat widget"</string>
     <string name="keyguard_accessibility_widget_empty_slot" msgid="1281505703307930757">"Prázdné"</string>
     <string name="keyguard_accessibility_unlock_area_expanded" msgid="2278106022311170299">"Oblast odemknutí byla rozšířena."</string>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index a3dd19a..c139fae 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -810,6 +810,7 @@
     <string name="lockscreen_access_pattern_cleared" msgid="5583479721001639579">"Mønster er ryddet"</string>
     <string name="lockscreen_access_pattern_cell_added" msgid="6756031208359292487">"Celle er tilføjet"</string>
     <string name="lockscreen_access_pattern_detected" msgid="4988730895554057058">"Mønster er afsluttet"</string>
+    <string name="keyguard_accessibility_widget_changed" msgid="5678624624681400191">"%1$s. Widget %2$d af %3$d."</string>
     <string name="keyguard_accessibility_add_widget" msgid="8273277058724924654">"Tilføj widget."</string>
     <string name="keyguard_accessibility_widget_empty_slot" msgid="1281505703307930757">"Tom"</string>
     <string name="keyguard_accessibility_unlock_area_expanded" msgid="2278106022311170299">"Oplåsningsområdet er udvidet."</string>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index 48da500..a2082a2 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -810,6 +810,7 @@
     <string name="lockscreen_access_pattern_cleared" msgid="5583479721001639579">"Muster gelöscht"</string>
     <string name="lockscreen_access_pattern_cell_added" msgid="6756031208359292487">"Zelle hinzugefügt"</string>
     <string name="lockscreen_access_pattern_detected" msgid="4988730895554057058">"Muster abgeschlossen"</string>
+    <string name="keyguard_accessibility_widget_changed" msgid="5678624624681400191">"%1$s. Widget %2$d von %3$d."</string>
     <string name="keyguard_accessibility_add_widget" msgid="8273277058724924654">"Widget hinzufügen"</string>
     <string name="keyguard_accessibility_widget_empty_slot" msgid="1281505703307930757">"Leer"</string>
     <string name="keyguard_accessibility_unlock_area_expanded" msgid="2278106022311170299">"Entsperr-Bereich maximiert"</string>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index 9b35015..6322fd8 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -810,6 +810,7 @@
     <string name="lockscreen_access_pattern_cleared" msgid="5583479721001639579">"Το μοτίβο απαλείφθηκε"</string>
     <string name="lockscreen_access_pattern_cell_added" msgid="6756031208359292487">"Προστέθηκε κελί"</string>
     <string name="lockscreen_access_pattern_detected" msgid="4988730895554057058">"Το μοτίβο ολοκληρώθηκε"</string>
+    <string name="keyguard_accessibility_widget_changed" msgid="5678624624681400191">"%1$s. Γραφικό στοιχείο %2$d από %3$d."</string>
     <string name="keyguard_accessibility_add_widget" msgid="8273277058724924654">"Προσθήκη γραφικού στοιχείου"</string>
     <string name="keyguard_accessibility_widget_empty_slot" msgid="1281505703307930757">"Κενή"</string>
     <string name="keyguard_accessibility_unlock_area_expanded" msgid="2278106022311170299">"Ανάπτυξη της περιοχής ξεκλειδώματος."</string>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index 5ceae63..d4ee1e8 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -810,6 +810,7 @@
     <string name="lockscreen_access_pattern_cleared" msgid="5583479721001639579">"Pattern cleared"</string>
     <string name="lockscreen_access_pattern_cell_added" msgid="6756031208359292487">"Cell added"</string>
     <string name="lockscreen_access_pattern_detected" msgid="4988730895554057058">"Pattern completed"</string>
+    <string name="keyguard_accessibility_widget_changed" msgid="5678624624681400191">"%1$s. Widget %2$d of %3$d."</string>
     <string name="keyguard_accessibility_add_widget" msgid="8273277058724924654">"Add widget"</string>
     <string name="keyguard_accessibility_widget_empty_slot" msgid="1281505703307930757">"Empty"</string>
     <string name="keyguard_accessibility_unlock_area_expanded" msgid="2278106022311170299">"Unlock area expanded."</string>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index 648f1f6..79163fa 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -810,6 +810,7 @@
     <string name="lockscreen_access_pattern_cleared" msgid="5583479721001639579">"Se eliminó el patrón"</string>
     <string name="lockscreen_access_pattern_cell_added" msgid="6756031208359292487">"Se agregó una celda."</string>
     <string name="lockscreen_access_pattern_detected" msgid="4988730895554057058">"Se completó el patrón"</string>
+    <string name="keyguard_accessibility_widget_changed" msgid="5678624624681400191">"%1$s. Widget %2$d de %3$d"</string>
     <string name="keyguard_accessibility_add_widget" msgid="8273277058724924654">"Agregar widget"</string>
     <string name="keyguard_accessibility_widget_empty_slot" msgid="1281505703307930757">"Vacío"</string>
     <string name="keyguard_accessibility_unlock_area_expanded" msgid="2278106022311170299">"Área desbloqueada expandida."</string>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index fb8548d..953738e 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -810,6 +810,7 @@
     <string name="lockscreen_access_pattern_cleared" msgid="5583479721001639579">"Patrón borrado"</string>
     <string name="lockscreen_access_pattern_cell_added" msgid="6756031208359292487">"Se ha añadido una celda."</string>
     <string name="lockscreen_access_pattern_detected" msgid="4988730895554057058">"Patrón completado"</string>
+    <string name="keyguard_accessibility_widget_changed" msgid="5678624624681400191">"%1$s. Widget %2$d de %3$d"</string>
     <string name="keyguard_accessibility_add_widget" msgid="8273277058724924654">"Añadir widget"</string>
     <string name="keyguard_accessibility_widget_empty_slot" msgid="1281505703307930757">"Vacío"</string>
     <string name="keyguard_accessibility_unlock_area_expanded" msgid="2278106022311170299">"Área de desbloqueo ampliada"</string>
diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml
index 85167ce..bc6c5dc 100644
--- a/core/res/res/values-et/strings.xml
+++ b/core/res/res/values-et/strings.xml
@@ -810,6 +810,7 @@
     <string name="lockscreen_access_pattern_cleared" msgid="5583479721001639579">"Muster on kustutatud"</string>
     <string name="lockscreen_access_pattern_cell_added" msgid="6756031208359292487">"Lahter on lisatud"</string>
     <string name="lockscreen_access_pattern_detected" msgid="4988730895554057058">"Muster on valmis"</string>
+    <string name="keyguard_accessibility_widget_changed" msgid="5678624624681400191">"%1$s. Vidin %2$d/%3$d."</string>
     <string name="keyguard_accessibility_add_widget" msgid="8273277058724924654">"Vidina lisamine."</string>
     <string name="keyguard_accessibility_widget_empty_slot" msgid="1281505703307930757">"Tühi"</string>
     <string name="keyguard_accessibility_unlock_area_expanded" msgid="2278106022311170299">"Avamisala on laiendatud."</string>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index 95d3bfa..640b46a 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -810,6 +810,7 @@
     <string name="lockscreen_access_pattern_cleared" msgid="5583479721001639579">"الگو پاک شد"</string>
     <string name="lockscreen_access_pattern_cell_added" msgid="6756031208359292487">"سلول اضافه شد"</string>
     <string name="lockscreen_access_pattern_detected" msgid="4988730895554057058">"الگو تکمیل شد"</string>
+    <string name="keyguard_accessibility_widget_changed" msgid="5678624624681400191">"%1$s. ابزارک %2$d از %3$d."</string>
     <string name="keyguard_accessibility_add_widget" msgid="8273277058724924654">"ابزارک اضافه کنید."</string>
     <string name="keyguard_accessibility_widget_empty_slot" msgid="1281505703307930757">"خالی"</string>
     <string name="keyguard_accessibility_unlock_area_expanded" msgid="2278106022311170299">"منطقه بازگشایی گسترده شد."</string>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index 70f5dc5..8acf9c6 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -810,6 +810,7 @@
     <string name="lockscreen_access_pattern_cleared" msgid="5583479721001639579">"Kuvio tyhjennetty"</string>
     <string name="lockscreen_access_pattern_cell_added" msgid="6756031208359292487">"Solu lisätty"</string>
     <string name="lockscreen_access_pattern_detected" msgid="4988730895554057058">"Kuvio valmis"</string>
+    <string name="keyguard_accessibility_widget_changed" msgid="5678624624681400191">"%1$s. Widget %2$d/%3$d."</string>
     <string name="keyguard_accessibility_add_widget" msgid="8273277058724924654">"Lisää widget."</string>
     <string name="keyguard_accessibility_widget_empty_slot" msgid="1281505703307930757">"Tyhjä"</string>
     <string name="keyguard_accessibility_unlock_area_expanded" msgid="2278106022311170299">"Lukituksen poiston alue laajennettu."</string>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index c319c6d..bb39c1e 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -810,6 +810,7 @@
     <string name="lockscreen_access_pattern_cleared" msgid="5583479721001639579">"Schéma effacé."</string>
     <string name="lockscreen_access_pattern_cell_added" msgid="6756031208359292487">"Cellule ajoutée."</string>
     <string name="lockscreen_access_pattern_detected" msgid="4988730895554057058">"Schéma terminé."</string>
+    <string name="keyguard_accessibility_widget_changed" msgid="5678624624681400191">"%1$s. Widget %2$d sur %3$d."</string>
     <string name="keyguard_accessibility_add_widget" msgid="8273277058724924654">"Ajouter un widget"</string>
     <string name="keyguard_accessibility_widget_empty_slot" msgid="1281505703307930757">"Vide"</string>
     <string name="keyguard_accessibility_unlock_area_expanded" msgid="2278106022311170299">"Zone de déverrouillage développée."</string>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index f272ef4..d2234ec 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -810,6 +810,7 @@
     <string name="lockscreen_access_pattern_cleared" msgid="5583479721001639579">"प्रतिमान साफ़ किया गया"</string>
     <string name="lockscreen_access_pattern_cell_added" msgid="6756031208359292487">"कक्ष जोड़ा गया"</string>
     <string name="lockscreen_access_pattern_detected" msgid="4988730895554057058">"प्रतिमान पूरा किया गया"</string>
+    <string name="keyguard_accessibility_widget_changed" msgid="5678624624681400191">"%1$s. %3$d विजेट में से %2$d."</string>
     <string name="keyguard_accessibility_add_widget" msgid="8273277058724924654">"विजेट जोड़ें"</string>
     <string name="keyguard_accessibility_widget_empty_slot" msgid="1281505703307930757">"रिक्त"</string>
     <string name="keyguard_accessibility_unlock_area_expanded" msgid="2278106022311170299">"अनलॉक क्षेत्र को विस्तृत कर दिया गया."</string>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index c41bb1d..5964a32 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -810,6 +810,7 @@
     <string name="lockscreen_access_pattern_cleared" msgid="5583479721001639579">"Uzorak je obrisan"</string>
     <string name="lockscreen_access_pattern_cell_added" msgid="6756031208359292487">"Dodan je mobitel"</string>
     <string name="lockscreen_access_pattern_detected" msgid="4988730895554057058">"Uzorak je dovršen"</string>
+    <string name="keyguard_accessibility_widget_changed" msgid="5678624624681400191">"%1$s. Widget %2$d od %3$d."</string>
     <string name="keyguard_accessibility_add_widget" msgid="8273277058724924654">"Dodavanje widgeta."</string>
     <string name="keyguard_accessibility_widget_empty_slot" msgid="1281505703307930757">"Prazno"</string>
     <string name="keyguard_accessibility_unlock_area_expanded" msgid="2278106022311170299">"Područje za otključavanje prošireno je."</string>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index c53108c..7e0035b 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -810,6 +810,7 @@
     <string name="lockscreen_access_pattern_cleared" msgid="5583479721001639579">"Minta törölve"</string>
     <string name="lockscreen_access_pattern_cell_added" msgid="6756031208359292487">"Cella hozzáadva"</string>
     <string name="lockscreen_access_pattern_detected" msgid="4988730895554057058">"Minta befejezve"</string>
+    <string name="keyguard_accessibility_widget_changed" msgid="5678624624681400191">"%1$s. Modul %3$d/%2$d"</string>
     <string name="keyguard_accessibility_add_widget" msgid="8273277058724924654">"Modul hozzáadása."</string>
     <string name="keyguard_accessibility_widget_empty_slot" msgid="1281505703307930757">"Üres"</string>
     <string name="keyguard_accessibility_unlock_area_expanded" msgid="2278106022311170299">"Feloldási terület kiterjesztve."</string>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index d281e03..a4c6bc21 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -810,6 +810,7 @@
     <string name="lockscreen_access_pattern_cleared" msgid="5583479721001639579">"Pola dihapus"</string>
     <string name="lockscreen_access_pattern_cell_added" msgid="6756031208359292487">"Sel ditambahkan"</string>
     <string name="lockscreen_access_pattern_detected" msgid="4988730895554057058">"Pola selesai"</string>
+    <string name="keyguard_accessibility_widget_changed" msgid="5678624624681400191">"%1$s. Widget %2$d dari %3$d."</string>
     <string name="keyguard_accessibility_add_widget" msgid="8273277058724924654">"Tambahkan widget."</string>
     <string name="keyguard_accessibility_widget_empty_slot" msgid="1281505703307930757">"Kosong"</string>
     <string name="keyguard_accessibility_unlock_area_expanded" msgid="2278106022311170299">"Area buka kunci diluaskan."</string>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index 92e7c95..ab57809 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -810,6 +810,7 @@
     <string name="lockscreen_access_pattern_cleared" msgid="5583479721001639579">"Sequenza cancellata"</string>
     <string name="lockscreen_access_pattern_cell_added" msgid="6756031208359292487">"Cella aggiunta"</string>
     <string name="lockscreen_access_pattern_detected" msgid="4988730895554057058">"Sequenza completata"</string>
+    <string name="keyguard_accessibility_widget_changed" msgid="5678624624681400191">"%1$s. Widget %2$d di %3$d."</string>
     <string name="keyguard_accessibility_add_widget" msgid="8273277058724924654">"Aggiungi widget."</string>
     <string name="keyguard_accessibility_widget_empty_slot" msgid="1281505703307930757">"Vuoto"</string>
     <string name="keyguard_accessibility_unlock_area_expanded" msgid="2278106022311170299">"Area di sblocco estesa."</string>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index bfdca9f..76a2daa 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -810,6 +810,7 @@
     <string name="lockscreen_access_pattern_cleared" msgid="5583479721001639579">"התבנית נמחקה"</string>
     <string name="lockscreen_access_pattern_cell_added" msgid="6756031208359292487">"התא נוסף"</string>
     <string name="lockscreen_access_pattern_detected" msgid="4988730895554057058">"התבנית הושלמה"</string>
+    <string name="keyguard_accessibility_widget_changed" msgid="5678624624681400191">"%1$s. Widget %2$d מתוך %3$d."</string>
     <string name="keyguard_accessibility_add_widget" msgid="8273277058724924654">"הוסף Widget."</string>
     <string name="keyguard_accessibility_widget_empty_slot" msgid="1281505703307930757">"ריק"</string>
     <string name="keyguard_accessibility_unlock_area_expanded" msgid="2278106022311170299">"אזור ביטול הנעילה הורחב."</string>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index 02126f0..a2d831a 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -810,6 +810,7 @@
     <string name="lockscreen_access_pattern_cleared" msgid="5583479721001639579">"パターンを消去しました"</string>
     <string name="lockscreen_access_pattern_cell_added" msgid="6756031208359292487">"セルを追加しました"</string>
     <string name="lockscreen_access_pattern_detected" msgid="4988730895554057058">"パターンの描画が完了しました"</string>
+    <string name="keyguard_accessibility_widget_changed" msgid="5678624624681400191">"%1$s。ウィジェット%2$d/%3$d。"</string>
     <string name="keyguard_accessibility_add_widget" msgid="8273277058724924654">"ウィジェットを追加します。"</string>
     <string name="keyguard_accessibility_widget_empty_slot" msgid="1281505703307930757">"なし"</string>
     <string name="keyguard_accessibility_unlock_area_expanded" msgid="2278106022311170299">"ロック解除エリアを拡大しました。"</string>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index 6bdb5d7..ff0f5d4 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -810,6 +810,7 @@
     <string name="lockscreen_access_pattern_cleared" msgid="5583479721001639579">"패턴 삭제"</string>
     <string name="lockscreen_access_pattern_cell_added" msgid="6756031208359292487">"셀 추가됨"</string>
     <string name="lockscreen_access_pattern_detected" msgid="4988730895554057058">"패턴 완료"</string>
+    <string name="keyguard_accessibility_widget_changed" msgid="5678624624681400191">"%1$s. %3$d의 위젯 %2$d."</string>
     <string name="keyguard_accessibility_add_widget" msgid="8273277058724924654">"위젯 추가"</string>
     <string name="keyguard_accessibility_widget_empty_slot" msgid="1281505703307930757">"비어 있음"</string>
     <string name="keyguard_accessibility_unlock_area_expanded" msgid="2278106022311170299">"잠금 해제 영역 확장됨"</string>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index 3e3c396..0b25abe 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -810,6 +810,7 @@
     <string name="lockscreen_access_pattern_cleared" msgid="5583479721001639579">"Šablonas išvalytas"</string>
     <string name="lockscreen_access_pattern_cell_added" msgid="6756031208359292487">"Pridėtas langelis"</string>
     <string name="lockscreen_access_pattern_detected" msgid="4988730895554057058">"Šablonas užbaigtas"</string>
+    <string name="keyguard_accessibility_widget_changed" msgid="5678624624681400191">"%1$s. %2$d valdiklis iš %3$d."</string>
     <string name="keyguard_accessibility_add_widget" msgid="8273277058724924654">"Pridėti valdiklį."</string>
     <string name="keyguard_accessibility_widget_empty_slot" msgid="1281505703307930757">"Tuščia"</string>
     <string name="keyguard_accessibility_unlock_area_expanded" msgid="2278106022311170299">"Atrakinimo sritis išplėsta."</string>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index dc4312f..3ef2f61 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -810,6 +810,7 @@
     <string name="lockscreen_access_pattern_cleared" msgid="5583479721001639579">"Kombinācija notīrīta"</string>
     <string name="lockscreen_access_pattern_cell_added" msgid="6756031208359292487">"Šūna pievienota"</string>
     <string name="lockscreen_access_pattern_detected" msgid="4988730895554057058">"Kombinācija pabeigta"</string>
+    <string name="keyguard_accessibility_widget_changed" msgid="5678624624681400191">"%1$s. %2$d. logrīks no %3$d."</string>
     <string name="keyguard_accessibility_add_widget" msgid="8273277058724924654">"Pievienot logrīku."</string>
     <string name="keyguard_accessibility_widget_empty_slot" msgid="1281505703307930757">"Tukšs"</string>
     <string name="keyguard_accessibility_unlock_area_expanded" msgid="2278106022311170299">"Atbloķēšanas apgabals ir izvērsts."</string>
diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml
index 5e649a7..4346a39 100644
--- a/core/res/res/values-ms/strings.xml
+++ b/core/res/res/values-ms/strings.xml
@@ -810,6 +810,7 @@
     <string name="lockscreen_access_pattern_cleared" msgid="5583479721001639579">"Corak dipadamkan"</string>
     <string name="lockscreen_access_pattern_cell_added" msgid="6756031208359292487">"Sel ditambahkan"</string>
     <string name="lockscreen_access_pattern_detected" msgid="4988730895554057058">"Corak siap"</string>
+    <string name="keyguard_accessibility_widget_changed" msgid="5678624624681400191">"%1$s. Widget %2$d dari %3$d."</string>
     <string name="keyguard_accessibility_add_widget" msgid="8273277058724924654">"Tambah widget."</string>
     <string name="keyguard_accessibility_widget_empty_slot" msgid="1281505703307930757">"Kosong"</string>
     <string name="keyguard_accessibility_unlock_area_expanded" msgid="2278106022311170299">"Bahagian buka kunci dikembangkan."</string>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index 79cf1ea..a5e473b 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -810,6 +810,7 @@
     <string name="lockscreen_access_pattern_cleared" msgid="5583479721001639579">"Mønsteret er slettet"</string>
     <string name="lockscreen_access_pattern_cell_added" msgid="6756031208359292487">"Celle er lagt til"</string>
     <string name="lockscreen_access_pattern_detected" msgid="4988730895554057058">"Mønsteret er fullført"</string>
+    <string name="keyguard_accessibility_widget_changed" msgid="5678624624681400191">"%1$s. Modul %2$d av %3$d."</string>
     <string name="keyguard_accessibility_add_widget" msgid="8273277058724924654">"Legg til modul."</string>
     <string name="keyguard_accessibility_widget_empty_slot" msgid="1281505703307930757">"Tom"</string>
     <string name="keyguard_accessibility_unlock_area_expanded" msgid="2278106022311170299">"Opplåsingsfeltet vises."</string>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 50b3a87..ec6d073 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -810,6 +810,7 @@
     <string name="lockscreen_access_pattern_cleared" msgid="5583479721001639579">"Patroon gewist"</string>
     <string name="lockscreen_access_pattern_cell_added" msgid="6756031208359292487">"Cel toegevoegd"</string>
     <string name="lockscreen_access_pattern_detected" msgid="4988730895554057058">"Patroon voltooid"</string>
+    <string name="keyguard_accessibility_widget_changed" msgid="5678624624681400191">"%1$s. Widget %2$d van %3$d."</string>
     <string name="keyguard_accessibility_add_widget" msgid="8273277058724924654">"Widget toevoegen."</string>
     <string name="keyguard_accessibility_widget_empty_slot" msgid="1281505703307930757">"Leeg"</string>
     <string name="keyguard_accessibility_unlock_area_expanded" msgid="2278106022311170299">"Ontgrendelingsgebied uitgevouwen."</string>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index 3a9a0f6..281b782 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -810,6 +810,7 @@
     <string name="lockscreen_access_pattern_cleared" msgid="5583479721001639579">"Wzór wyczyszczony"</string>
     <string name="lockscreen_access_pattern_cell_added" msgid="6756031208359292487">"Dodano komórkę."</string>
     <string name="lockscreen_access_pattern_detected" msgid="4988730895554057058">"Wzór ukończony"</string>
+    <string name="keyguard_accessibility_widget_changed" msgid="5678624624681400191">"%1$s. Widżet %2$d z %3$d."</string>
     <string name="keyguard_accessibility_add_widget" msgid="8273277058724924654">"Dodaj widżet."</string>
     <string name="keyguard_accessibility_widget_empty_slot" msgid="1281505703307930757">"Puste"</string>
     <string name="keyguard_accessibility_unlock_area_expanded" msgid="2278106022311170299">"Rozwinięto obszar odblokowania."</string>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index f1ac978..50adccc 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -810,6 +810,7 @@
     <string name="lockscreen_access_pattern_cleared" msgid="5583479721001639579">"Sequência apagada"</string>
     <string name="lockscreen_access_pattern_cell_added" msgid="6756031208359292487">"Célula adicionada"</string>
     <string name="lockscreen_access_pattern_detected" msgid="4988730895554057058">"Sequência concluída"</string>
+    <string name="keyguard_accessibility_widget_changed" msgid="5678624624681400191">"%1$s. Widget %2$d de %3$d."</string>
     <string name="keyguard_accessibility_add_widget" msgid="8273277058724924654">"Adicionar widget."</string>
     <string name="keyguard_accessibility_widget_empty_slot" msgid="1281505703307930757">"Vazio"</string>
     <string name="keyguard_accessibility_unlock_area_expanded" msgid="2278106022311170299">"Área de desbloqueio expandida."</string>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index d4dd494..1ba453c 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -810,6 +810,7 @@
     <string name="lockscreen_access_pattern_cleared" msgid="5583479721001639579">"Padrão apagado"</string>
     <string name="lockscreen_access_pattern_cell_added" msgid="6756031208359292487">"Célula adicionada"</string>
     <string name="lockscreen_access_pattern_detected" msgid="4988730895554057058">"Padrão concluído"</string>
+    <string name="keyguard_accessibility_widget_changed" msgid="5678624624681400191">"%1$s. Widget %2$d de %3$d."</string>
     <string name="keyguard_accessibility_add_widget" msgid="8273277058724924654">"Adicionar widget"</string>
     <string name="keyguard_accessibility_widget_empty_slot" msgid="1281505703307930757">"Vazio"</string>
     <string name="keyguard_accessibility_unlock_area_expanded" msgid="2278106022311170299">"Área de desbloqueio expandida."</string>
diff --git a/core/res/res/values-rm/strings.xml b/core/res/res/values-rm/strings.xml
index d3efd7e..79997db 100644
--- a/core/res/res/values-rm/strings.xml
+++ b/core/res/res/values-rm/strings.xml
@@ -1298,6 +1298,8 @@
     <skip />
     <!-- no translation found for lockscreen_access_pattern_detected (4988730895554057058) -->
     <skip />
+    <!-- no translation found for keyguard_accessibility_widget_changed (5678624624681400191) -->
+    <skip />
     <!-- no translation found for keyguard_accessibility_add_widget (8273277058724924654) -->
     <skip />
     <!-- no translation found for keyguard_accessibility_widget_empty_slot (1281505703307930757) -->
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index d0ef774..76a64b9 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -810,6 +810,7 @@
     <string name="lockscreen_access_pattern_cleared" msgid="5583479721001639579">"Modelul a fost şters"</string>
     <string name="lockscreen_access_pattern_cell_added" msgid="6756031208359292487">"Celulă adăugată"</string>
     <string name="lockscreen_access_pattern_detected" msgid="4988730895554057058">"Modelul a fost desenat"</string>
+    <string name="keyguard_accessibility_widget_changed" msgid="5678624624681400191">"%1$s. Widget %2$d din %3$d."</string>
     <string name="keyguard_accessibility_add_widget" msgid="8273277058724924654">"Adăugaţi un widget."</string>
     <string name="keyguard_accessibility_widget_empty_slot" msgid="1281505703307930757">"Gol"</string>
     <string name="keyguard_accessibility_unlock_area_expanded" msgid="2278106022311170299">"Zona de deblocare a fost extinsă."</string>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index 9314866..906217d 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -810,6 +810,7 @@
     <string name="lockscreen_access_pattern_cleared" msgid="5583479721001639579">"Графический ключ сброшен"</string>
     <string name="lockscreen_access_pattern_cell_added" msgid="6756031208359292487">"Ячейка добавлена"</string>
     <string name="lockscreen_access_pattern_detected" msgid="4988730895554057058">"Графический ключ введен"</string>
+    <string name="keyguard_accessibility_widget_changed" msgid="5678624624681400191">"%1$s. Виджет %2$d из %3$d."</string>
     <string name="keyguard_accessibility_add_widget" msgid="8273277058724924654">"Добавить виджет"</string>
     <string name="keyguard_accessibility_widget_empty_slot" msgid="1281505703307930757">"Пусто"</string>
     <string name="keyguard_accessibility_unlock_area_expanded" msgid="2278106022311170299">"Область разблокировки развернута"</string>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index 12a3b8f..75daa0b 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -810,6 +810,7 @@
     <string name="lockscreen_access_pattern_cleared" msgid="5583479721001639579">"Bezpečnostný vzor bol vymazaný"</string>
     <string name="lockscreen_access_pattern_cell_added" msgid="6756031208359292487">"Bunka bola pridaná"</string>
     <string name="lockscreen_access_pattern_detected" msgid="4988730895554057058">"Bezpečnostný vzor bol dokončený"</string>
+    <string name="keyguard_accessibility_widget_changed" msgid="5678624624681400191">"%1$s. Miniaplikácia %2$d z %3$d."</string>
     <string name="keyguard_accessibility_add_widget" msgid="8273277058724924654">"Pridať miniaplikáciu."</string>
     <string name="keyguard_accessibility_widget_empty_slot" msgid="1281505703307930757">"Prázdne"</string>
     <string name="keyguard_accessibility_unlock_area_expanded" msgid="2278106022311170299">"Oblasť na odomknutie bola rozšírená."</string>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index 3e9273d..bef7237 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -810,6 +810,7 @@
     <string name="lockscreen_access_pattern_cleared" msgid="5583479721001639579">"Vzorec je izbrisan"</string>
     <string name="lockscreen_access_pattern_cell_added" msgid="6756031208359292487">"Celica je dodana"</string>
     <string name="lockscreen_access_pattern_detected" msgid="4988730895554057058">"Vzorec je končan"</string>
+    <string name="keyguard_accessibility_widget_changed" msgid="5678624624681400191">"%1$s. Pripomoček %2$d za %3$d."</string>
     <string name="keyguard_accessibility_add_widget" msgid="8273277058724924654">"Dodajanje pripomočka."</string>
     <string name="keyguard_accessibility_widget_empty_slot" msgid="1281505703307930757">"Prazno"</string>
     <string name="keyguard_accessibility_unlock_area_expanded" msgid="2278106022311170299">"Območje odklepanja razširjeno."</string>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index 53604f1..afb669f 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -810,6 +810,7 @@
     <string name="lockscreen_access_pattern_cleared" msgid="5583479721001639579">"Образац је обрисан"</string>
     <string name="lockscreen_access_pattern_cell_added" msgid="6756031208359292487">"Ћелија је додата"</string>
     <string name="lockscreen_access_pattern_detected" msgid="4988730895554057058">"Образац је довршен"</string>
+    <string name="keyguard_accessibility_widget_changed" msgid="5678624624681400191">"%1$s. Виџет %2$d од %3$d."</string>
     <string name="keyguard_accessibility_add_widget" msgid="8273277058724924654">"Додај виџет."</string>
     <string name="keyguard_accessibility_widget_empty_slot" msgid="1281505703307930757">"Празно"</string>
     <string name="keyguard_accessibility_unlock_area_expanded" msgid="2278106022311170299">"Област откључавања је проширена."</string>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index d6a8eeb..89d2b87 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -810,6 +810,7 @@
     <string name="lockscreen_access_pattern_cleared" msgid="5583479721001639579">"Grafiskt lösenord har tagits bort"</string>
     <string name="lockscreen_access_pattern_cell_added" msgid="6756031208359292487">"En cell har lagts till"</string>
     <string name="lockscreen_access_pattern_detected" msgid="4988730895554057058">"Grafiskt lösenord har slutförts"</string>
+    <string name="keyguard_accessibility_widget_changed" msgid="5678624624681400191">"%1$s. Widget %2$d av %3$d."</string>
     <string name="keyguard_accessibility_add_widget" msgid="8273277058724924654">"Lägg till en widget."</string>
     <string name="keyguard_accessibility_widget_empty_slot" msgid="1281505703307930757">"Tom"</string>
     <string name="keyguard_accessibility_unlock_area_expanded" msgid="2278106022311170299">"Expanderad upplåsningsyta."</string>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index 14f2b22..4b6758a4 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -810,6 +810,7 @@
     <string name="lockscreen_access_pattern_cleared" msgid="5583479721001639579">"Ruwaza imefutwa"</string>
     <string name="lockscreen_access_pattern_cell_added" msgid="6756031208359292487">"Kiini kimeongezwa"</string>
     <string name="lockscreen_access_pattern_detected" msgid="4988730895554057058">"Ruwaza imekamilika"</string>
+    <string name="keyguard_accessibility_widget_changed" msgid="5678624624681400191">"%1$s. Wiji %2$d ya %3$d."</string>
     <string name="keyguard_accessibility_add_widget" msgid="8273277058724924654">"Ongeza wiji"</string>
     <string name="keyguard_accessibility_widget_empty_slot" msgid="1281505703307930757">"Tupu"</string>
     <string name="keyguard_accessibility_unlock_area_expanded" msgid="2278106022311170299">"Eneo la kufungua limepanuliwa."</string>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index d26b2d5..9fb29a4 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -810,6 +810,7 @@
     <string name="lockscreen_access_pattern_cleared" msgid="5583479721001639579">"ล้างรูปแบบแล้ว"</string>
     <string name="lockscreen_access_pattern_cell_added" msgid="6756031208359292487">"เพิ่มเซลแล้ว"</string>
     <string name="lockscreen_access_pattern_detected" msgid="4988730895554057058">"วาดรูปแบบเสร็จสิ้น"</string>
+    <string name="keyguard_accessibility_widget_changed" msgid="5678624624681400191">"%1$s วิดเจ็ต %2$d ของ %3$d"</string>
     <string name="keyguard_accessibility_add_widget" msgid="8273277058724924654">"เพิ่มวิดเจ็ต"</string>
     <string name="keyguard_accessibility_widget_empty_slot" msgid="1281505703307930757">"ว่าง"</string>
     <string name="keyguard_accessibility_unlock_area_expanded" msgid="2278106022311170299">"ขยายพื้นที่ปลดล็อกแล้ว"</string>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index 3d68842..1578e7d 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -810,6 +810,7 @@
     <string name="lockscreen_access_pattern_cleared" msgid="5583479721001639579">"Na-clear ang pattern"</string>
     <string name="lockscreen_access_pattern_cell_added" msgid="6756031208359292487">"Idinagdag ang cell"</string>
     <string name="lockscreen_access_pattern_detected" msgid="4988730895554057058">"Nakumpleto ang pattern"</string>
+    <string name="keyguard_accessibility_widget_changed" msgid="5678624624681400191">"%1$s. Widget %2$d ng %3$d."</string>
     <string name="keyguard_accessibility_add_widget" msgid="8273277058724924654">"Magdagdag ng widget."</string>
     <string name="keyguard_accessibility_widget_empty_slot" msgid="1281505703307930757">"Walang laman"</string>
     <string name="keyguard_accessibility_unlock_area_expanded" msgid="2278106022311170299">"Pinalaki ang bahagi ng pag-unlock."</string>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index d775233..d8ca187 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -810,6 +810,7 @@
     <string name="lockscreen_access_pattern_cleared" msgid="5583479721001639579">"Desen temizlendi"</string>
     <string name="lockscreen_access_pattern_cell_added" msgid="6756031208359292487">"Hücre eklendi"</string>
     <string name="lockscreen_access_pattern_detected" msgid="4988730895554057058">"Desen tamamlandı"</string>
+    <string name="keyguard_accessibility_widget_changed" msgid="5678624624681400191">"%1$s. Widget %2$d / %3$d."</string>
     <string name="keyguard_accessibility_add_widget" msgid="8273277058724924654">"Widget ekleyin."</string>
     <string name="keyguard_accessibility_widget_empty_slot" msgid="1281505703307930757">"Boş"</string>
     <string name="keyguard_accessibility_unlock_area_expanded" msgid="2278106022311170299">"Kilit açma alanı genişletildi."</string>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index cc33b7b..6ccc115 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -810,6 +810,7 @@
     <string name="lockscreen_access_pattern_cleared" msgid="5583479721001639579">"Ключ очищено"</string>
     <string name="lockscreen_access_pattern_cell_added" msgid="6756031208359292487">"Телефон додано"</string>
     <string name="lockscreen_access_pattern_detected" msgid="4988730895554057058">"Малювання ключа закінчено"</string>
+    <string name="keyguard_accessibility_widget_changed" msgid="5678624624681400191">"%1$s. Віджет %2$d з %3$d."</string>
     <string name="keyguard_accessibility_add_widget" msgid="8273277058724924654">"Додати віджет."</string>
     <string name="keyguard_accessibility_widget_empty_slot" msgid="1281505703307930757">"Порожня область"</string>
     <string name="keyguard_accessibility_unlock_area_expanded" msgid="2278106022311170299">"Область розблокування розгорнуто."</string>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index 3e47de5..2afbb49 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -810,6 +810,7 @@
     <string name="lockscreen_access_pattern_cleared" msgid="5583479721001639579">"Đã xóa hình"</string>
     <string name="lockscreen_access_pattern_cell_added" msgid="6756031208359292487">"Đã thêm ô"</string>
     <string name="lockscreen_access_pattern_detected" msgid="4988730895554057058">"Đã vẽ xong hình"</string>
+    <string name="keyguard_accessibility_widget_changed" msgid="5678624624681400191">"%1$s. Tiện ích %2$d trong số %3$d."</string>
     <string name="keyguard_accessibility_add_widget" msgid="8273277058724924654">"Thêm tiện ích."</string>
     <string name="keyguard_accessibility_widget_empty_slot" msgid="1281505703307930757">"Trống"</string>
     <string name="keyguard_accessibility_unlock_area_expanded" msgid="2278106022311170299">"Đã mở rộng vùng khóa."</string>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index e21ebcf..6d8d220 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -810,6 +810,7 @@
     <string name="lockscreen_access_pattern_cleared" msgid="5583479721001639579">"图案已清除"</string>
     <string name="lockscreen_access_pattern_cell_added" msgid="6756031208359292487">"已添加单元格"</string>
     <string name="lockscreen_access_pattern_detected" msgid="4988730895554057058">"图案绘制完成"</string>
+    <string name="keyguard_accessibility_widget_changed" msgid="5678624624681400191">"%1$s。%3$d的小部件%2$d。"</string>
     <string name="keyguard_accessibility_add_widget" msgid="8273277058724924654">"添加小部件。"</string>
     <string name="keyguard_accessibility_widget_empty_slot" msgid="1281505703307930757">"空白"</string>
     <string name="keyguard_accessibility_unlock_area_expanded" msgid="2278106022311170299">"已展开解锁区域。"</string>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index a1286f1..879ccf5 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -810,6 +810,7 @@
     <string name="lockscreen_access_pattern_cleared" msgid="5583479721001639579">"已清除解鎖圖形"</string>
     <string name="lockscreen_access_pattern_cell_added" msgid="6756031208359292487">"已加入 1 格"</string>
     <string name="lockscreen_access_pattern_detected" msgid="4988730895554057058">"已畫出解鎖圖形"</string>
+    <string name="keyguard_accessibility_widget_changed" msgid="5678624624681400191">"%1$s。第 %2$d 個小工具,共 %3$d 個。"</string>
     <string name="keyguard_accessibility_add_widget" msgid="8273277058724924654">"新增小工具。"</string>
     <string name="keyguard_accessibility_widget_empty_slot" msgid="1281505703307930757">"空白"</string>
     <string name="keyguard_accessibility_unlock_area_expanded" msgid="2278106022311170299">"解鎖區域已展開。"</string>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index 27660de..5d25c29 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -810,6 +810,7 @@
     <string name="lockscreen_access_pattern_cleared" msgid="5583479721001639579">"Iphethini isusiwe"</string>
     <string name="lockscreen_access_pattern_cell_added" msgid="6756031208359292487">"Kwengezwe"</string>
     <string name="lockscreen_access_pattern_detected" msgid="4988730895554057058">"Iphethini isiphelile"</string>
+    <string name="keyguard_accessibility_widget_changed" msgid="5678624624681400191">"%1$s. iwijethi %2$d ye-%3$d."</string>
     <string name="keyguard_accessibility_add_widget" msgid="8273277058724924654">"Engeza iwijethi."</string>
     <string name="keyguard_accessibility_widget_empty_slot" msgid="1281505703307930757">"Akunalutho"</string>
     <string name="keyguard_accessibility_unlock_area_expanded" msgid="2278106022311170299">"Indawo yokuvula inwetshisiwe."</string>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 48ee429..451d3ef 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -2246,6 +2246,14 @@
              See {@link android.view.ViewGroup#setMotionEventSplittingEnabled(boolean)}
              for more information. -->
         <attr name="splitMotionEvents" format="boolean" />
+
+        <!-- Defines the layout mode of this ViewGroup. -->
+        <attr name="layoutMode">
+            <!-- Use the children's clip bounds when laying out this container. -->
+            <enum name="clipBounds" value="0" />
+            <!-- Use the children's optical bounds when laying out this container. -->
+            <enum name="opticalBounds" value="1" />
+        </attr>
     </declare-styleable>
 
     <!-- A {@link android.view.ViewStub} lets you lazily include other XML layouts
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index ea28a51..3523db6 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -882,6 +882,16 @@
 
     <!-- Remote server that can provide NTP responses. -->
     <string translatable="false" name="config_ntpServer">2.android.pool.ntp.org</string>
+    <!-- Normal polling frequency in milliseconds -->
+    <integer name="config_ntpPollingInterval">864000000</integer>
+    <!-- Try-again polling interval in milliseconds, in case the network request failed -->
+    <integer name="config_ntpPollingIntervalShorter">60000</integer>
+    <!-- Number of times to try again with the shorter interval, before backing
+         off until the normal polling interval. A value < 0 indicates infinite. -->
+    <integer name="config_ntpRetry">3</integer>
+    <!-- If the time difference is greater than this threshold in milliseconds,
+         then update the time. -->
+    <integer name="config_ntpThreshold">5000</integer>
     <!-- Timeout to wait for NTP server response. -->
     <integer name="config_ntpTimeout">20000</integer>
 
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 1d29d8c..592ebb7 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -281,6 +281,10 @@
   <java-symbol type="integer" name="config_cursorWindowSize" />
   <java-symbol type="integer" name="config_longPressOnPowerBehavior" />
   <java-symbol type="integer" name="config_max_pan_devices" />
+  <java-symbol type="integer" name="config_ntpPollingInterval" />
+  <java-symbol type="integer" name="config_ntpPollingIntervalShorter" />
+  <java-symbol type="integer" name="config_ntpRetry" />
+  <java-symbol type="integer" name="config_ntpThreshold" />
   <java-symbol type="integer" name="config_ntpTimeout" />
   <java-symbol type="integer" name="config_wifi_framework_scan_interval" />
   <java-symbol type="integer" name="config_wifi_supplicant_scan_interval" />
@@ -1818,4 +1822,8 @@
   <!-- From PinyinIME(!!!) -->
   <java-symbol type="string" name="inputMethod" />
 
+  <!-- From Chromium-WebView -->
+  <java-symbol type="attr" name="actionModeWebSearchDrawable" />
+  <java-symbol type="string" name="websearch" />
+
 </resources>
diff --git a/core/tests/coretests/src/android/content/SyncOperationTest.java b/core/tests/coretests/src/android/content/SyncOperationTest.java
index 910c721..1fd25d2 100644
--- a/core/tests/coretests/src/android/content/SyncOperationTest.java
+++ b/core/tests/coretests/src/android/content/SyncOperationTest.java
@@ -43,6 +43,7 @@
 
         SyncOperation op1 = new SyncOperation(account1, 0,
                 1,
+                SyncOperation.REASON_PERIODIC,
                 "authority1",
                 b1,
                 100,
@@ -53,6 +54,7 @@
         // Same as op1 but different time infos
         SyncOperation op2 = new SyncOperation(account1, 0,
                 1,
+                SyncOperation.REASON_PERIODIC,
                 "authority1",
                 b1,
                 200,
@@ -63,6 +65,7 @@
         // Same as op1 but different authority
         SyncOperation op3 = new SyncOperation(account1, 0,
                 1,
+                SyncOperation.REASON_PERIODIC,
                 "authority2",
                 b1,
                 100,
@@ -73,6 +76,7 @@
         // Same as op1 but different account
         SyncOperation op4 = new SyncOperation(account2, 0,
                 1,
+                SyncOperation.REASON_PERIODIC,
                 "authority1",
                 b1,
                 100,
@@ -83,6 +87,7 @@
         // Same as op1 but different bundle
         SyncOperation op5 = new SyncOperation(account1, 0,
                 1,
+                SyncOperation.REASON_PERIODIC,
                 "authority1",
                 b2,
                 100,
diff --git a/core/tests/coretests/src/android/content/SyncStorageEngineTest.java b/core/tests/coretests/src/android/content/SyncStorageEngineTest.java
index 2add623..58d2327 100644
--- a/core/tests/coretests/src/android/content/SyncStorageEngineTest.java
+++ b/core/tests/coretests/src/android/content/SyncStorageEngineTest.java
@@ -16,8 +16,6 @@
 
 package android.content;
 
-import com.android.internal.os.AtomicFile;
-
 import android.accounts.Account;
 import android.os.Bundle;
 import android.test.AndroidTestCase;
@@ -28,6 +26,8 @@
 import android.test.suitebuilder.annotation.MediumTest;
 import android.test.suitebuilder.annotation.SmallTest;
 
+import com.android.internal.os.AtomicFile;
+
 import java.io.File;
 import java.io.FileOutputStream;
 import java.util.List;
@@ -56,8 +56,8 @@
 
         long time0 = 1000;
         long historyId = engine.insertStartSyncEvent(
-                account, 0, authority, time0, SyncStorageEngine.SOURCE_LOCAL,
-                false /* initialization */);
+                account, 0, SyncOperation.REASON_PERIODIC, authority, time0,
+                SyncStorageEngine.SOURCE_LOCAL, false /* initialization */, null /* extras */);
         long time1 = time0 + SyncStorageEngine.MILLIS_IN_4WEEKS * 2;
         engine.stopSyncEvent(historyId, time1 - time0, "yay", 0, 0);
     }
diff --git a/data/sounds/AudioPackage10.mk b/data/sounds/AudioPackage10.mk
index cb55bba..a930a54 100755
--- a/data/sounds/AudioPackage10.mk
+++ b/data/sounds/AudioPackage10.mk
@@ -16,13 +16,13 @@
         $(LOCAL_PATH)/alarms/ogg/Oxygen.ogg:system/media/audio/alarms/Oxygen.ogg \
         $(LOCAL_PATH)/alarms/ogg/Osmium.ogg:system/media/audio/alarms/Osmium.ogg \
         $(LOCAL_PATH)/alarms/ogg/Platinum.ogg:system/media/audio/alarms/Platinum.ogg \
-	$(LOCAL_PATH)/effects/ogg/Effect_Tick.ogg:system/media/audio/ui/Effect_Tick.ogg \
-	$(LOCAL_PATH)/effects/ogg/KeypressStandard_120.ogg:system/media/audio/ui/KeypressStandard.ogg \
-	$(LOCAL_PATH)/effects/ogg/KeypressSpacebar_120.ogg:system/media/audio/ui/KeypressSpacebar.ogg \
-	$(LOCAL_PATH)/effects/ogg/KeypressDelete_120.ogg:system/media/audio/ui/KeypressDelete.ogg \
-	$(LOCAL_PATH)/effects/ogg/KeypressReturn_120.ogg:system/media/audio/ui/KeypressReturn.ogg \
-	$(LOCAL_PATH)/effects/ogg/VideoRecord.ogg:system/media/audio/ui/VideoRecord.ogg \
-	$(LOCAL_PATH)/effects/ogg/camera_click.ogg:system/media/audio/ui/camera_click.ogg \
+	$(LOCAL_PATH)/effects/ogg/Effect_Tick_48k.ogg:system/media/audio/ui/Effect_Tick.ogg \
+	$(LOCAL_PATH)/effects/ogg/KeypressStandard_120_48k.ogg:system/media/audio/ui/KeypressStandard.ogg \
+	$(LOCAL_PATH)/effects/ogg/KeypressSpacebar_120_48k.ogg:system/media/audio/ui/KeypressSpacebar.ogg \
+	$(LOCAL_PATH)/effects/ogg/KeypressDelete_120_48k.ogg:system/media/audio/ui/KeypressDelete.ogg \
+	$(LOCAL_PATH)/effects/ogg/KeypressReturn_120_48k.ogg:system/media/audio/ui/KeypressReturn.ogg \
+	$(LOCAL_PATH)/effects/ogg/VideoRecord_48k.ogg:system/media/audio/ui/VideoRecord.ogg \
+	$(LOCAL_PATH)/effects/ogg/camera_click_48k.ogg:system/media/audio/ui/camera_click.ogg \
 	$(LOCAL_PATH)/effects/ogg/camera_focus.ogg:system/media/audio/ui/camera_focus.ogg \
 	$(LOCAL_PATH)/effects/ogg/LowBattery.ogg:system/media/audio/ui/LowBattery.ogg \
 	$(LOCAL_PATH)/effects/ogg/Dock.ogg:system/media/audio/ui/Dock.ogg \
diff --git a/data/sounds/README.txt b/data/sounds/README.txt
new file mode 100644
index 0000000..193fd71
--- /dev/null
+++ b/data/sounds/README.txt
@@ -0,0 +1,33 @@
+This README describes the audio assets, and how they relate to each other.
+
+The product .mk references one of the AudioPackage*.mk,
+which installs the appropriate assets into the destination directory.
+
+For UI sound effects,
+frameworks/base/media/java/android/media/AudioService.java array
+SOUND_EFFECT_FILES contains a hard-coded list of asset filenames, stored
+in directory SOUND_EFFECTS_PATH.
+
+Touch sounds
+------------
+
+effects/Effect_Tick.ogg
+  old, referenced by AudioPackage[2345].mk OriginalAudio.mk
+
+effects/ogg/Effect_Tick.ogg
+  new, referenced by AudioPackage[6789].mk AudioPackage7alt.mk AudioPackage10.mk
+
+effects/ogg/Effect_Tick_48k.ogg
+  oggdec -o temp.wav ogg/Effect_Tick.ogg
+  sox temp.wav -r 48000 temp48k.wav
+  oggenc -b 80 -o ogg/Effect_Tick_48k.ogg temp48k.wav
+
+effects/wav/Effect_Tick.wav
+  does not appear to be related to the other files in any obvious way
+
+Video recording
+---------------
+
+./effects/ogg/VideoStop_48k.ogg
+  unused
+
diff --git a/data/sounds/effects/ogg/Effect_Tick_48k.ogg b/data/sounds/effects/ogg/Effect_Tick_48k.ogg
new file mode 100644
index 0000000..e1f53d7
--- /dev/null
+++ b/data/sounds/effects/ogg/Effect_Tick_48k.ogg
Binary files differ
diff --git a/data/sounds/effects/ogg/KeypressDelete_120_48k.ogg b/data/sounds/effects/ogg/KeypressDelete_120_48k.ogg
new file mode 100644
index 0000000..e218215
--- /dev/null
+++ b/data/sounds/effects/ogg/KeypressDelete_120_48k.ogg
Binary files differ
diff --git a/data/sounds/effects/ogg/KeypressReturn_120_48k.ogg b/data/sounds/effects/ogg/KeypressReturn_120_48k.ogg
new file mode 100644
index 0000000..37a6d34
--- /dev/null
+++ b/data/sounds/effects/ogg/KeypressReturn_120_48k.ogg
Binary files differ
diff --git a/data/sounds/effects/ogg/KeypressSpacebar_120_48k.ogg b/data/sounds/effects/ogg/KeypressSpacebar_120_48k.ogg
new file mode 100644
index 0000000..69ee792
--- /dev/null
+++ b/data/sounds/effects/ogg/KeypressSpacebar_120_48k.ogg
Binary files differ
diff --git a/data/sounds/effects/ogg/KeypressStandard_120_48k.ogg b/data/sounds/effects/ogg/KeypressStandard_120_48k.ogg
new file mode 100644
index 0000000..1598c24
--- /dev/null
+++ b/data/sounds/effects/ogg/KeypressStandard_120_48k.ogg
Binary files differ
diff --git a/docs/html/guide/google/gcm/gcm.jd b/docs/html/guide/google/gcm/gcm.jd
index 1762e12..7fc192b 100644
--- a/docs/html/guide/google/gcm/gcm.jd
+++ b/docs/html/guide/google/gcm/gcm.jd
@@ -920,6 +920,7 @@
 # curl --header "Authorization: key=$api_key" --header Content-Type:"application/json" https://android.googleapis.com/gcm/send  -d "{\"registration_ids\":[\"ABC\"]}"</pre>
 
 
+
 If you receive a 401 HTTP status code, your API key is not valid. Otherwise you should see something like this:<br/>
 
 <pre>
diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java
index 688fd7a..89abdef 100644
--- a/graphics/java/android/graphics/Bitmap.java
+++ b/graphics/java/android/graphics/Bitmap.java
@@ -82,6 +82,7 @@
         if (sDefaultDensity >= 0) {
             return sDefaultDensity;
         }
+        //noinspection deprecation
         sDefaultDensity = DisplayMetrics.DENSITY_DEVICE;
         return sDefaultDensity;
     }
@@ -360,6 +361,9 @@
      * that if this bitmap stores its pixels pre-multiplied
      * (see {@link #isPremultiplied()}, the values in the buffer will also be
      * pre-multiplied.</p>
+     * <p>After this method returns, the current position of the buffer is
+     * updated: the position is incremented by the number of elements written
+     * in the buffer.</p>
      */
     public void copyPixelsToBuffer(Buffer dst) {
         int elements = dst.remaining();
@@ -394,6 +398,10 @@
      * overwriting the bitmap's pixels. The data in the buffer is not changed
      * in any way (unlike setPixels(), which converts from unpremultipled 32bit
      * to whatever the bitmap's native format is.</p>
+     * <p>After this method returns, the current position of the buffer is
+     * updated: the position is incremented by the number of elements read from
+     * the buffer. If you need to read the bitmap from the buffer again you must
+     * first rewind the buffer.</p>
      */
     public void copyPixelsFromBuffer(Buffer src) {
         checkRecycled("copyPixelsFromBuffer called on recycled bitmap");
diff --git a/graphics/java/android/graphics/SurfaceTexture.java b/graphics/java/android/graphics/SurfaceTexture.java
index 4beaecd..b919ba4 100644
--- a/graphics/java/android/graphics/SurfaceTexture.java
+++ b/graphics/java/android/graphics/SurfaceTexture.java
@@ -66,9 +66,10 @@
     private OnFrameAvailableListener mOnFrameAvailableListener;
 
     /**
-     * This field is used by native code, do not access or modify.
+     * These fields are used by native code, do not access or modify.
      */
     private int mSurfaceTexture;
+    private int mFrameAvailableListener;
 
     /**
      * Callback interface for being notified that a new stream frame is available.
@@ -196,7 +197,7 @@
     public void attachToGLContext(int texName) {
         int err = nativeAttachToGLContext(texName);
         if (err != 0) {
-            throw new RuntimeException("Error during detachFromGLContext (see logcat for details)");
+            throw new RuntimeException("Error during attachToGLContext (see logcat for details)");
         }
     }
 
diff --git a/graphics/java/android/graphics/drawable/Drawable.java b/graphics/java/android/graphics/drawable/Drawable.java
index f9392e4..54d1bf5 100644
--- a/graphics/java/android/graphics/drawable/Drawable.java
+++ b/graphics/java/android/graphics/drawable/Drawable.java
@@ -715,7 +715,7 @@
      *
      * @hide
      */
-    public Insets getLayoutInsets() {
+    public Insets getOpticalInsets() {
         return Insets.NONE;
     }
 
diff --git a/graphics/java/android/graphics/drawable/DrawableContainer.java b/graphics/java/android/graphics/drawable/DrawableContainer.java
index 8280d2d..a0c9701 100644
--- a/graphics/java/android/graphics/drawable/DrawableContainer.java
+++ b/graphics/java/android/graphics/drawable/DrawableContainer.java
@@ -95,8 +95,8 @@
      * @hide
      */
     @Override
-    public Insets getLayoutInsets() {
-        return (mCurrDrawable == null) ? Insets.NONE : mCurrDrawable.getLayoutInsets();
+    public Insets getOpticalInsets() {
+        return (mCurrDrawable == null) ? Insets.NONE : mCurrDrawable.getOpticalInsets();
     }
 
     @Override
diff --git a/graphics/java/android/graphics/drawable/NinePatchDrawable.java b/graphics/java/android/graphics/drawable/NinePatchDrawable.java
index 2ee6233..a9dc22b 100644
--- a/graphics/java/android/graphics/drawable/NinePatchDrawable.java
+++ b/graphics/java/android/graphics/drawable/NinePatchDrawable.java
@@ -56,7 +56,7 @@
     private NinePatchState mNinePatchState;
     private NinePatch mNinePatch;
     private Rect mPadding;
-    private Insets mLayoutInsets = Insets.NONE;
+    private Insets mOpticalInsets = Insets.NONE;
     private Paint mPaint;
     private boolean mMutated;
 
@@ -96,8 +96,8 @@
      * @hide
      */
     public NinePatchDrawable(Resources res, Bitmap bitmap, byte[] chunk,
-            Rect padding, Rect layoutInsets, String srcName) {
-        this(new NinePatchState(new NinePatch(bitmap, chunk, srcName), padding, layoutInsets), res);
+            Rect padding, Rect opticalInsets, String srcName) {
+        this(new NinePatchState(new NinePatch(bitmap, chunk, srcName), padding, opticalInsets), res);
         mNinePatchState.mTargetDensity = mTargetDensity;
     }
 
@@ -195,7 +195,7 @@
         if (sdensity == tdensity) {
             mBitmapWidth = mNinePatch.getWidth();
             mBitmapHeight = mNinePatch.getHeight();
-            mLayoutInsets = mNinePatchState.mLayoutInsets;
+            mOpticalInsets = mNinePatchState.mOpticalInsets;
         } else {
             mBitmapWidth = Bitmap.scaleFromDensity(mNinePatch.getWidth(),
                     sdensity, tdensity);
@@ -212,7 +212,7 @@
                 dest.right = Bitmap.scaleFromDensity(src.right, sdensity, tdensity);
                 dest.bottom = Bitmap.scaleFromDensity(src.bottom, sdensity, tdensity);
             }
-            mLayoutInsets = scaleFromDensity(mNinePatchState.mLayoutInsets, sdensity, tdensity);
+            mOpticalInsets = scaleFromDensity(mNinePatchState.mOpticalInsets, sdensity, tdensity);
         }
     }
 
@@ -236,8 +236,8 @@
      * @hide
      */
     @Override
-    public Insets getLayoutInsets() {
-        return mLayoutInsets;
+    public Insets getOpticalInsets() {
+        return mOpticalInsets;
     }
 
     @Override
@@ -299,7 +299,7 @@
         options.inScreenDensity = r.getDisplayMetrics().noncompatDensityDpi;
 
         final Rect padding = new Rect();
-        final Rect layoutInsets = new Rect();
+        final Rect opticalInsets = new Rect();
         Bitmap bitmap = null;
 
         try {
@@ -323,7 +323,7 @@
 
         setNinePatchState(new NinePatchState(
                 new NinePatch(bitmap, bitmap.getNinePatchChunk(), "XML 9-patch"),
-                padding, layoutInsets, dither), r);
+                padding, opticalInsets, dither), r);
         mNinePatchState.mTargetDensity = mTargetDensity;
 
         a.recycle();
@@ -397,7 +397,7 @@
     private final static class NinePatchState extends ConstantState {
         final NinePatch mNinePatch;
         final Rect mPadding;
-        final Insets mLayoutInsets;
+        final Insets mOpticalInsets;
         final boolean mDither;
         int mChangingConfigurations;
         int mTargetDensity = DisplayMetrics.DENSITY_DEFAULT;
@@ -406,14 +406,14 @@
             this(ninePatch, padding, new Rect(), DEFAULT_DITHER);
         }
 
-        NinePatchState(NinePatch ninePatch, Rect padding, Rect layoutInsets) {
-            this(ninePatch, padding, layoutInsets, DEFAULT_DITHER);
+        NinePatchState(NinePatch ninePatch, Rect padding, Rect opticalInsets) {
+            this(ninePatch, padding, opticalInsets, DEFAULT_DITHER);
         }
 
-        NinePatchState(NinePatch ninePatch, Rect rect, Rect layoutInsets, boolean dither) {
+        NinePatchState(NinePatch ninePatch, Rect rect, Rect opticalInsets, boolean dither) {
             mNinePatch = ninePatch;
             mPadding = rect;
-            mLayoutInsets = Insets.of(layoutInsets);
+            mOpticalInsets = Insets.of(opticalInsets);
             mDither = dither;
         }
 
@@ -423,7 +423,7 @@
             mNinePatch = new NinePatch(state.mNinePatch);
             // Note we don't copy the padding because it is immutable.
             mPadding = state.mPadding;
-            mLayoutInsets = state.mLayoutInsets;
+            mOpticalInsets = state.mOpticalInsets;
             mDither = state.mDither;
             mChangingConfigurations = state.mChangingConfigurations;
             mTargetDensity = state.mTargetDensity;
diff --git a/graphics/java/android/renderscript/Allocation.java b/graphics/java/android/renderscript/Allocation.java
index 10ccb87..e44a3ef 100644
--- a/graphics/java/android/renderscript/Allocation.java
+++ b/graphics/java/android/renderscript/Allocation.java
@@ -568,6 +568,21 @@
     }
 
     /**
+     * Copy an allocation from an allocation.  The types of both allocations
+     * must be identical.
+     *
+     * @param a the source allocation
+     */
+    public void copyFrom(Allocation a) {
+        mRS.validate();
+        if (!mType.equals(a.getType())) {
+            throw new RSIllegalArgumentException("Types of allocations must match.");
+        }
+        copy2DRangeFrom(0, 0, mCurrentDimX, mCurrentDimY, a, 0, 0);
+    }
+
+
+    /**
      * This is only intended to be used by auto-generate code reflected from the
      * renderscript script files.
      *
@@ -971,11 +986,10 @@
      *
      * A new type will be created with the new dimension.
      *
-     * @hide
      * @param dimX The new size of the allocation.
      * @param dimY The new size of the allocation.
      */
-    public void resize(int dimX, int dimY) {
+    public synchronized void resize(int dimX, int dimY) {
         if ((mType.getZ() > 0) || mType.hasFaces() || mType.hasMipmaps()) {
             throw new RSInvalidStateException(
                 "Resize only support for 2D allocations at this time.");
diff --git a/graphics/java/android/renderscript/ScriptIntrinsicBlur.java b/graphics/java/android/renderscript/ScriptIntrinsicBlur.java
index 11164e3..7ffd1e7 100644
--- a/graphics/java/android/renderscript/ScriptIntrinsicBlur.java
+++ b/graphics/java/android/renderscript/ScriptIntrinsicBlur.java
@@ -46,7 +46,7 @@
      * @return ScriptIntrinsicBlur
      */
     public static ScriptIntrinsicBlur create(RenderScript rs, Element e) {
-        if (e != Element.U8_4(rs)) {
+        if ((e != Element.U8_4(rs)) && e != (Element.U8(rs))) {
             throw new RSIllegalArgumentException("Unsuported element type.");
         }
         int id = rs.nScriptIntrinsicCreate(5, e.getID(rs));
diff --git a/libs/diskusage/Android.mk b/libs/diskusage/Android.mk
deleted file mode 100644
index d54f8ad..0000000
--- a/libs/diskusage/Android.mk
+++ /dev/null
@@ -1,24 +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.
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := libdiskusage
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_SRC_FILES := dirsize.c
-
-include $(BUILD_STATIC_LIBRARY)
\ No newline at end of file
diff --git a/libs/diskusage/MODULE_LICENSE_APACHE2 b/libs/diskusage/MODULE_LICENSE_APACHE2
deleted file mode 100644
index e69de29..0000000
--- a/libs/diskusage/MODULE_LICENSE_APACHE2
+++ /dev/null
diff --git a/libs/diskusage/dirsize.c b/libs/diskusage/dirsize.c
deleted file mode 100644
index 6703783..0000000
--- a/libs/diskusage/dirsize.c
+++ /dev/null
@@ -1,74 +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.
- */
-
-#include <dirent.h>
-#include <fcntl.h>
-#include <sys/stat.h>
-
-#include <diskusage/dirsize.h>
-
-int64_t stat_size(struct stat *s)
-{
-    int64_t blksize = s->st_blksize;
-    int64_t size = s->st_size;
-
-    if (blksize) {
-        /* round up to filesystem block size */
-        size = (size + blksize - 1) & (~(blksize - 1));
-    }
-
-    return size;
-}
-
-int64_t calculate_dir_size(int dfd)
-{
-    int64_t size = 0;
-    struct stat s;
-    DIR *d;
-    struct dirent *de;
-
-    d = fdopendir(dfd);
-    if (d == NULL) {
-        close(dfd);
-        return 0;
-    }
-
-    while ((de = readdir(d))) {
-        const char *name = de->d_name;
-        if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) == 0) {
-            size += stat_size(&s);
-        }
-        if (de->d_type == DT_DIR) {
-            int subfd;
-
-            /* always skip "." and ".." */
-            if (name[0] == '.') {
-                if (name[1] == 0)
-                    continue;
-                if ((name[1] == '.') && (name[2] == 0))
-                    continue;
-            }
-
-            subfd = openat(dfd, name, O_RDONLY | O_DIRECTORY);
-            if (subfd >= 0) {
-                size += calculate_dir_size(subfd);
-            }
-        }
-    }
-    closedir(d);
-    return size;
-}
diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java
index 56abed4..2ad9de9 100644
--- a/media/java/android/media/AudioService.java
+++ b/media/java/android/media/AudioService.java
@@ -3178,7 +3178,7 @@
                         mediaPlayer.setDataSource(filePath);
                         mediaPlayer.setAudioStreamType(AudioSystem.STREAM_SYSTEM);
                         mediaPlayer.prepare();
-                        mediaPlayer.setVolume(volFloat, volFloat);
+                        mediaPlayer.setVolume(volFloat);
                         mediaPlayer.setOnCompletionListener(new OnCompletionListener() {
                             public void onCompletion(MediaPlayer mp) {
                                 cleanupPlayer(mp);
diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java
index 96f01db..694e9c2 100644
--- a/media/java/android/media/AudioTrack.java
+++ b/media/java/android/media/AudioTrack.java
@@ -779,6 +779,15 @@
 
 
     /**
+     * Similar, except set volume of all channels to same value.
+     * @hide
+     */
+    public int setVolume(float volume) {
+        return setStereoVolume(volume, volume);
+    }
+
+
+    /**
      * Sets the playback sample rate for this track. This sets the sampling rate at which
      * the audio data will be consumed and played back, not the original sampling rate of the
      * content. Setting it to half the sample rate of the content will cause the playback to
diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
index ef0da3a..7bd9049 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -1361,15 +1361,28 @@
      * within an application. Unless you are writing an application to
      * control user settings, this API should be used in preference to
      * {@link AudioManager#setStreamVolume(int, int, int)} which sets the volume of ALL streams of
-     * a particular type. Note that the passed volume values are raw scalars.
+     * a particular type. Note that the passed volume values are raw scalars in range 0.0 to 1.0.
      * UI controls should be scaled logarithmically.
      *
      * @param leftVolume left volume scalar
      * @param rightVolume right volume scalar
      */
+    /*
+     * FIXME: Merge this into javadoc comment above when setVolume(float) is not @hide.
+     * The single parameter form below is preferred if the channel volumes don't need
+     * to be set independently.
+     */
     public native void setVolume(float leftVolume, float rightVolume);
 
     /**
+     * Similar, excepts sets volume of all channels to same value.
+     * @hide
+     */
+    public void setVolume(float volume) {
+        setVolume(volume, volume);
+    }
+
+    /**
      * Currently not implemented, returns null.
      * @deprecated
      * @hide
diff --git a/media/java/android/media/MediaScanner.java b/media/java/android/media/MediaScanner.java
index 0117d73..959bf0a 100644
--- a/media/java/android/media/MediaScanner.java
+++ b/media/java/android/media/MediaScanner.java
@@ -310,6 +310,7 @@
     private Uri mThumbsUri;
     private Uri mPlaylistsUri;
     private Uri mFilesUri;
+    private Uri mFilesUriNoNotify;
     private boolean mProcessPlaylists, mProcessGenres;
     private int mMtpObjectHandle;
 
@@ -1275,6 +1276,7 @@
         mImagesUri = Images.Media.getContentUri(volumeName);
         mThumbsUri = Images.Thumbnails.getContentUri(volumeName);
         mFilesUri = Files.getContentUri(volumeName);
+        mFilesUriNoNotify = mFilesUri.buildUpon().appendQueryParameter("nonotify", "1").build();
 
         if (!volumeName.equals("internal")) {
             // we only support playlists on external media
@@ -1336,6 +1338,9 @@
             prescan(path, true);
 
             File file = new File(path);
+            if (!file.exists()) {
+                return null;
+            }
 
             // lastModified is in milliseconds on Files.
             long lastModifiedSeconds = file.lastModified() / 1000;
@@ -1469,36 +1474,10 @@
 
         Cursor c = null;
         try {
-            boolean hasWildCards = path.contains("_") || path.contains("%");
-
-            if (hasWildCards || !mCaseInsensitivePaths) {
-                // if there are wildcard characters in the path, the "like" match
-                // will be slow, and it's worth trying an "=" comparison
-                // first, since in most cases the case will match.
-                // Also, we shouldn't do a "like" match on case-sensitive filesystems
-                where = Files.FileColumns.DATA + "=?";
-                selectionArgs = new String[] { path };
-            } else {
-                // if there are no wildcard characters in the path, then the "like"
-                // match will be just as fast as the "=" case, because of the index
-                where = "_data LIKE ?1 AND lower(_data)=lower(?1)";
-                selectionArgs = new String[] { path };
-            }
-            c = mMediaProvider.query(mFilesUri, FILES_PRESCAN_PROJECTION,
+            where = Files.FileColumns.DATA + "=?";
+            selectionArgs = new String[] { path };
+            c = mMediaProvider.query(mFilesUriNoNotify, FILES_PRESCAN_PROJECTION,
                     where, selectionArgs, null, null);
-            if (!c.moveToFirst() && hasWildCards && mCaseInsensitivePaths) {
-                // Try again with case-insensitive match. This will be slower, especially
-                // if the path contains wildcard characters.
-                // The 'like' makes it use the index, the 'lower()' makes it correct
-                // when the path contains sqlite wildcard characters,
-                where = "_data LIKE ?1 AND lower(_data)=lower(?1)";
-                selectionArgs = new String[] { path };
-                c.close();
-                c = mMediaProvider.query(mFilesUri, FILES_PRESCAN_PROJECTION,
-                        where, selectionArgs, null, null);
-                // TODO update the path in the db with the correct case so the fast
-                // path works next time?
-            }
             if (c.moveToFirst()) {
                 long rowId = c.getLong(FILES_PRESCAN_ID_COLUMN_INDEX);
                 int format = c.getInt(FILES_PRESCAN_FORMAT_COLUMN_INDEX);
diff --git a/media/java/android/media/SoundPool.java b/media/java/android/media/SoundPool.java
index 0f68e98..587af47 100644
--- a/media/java/android/media/SoundPool.java
+++ b/media/java/android/media/SoundPool.java
@@ -354,6 +354,14 @@
             float leftVolume, float rightVolume);
 
     /**
+     * Similar, except set volume of all channels to same value.
+     * @hide
+     */
+    public void setVolume(int streamID, float volume) {
+        setVolume(streamID, volume, volume);
+    }
+
+    /**
      * Change stream priority.
      *
      * Change the priority of the stream specified by the streamID.
diff --git a/media/jni/Android.mk b/media/jni/Android.mk
index 6294704..6aaab220 100644
--- a/media/jni/Android.mk
+++ b/media/jni/Android.mk
@@ -24,7 +24,6 @@
     libutils \
     libbinder \
     libmedia \
-    libmedia_native \
     libskia \
     libui \
     libcutils \
diff --git a/media/jni/audioeffect/Android.mk b/media/jni/audioeffect/Android.mk
index 0059bb2..b5d8b7b 100644
--- a/media/jni/audioeffect/Android.mk
+++ b/media/jni/audioeffect/Android.mk
@@ -10,8 +10,7 @@
 	libutils \
 	libandroid_runtime \
 	libnativehelper \
-	libmedia \
-	libmedia_native
+	libmedia
 
 LOCAL_C_INCLUDES := \
 	$(call include-path-for, audio-effects)
diff --git a/media/jni/soundpool/Android.mk b/media/jni/soundpool/Android.mk
index 160666b..9b11bfa 100644
--- a/media/jni/soundpool/Android.mk
+++ b/media/jni/soundpool/Android.mk
@@ -9,8 +9,7 @@
 	libutils \
 	libandroid_runtime \
 	libnativehelper \
-	libmedia \
-	libmedia_native
+	libmedia
 
 LOCAL_MODULE:= libsoundpool
 
diff --git a/media/mca/filterfw/Android.mk b/media/mca/filterfw/Android.mk
index b822e99..1d69799 100644
--- a/media/mca/filterfw/Android.mk
+++ b/media/mca/filterfw/Android.mk
@@ -39,8 +39,7 @@
                           libutils \
                           libandroid \
                           libjnigraphics \
-                          libmedia \
-                          libmedia_native
+                          libmedia
 
 # Don't prelink this library.  For more efficient code, you may want
 # to add this library to the prelink map and set this to true. However,
diff --git a/packages/BackupRestoreConfirmation/res/values-ca/strings.xml b/packages/BackupRestoreConfirmation/res/values-ca/strings.xml
index c511510..32cfefc 100644
--- a/packages/BackupRestoreConfirmation/res/values-ca/strings.xml
+++ b/packages/BackupRestoreConfirmation/res/values-ca/strings.xml
@@ -16,7 +16,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="backup_confirm_title" msgid="827563724209303345">"Fes una còpia de seguretat completa"</string>
+    <string name="backup_confirm_title" msgid="827563724209303345">"Còpia de seguretat completa"</string>
     <string name="restore_confirm_title" msgid="5469365809567486602">"Restaura completament"</string>
     <string name="backup_confirm_text" msgid="1878021282758896593">"S\'ha sol·licitat una còpia de seguretat completa de totes les dades a un equip de sobretaula connectat. Vols permetre que això passi?"\n" "\n"Si no has sol·licitat la còpia de seguretat tu mateix, no permetis que continuï l\'operació."</string>
     <string name="allow_backup_button_label" msgid="4217228747769644068">"Còpia de seguretat de dades"</string>
diff --git a/packages/BackupRestoreConfirmation/res/values-fa/strings.xml b/packages/BackupRestoreConfirmation/res/values-fa/strings.xml
index 6da7d4a..4349444 100644
--- a/packages/BackupRestoreConfirmation/res/values-fa/strings.xml
+++ b/packages/BackupRestoreConfirmation/res/values-fa/strings.xml
@@ -18,7 +18,7 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="backup_confirm_title" msgid="827563724209303345">"پشتیبان‌گیری کامل"</string>
     <string name="restore_confirm_title" msgid="5469365809567486602">"بازیابی کامل"</string>
-    <string name="backup_confirm_text" msgid="1878021282758896593">"درخواست پشتیبان گیری کامل از تمام داده‌ها به یک رایانه دسک‌تاپ متصل داده شده است. آیا می‌خواهید این عمل انجام شود؟"\n\n"اگر شما درخواست تهیه نسخهٔ پشتیبان را نداده‌اید، اجازه‌ ادامه عملیات را ندهید."</string>
+    <string name="backup_confirm_text" msgid="1878021282758896593">"درخواست پشتیبان گیری کامل از تمام داده‌ها به یک رایانه دسک‌تاپ متصل داده شده است. آیا می‌خواهید این عمل انجام شود؟"\n\n"اگر شما درخواست تهیهٔ نسخهٔ پشتیبان را نداده‌اید، اجازه‌ ادامه عملیات را ندهید."</string>
     <string name="allow_backup_button_label" msgid="4217228747769644068">"از داده‌های من نسخهٔ پشتیبان تهیه شود"</string>
     <string name="deny_backup_button_label" msgid="6009119115581097708">"نسخهٔ پشتیبان تهیه نشود"</string>
     <string name="restore_confirm_text" msgid="7499866728030461776">"بازیابی کامل تمام داده‌ها از یک رایانه دسک تاپ متصل درخواست شده است. آیا می‌خواهید این اجازه را بدهید؟"\n\n"اگر خود شما درخواست بازیابی نداده‌اید، اجازه ادامه این عملیات را ندهید. با این کار همه داده‌هایی که اکنون روی دستگاه است جایگزین می‌شود!"</string>
diff --git a/packages/BackupRestoreConfirmation/res/values-hi/strings.xml b/packages/BackupRestoreConfirmation/res/values-hi/strings.xml
index ccac982..1495f8e 100644
--- a/packages/BackupRestoreConfirmation/res/values-hi/strings.xml
+++ b/packages/BackupRestoreConfirmation/res/values-hi/strings.xml
@@ -24,12 +24,12 @@
     <string name="restore_confirm_text" msgid="7499866728030461776">"कनेक्‍ट कि‍ए गए डेस्‍कटॉप कंप्‍यूटर से सभी डेटा की पूर्ण पुनर्स्थापना का अनुरोध कि‍या गया है. क्‍या आप इसकी अनुमति‍ देना चाहते हैं?"\n\n"यदि‍ आपने स्‍वयं पुनर्प्राप्ति‍ का अनुरोध नहीं कि‍या है, तो प्रक्रि‍या जारी रखने की अनुमति‍ न दें. इससे वर्तमान में आपके उपकरण पर मौजूद डेटा बदल जाएगा!"</string>
     <string name="allow_restore_button_label" msgid="3081286752277127827">"मेरा डेटा पुनर्स्थापित करें"</string>
     <string name="deny_restore_button_label" msgid="1724367334453104378">"पुनर्स्‍थापित न करें"</string>
-    <string name="current_password_text" msgid="8268189555578298067">"कृपया नीचे अपना वर्तमान बैकअप पासवर्ड दर्ज करें:"</string>
-    <string name="device_encryption_restore_text" msgid="1570864916855208992">"कृपया नीचे अपना उपकरण एन्‍क्रिप्शन पासवर्ड दर्ज करें."</string>
+    <string name="current_password_text" msgid="8268189555578298067">"कृपया नीचे अपना वर्तमान बैकअप पासवर्ड डालें:"</string>
+    <string name="device_encryption_restore_text" msgid="1570864916855208992">"कृपया नीचे अपना उपकरण एन्‍क्रिप्शन पासवर्ड डालें."</string>
     <string name="device_encryption_backup_text" msgid="5866590762672844664">"कृपया अपना उपकरण एन्क्रिप्शन पासवर्ड नीचे दर्ज करें. बैकअप संग्रहण को एन्‍क्रिप्‍ट करने के लिए भी इसका उपयोग किया जाएगा."</string>
-    <string name="backup_enc_password_text" msgid="4981585714795233099">"कृपया संपूर्ण बैकअप डेटा को एन्‍क्रि‍प्‍ट करने में उपयोग के लि‍ए पासवर्ड दर्ज करें. यदि‍ यह खाली छोड़ दि‍या जाता है, तो आपके वर्तमान बैकअप पासवर्ड का उपयोग कि‍या जाएगा:"</string>
-    <string name="backup_enc_password_optional" msgid="1350137345907579306">"यदि‍ आप संपूर्ण बैकअप डेटा एन्‍क्रि‍प्‍ट करना चाहते हैं, तो नीचे पासवर्ड दर्ज करें:"</string>
-    <string name="restore_enc_password_text" msgid="6140898525580710823">"यदि‍ पुनर्स्थापित डेटा को एन्‍क्रि‍प्‍ट कि‍या गया है, तो कृपया नीचे पासवर्ड दर्ज करें:"</string>
+    <string name="backup_enc_password_text" msgid="4981585714795233099">"कृपया संपूर्ण बैकअप डेटा को एन्‍क्रि‍प्‍ट करने में उपयोग के लि‍ए पासवर्ड डालें. यदि‍ यह खाली छोड़ दि‍या जाता है, तो आपके वर्तमान बैकअप पासवर्ड का उपयोग कि‍या जाएगा:"</string>
+    <string name="backup_enc_password_optional" msgid="1350137345907579306">"यदि‍ आप संपूर्ण बैकअप डेटा एन्‍क्रि‍प्‍ट करना चाहते हैं, तो नीचे पासवर्ड डालें:"</string>
+    <string name="restore_enc_password_text" msgid="6140898525580710823">"यदि‍ पुनर्स्थापित डेटा को एन्‍क्रि‍प्‍ट कि‍या गया है, तो कृपया नीचे पासवर्ड डालें:"</string>
     <string name="toast_backup_started" msgid="550354281452756121">"बैकअप प्रारंभ हो रहा है..."</string>
     <string name="toast_backup_ended" msgid="3818080769548726424">"बैकअप पूर्ण"</string>
     <string name="toast_restore_started" msgid="7881679218971277385">"पुनर्स्‍थापना प्रारंभ हो रही है..."</string>
diff --git a/packages/BackupRestoreConfirmation/res/values-pt-rPT/strings.xml b/packages/BackupRestoreConfirmation/res/values-pt-rPT/strings.xml
index 9540300..a486f54 100644
--- a/packages/BackupRestoreConfirmation/res/values-pt-rPT/strings.xml
+++ b/packages/BackupRestoreConfirmation/res/values-pt-rPT/strings.xml
@@ -18,15 +18,15 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="backup_confirm_title" msgid="827563724209303345">"Cópia de segurança completa"</string>
     <string name="restore_confirm_title" msgid="5469365809567486602">"Restauro completo"</string>
-    <string name="backup_confirm_text" msgid="1878021282758896593">"Foi solicitada uma cópia de segurança completa de todos os dados para um computador de secretária. Pretende permitir esta operação?"\n\n"Caso não tenha solicitado a cópia de segurança, não permita que a operação prossiga."</string>
+    <string name="backup_confirm_text" msgid="1878021282758896593">"Foi solicitada uma cópia de segurança completa de todos os dados para um computador. Pretende permitir esta operação?"\n\n"Caso não tenha solicitado a cópia de segurança, não permita que a operação prossiga."</string>
     <string name="allow_backup_button_label" msgid="4217228747769644068">"Fazer cópia de seg. dos dados"</string>
     <string name="deny_backup_button_label" msgid="6009119115581097708">"Não efetuar cópia de seg."</string>
-    <string name="restore_confirm_text" msgid="7499866728030461776">"Foi solicitado um restauro completo de todos os dados a partir de um computador de secretária. Pretende permitir esta operação?"\n\n"Caso não tenha solicitado o restauro, não permita que a operação prossiga. Isto substituirá os dados existentes no aparelho!"</string>
+    <string name="restore_confirm_text" msgid="7499866728030461776">"Foi solicitado um restauro completo de todos os dados a partir de um computador. Pretende permitir esta operação?"\n\n"Caso não tenha solicitado o restauro, não permita que a operação prossiga. Isto substituirá os dados existentes no equipamento!"</string>
     <string name="allow_restore_button_label" msgid="3081286752277127827">"Restaurar os meus dados"</string>
     <string name="deny_restore_button_label" msgid="1724367334453104378">"Não restaurar"</string>
     <string name="current_password_text" msgid="8268189555578298067">"Introduza a palavra-passe de cópia de segurança atual abaixo:"</string>
-    <string name="device_encryption_restore_text" msgid="1570864916855208992">"Introduza a palavra-passe de encriptação do aparelho abaixo."</string>
-    <string name="device_encryption_backup_text" msgid="5866590762672844664">"Introduza a palavra-passe de encriptação do aparelho abaixo. Esta também será utilizada para encriptar o arquivo da cópia de segurança."</string>
+    <string name="device_encryption_restore_text" msgid="1570864916855208992">"Introduza a palavra-passe de encriptação do dispositivo abaixo."</string>
+    <string name="device_encryption_backup_text" msgid="5866590762672844664">"Introduza a palavra-passe de encriptação do dispositivo abaixo. Esta também será utilizada para encriptar o arquivo da cópia de segurança."</string>
     <string name="backup_enc_password_text" msgid="4981585714795233099">"Introduza uma palavra-passe a utilizar para encriptar os dados da cópia de segurança completa. Se deixar o campo em branco, será utilizada a palavra-passe de cópia de segurança atual."</string>
     <string name="backup_enc_password_optional" msgid="1350137345907579306">"Se pretender encriptar os dados da cópia de segurança completa, introduza uma palavra-passe abaixo:"</string>
     <string name="restore_enc_password_text" msgid="6140898525580710823">"Se os dados a restaurar estiverem encriptados, introduza a palavra-passe abaixo:"</string>
diff --git a/packages/BackupRestoreConfirmation/res/values-ru/strings.xml b/packages/BackupRestoreConfirmation/res/values-ru/strings.xml
index 98b8bfc..dfbcff1 100644
--- a/packages/BackupRestoreConfirmation/res/values-ru/strings.xml
+++ b/packages/BackupRestoreConfirmation/res/values-ru/strings.xml
@@ -32,7 +32,7 @@
     <string name="restore_enc_password_text" msgid="6140898525580710823">"Если восстановленные данные зашифрованы, введите пароль:"</string>
     <string name="toast_backup_started" msgid="550354281452756121">"Резервное копирование..."</string>
     <string name="toast_backup_ended" msgid="3818080769548726424">"Резервное копирование завершено"</string>
-    <string name="toast_restore_started" msgid="7881679218971277385">"Восстановление..."</string>
+    <string name="toast_restore_started" msgid="7881679218971277385">"Копирование..."</string>
     <string name="toast_restore_ended" msgid="1764041639199696132">"Восстановление завершено"</string>
     <string name="toast_timeout" msgid="5276598587087626877">"Время ожидания истекло"</string>
 </resources>
diff --git a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
index 9da883a..a1c5650 100644
--- a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
+++ b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
@@ -31,7 +31,6 @@
 import android.renderscript.Matrix4f;
 import android.service.wallpaper.WallpaperService;
 import android.util.Log;
-import android.view.Display;
 import android.view.MotionEvent;
 import android.view.SurfaceHolder;
 import android.view.WindowManager;
@@ -41,7 +40,6 @@
 import javax.microedition.khronos.egl.EGLContext;
 import javax.microedition.khronos.egl.EGLDisplay;
 import javax.microedition.khronos.egl.EGLSurface;
-import javax.microedition.khronos.opengles.GL;
 import java.io.IOException;
 import java.nio.ByteBuffer;
 import java.nio.ByteOrder;
@@ -93,6 +91,7 @@
         return "1".equals(SystemProperties.get(PROPERTY_KERNEL_QEMU, "0"));
     }
 
+    @Override
     public Engine onCreateEngine() {
         mEngine = new DrawableEngine();
         return mEngine;
@@ -102,8 +101,6 @@
         static final int EGL_CONTEXT_CLIENT_VERSION = 0x3098;
         static final int EGL_OPENGL_ES2_BIT = 4;
 
-        private final Object mLock = new Object[0];
-
         // TODO: Not currently used, keeping around until we know we don't need it
         @SuppressWarnings({"UnusedDeclaration"})
         private WallpaperObserver mReceiver;
@@ -125,7 +122,6 @@
         private EGLConfig mEglConfig;
         private EGLContext mEglContext;
         private EGLSurface mEglSurface;
-        private GL mGL;
 
         private static final String sSimpleVS =
                 "attribute vec4 position;\n" +
@@ -150,17 +146,16 @@
         private static final int TRIANGLE_VERTICES_DATA_UV_OFFSET = 3;
 
         class WallpaperObserver extends BroadcastReceiver {
+            @Override
             public void onReceive(Context context, Intent intent) {
                 if (DEBUG) {
                     Log.d(TAG, "onReceive");
                 }
 
-                synchronized (mLock) {
-                    mLastSurfaceWidth = mLastSurfaceHeight = -1;
-                    mBackground = null;
-                    mRedrawNeeded = true;
-                    drawFrameLocked();
-                }
+                mLastSurfaceWidth = mLastSurfaceHeight = -1;
+                mBackground = null;
+                mRedrawNeeded = true;
+                drawFrame();
             }
         }
 
@@ -234,14 +229,12 @@
                 Log.d(TAG, "onVisibilityChanged: mVisible, visible=" + mVisible + ", " + visible);
             }
 
-            synchronized (mLock) {
-                if (mVisible != visible) {
-                    if (DEBUG) {
-                        Log.d(TAG, "Visibility changed to visible=" + visible);
-                    }
-                    mVisible = visible;
-                    drawFrameLocked();
+            if (mVisible != visible) {
+                if (DEBUG) {
+                    Log.d(TAG, "Visibility changed to visible=" + visible);
                 }
+                mVisible = visible;
+                drawFrame();
             }
         }
 
@@ -260,17 +253,15 @@
                         + ", xPixels=" + xPixels + ", yPixels=" + yPixels);
             }
 
-            synchronized (mLock) {
-                if (mXOffset != xOffset || mYOffset != yOffset) {
-                    if (DEBUG) {
-                        Log.d(TAG, "Offsets changed to (" + xOffset + "," + yOffset + ").");
-                    }
-                    mXOffset = xOffset;
-                    mYOffset = yOffset;
-                    mOffsetsChanged = true;
+            if (mXOffset != xOffset || mYOffset != yOffset) {
+                if (DEBUG) {
+                    Log.d(TAG, "Offsets changed to (" + xOffset + "," + yOffset + ").");
                 }
-                drawFrameLocked();
+                mXOffset = xOffset;
+                mYOffset = yOffset;
+                mOffsetsChanged = true;
             }
+            drawFrame();
         }
 
         @Override
@@ -281,9 +272,7 @@
 
             super.onSurfaceChanged(holder, format, width, height);
 
-            synchronized (mLock) {
-                drawFrameLocked();
-            }
+            drawFrame();
         }
 
         @Override
@@ -305,12 +294,10 @@
             }
             super.onSurfaceRedrawNeeded(holder);
 
-            synchronized (mLock) {
-                drawFrameLocked();
-            }
+            drawFrame();
         }
 
-        void drawFrameLocked() {
+        void drawFrame() {
             SurfaceHolder sh = getSurfaceHolder();
             final Rect frame = sh.getSurfaceFrame();
             final int dw = frame.width();
@@ -657,8 +644,6 @@
                 throw new RuntimeException("eglMakeCurrent failed " +
                         GLUtils.getEGLErrorString(mEgl.eglGetError()));
             }
-    
-            mGL = mEglContext.getGL();
 
             return true;
         }
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
index f25ac0d..03de89bd 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
@@ -82,6 +82,7 @@
     private static final String SCREENSHOTS_DIR_NAME = "Screenshots";
     private static final String SCREENSHOT_FILE_NAME_TEMPLATE = "Screenshot_%s.png";
     private static final String SCREENSHOT_FILE_PATH_TEMPLATE = "%s/%s/%s";
+    private static final String SCREENSHOT_SHARE_SUBJECT_TEMPLATE = "Screenshot (%s)";
 
     private int mNotificationId;
     private NotificationManager mNotificationManager;
@@ -90,6 +91,8 @@
     private String mImageFilePath;
     private long mImageTime;
     private BigPictureStyle mNotificationStyle;
+    private int mImageWidth;
+    private int mImageHeight;
 
     // WORKAROUND: We want the same notification across screenshots that we update so that we don't
     // spam a user's notification drawer.  However, we only show the ticker for the saving state
@@ -112,11 +115,11 @@
                 SCREENSHOTS_DIR_NAME, mImageFileName);
 
         // Create the large notification icon
-        int imageWidth = data.image.getWidth();
-        int imageHeight = data.image.getHeight();
+        mImageWidth = data.image.getWidth();
+        mImageHeight = data.image.getHeight();
         int iconSize = data.iconSize;
 
-        final int shortSide = imageWidth < imageHeight ? imageWidth : imageHeight;
+        final int shortSide = mImageWidth < mImageHeight ? mImageWidth : mImageHeight;
         Bitmap preview = Bitmap.createBitmap(shortSide, shortSide, data.image.getConfig());
         Canvas c = new Canvas(preview);
         Paint paint = new Paint();
@@ -124,8 +127,8 @@
         desat.setSaturation(0.25f);
         paint.setColorFilter(new ColorMatrixColorFilter(desat));
         Matrix matrix = new Matrix();
-        matrix.postTranslate((shortSide - imageWidth) / 2,
-                            (shortSide - imageHeight) / 2);
+        matrix.postTranslate((shortSide - mImageWidth) / 2,
+                            (shortSide - mImageHeight) / 2);
         c.drawBitmap(data.image, matrix, paint);
         c.drawColor(0x40FFFFFF);
 
@@ -182,11 +185,17 @@
             values.put(MediaStore.Images.ImageColumns.DATE_ADDED, mImageTime);
             values.put(MediaStore.Images.ImageColumns.DATE_MODIFIED, mImageTime);
             values.put(MediaStore.Images.ImageColumns.MIME_TYPE, "image/png");
+            values.put(MediaStore.Images.ImageColumns.WIDTH, mImageWidth);
+            values.put(MediaStore.Images.ImageColumns.HEIGHT, mImageHeight);
             Uri uri = resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
 
+            String subjectDate = new SimpleDateFormat("hh:mma, MMM dd, yyyy")
+                .format(new Date(mImageTime));
+            String subject = String.format(SCREENSHOT_SHARE_SUBJECT_TEMPLATE, subjectDate);
             Intent sharingIntent = new Intent(Intent.ACTION_SEND);
             sharingIntent.setType("image/png");
             sharingIntent.putExtra(Intent.EXTRA_STREAM, uri);
+            sharingIntent.putExtra(Intent.EXTRA_SUBJECT, subject);
 
             Intent chooserIntent = Intent.createChooser(sharingIntent, null);
             chooserIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK 
@@ -600,14 +609,17 @@
         Resources r = context.getResources();
 
         // Clear all existing notification, compose the new notification and show it
-        Notification n = new Notification.Builder(context)
+        Notification.Builder b = new Notification.Builder(context)
             .setTicker(r.getString(R.string.screenshot_failed_title))
             .setContentTitle(r.getString(R.string.screenshot_failed_title))
             .setContentText(r.getString(R.string.screenshot_failed_text))
             .setSmallIcon(R.drawable.stat_notify_image_error)
             .setWhen(System.currentTimeMillis())
-            .setAutoCancel(true)
-            .getNotification();
+            .setAutoCancel(true);
+        Notification n =
+            new Notification.BigTextStyle(b)
+                .bigText(r.getString(R.string.screenshot_failed_text))
+                .build();
         nManager.notify(SCREENSHOT_NOTIFICATION_ID, n);
     }
 }
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index d9c07f8..9acdd99 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -1055,7 +1055,7 @@
         } else {
             mHdmiRotation = mLandscapeRotation;
         }
-        mHdmiRotationLock = SystemProperties.getBoolean("persist.demo.hdmirotationlock", true);
+        mHdmiRotationLock = SystemProperties.getBoolean("persist.demo.hdmirotationlock", false);
     }
 
     public void updateSettings() {
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewManager.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewManager.java
index 4e8aba7..76ba811 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewManager.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewManager.java
@@ -129,19 +129,12 @@
         @Override
         protected void onConfigurationChanged(Configuration newConfig) {
             super.onConfigurationChanged(newConfig);
-            post(new Runnable() {
-                @Override
-                public void run() {
-                    synchronized (KeyguardViewManager.this) {
-                        if (mKeyguardHost.getVisibility() == View.VISIBLE) {
-                            // only propagate configuration messages if we're currently showing
-                            maybeCreateKeyguardLocked(shouldEnableScreenRotation(), true, null);
-                        } else {
-                            if (DEBUG) Log.v(TAG, "onConfigurationChanged: view not visible");
-                        }
-                    }
-                }
-            });
+            if (mKeyguardHost.getVisibility() == View.VISIBLE) {
+                // only propagate configuration messages if we're currently showing
+                maybeCreateKeyguardLocked(shouldEnableScreenRotation(), true, null);
+            } else {
+                if (DEBUG) Log.v(TAG, "onConfigurationChanged: view not visible");
+            }
         }
 
         @Override
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java
index a7c4d73..4c22ae8 100644
--- a/services/java/com/android/server/ConnectivityService.java
+++ b/services/java/com/android/server/ConnectivityService.java
@@ -2524,19 +2524,19 @@
             SystemProperties.set(key, "");
         }
         mNumDnsEntries = last;
+        if (SystemProperties.get("net.dns.search").equals(domains) == false) {
+            SystemProperties.set("net.dns.search", domains);
+            changed = true;
+        }
 
         if (changed) {
             try {
-                mNetd.setDnsServersForInterface(iface, NetworkUtils.makeStrings(dnses));
+                mNetd.setDnsServersForInterface(iface, NetworkUtils.makeStrings(dnses), domains);
                 mNetd.setDefaultInterfaceForDns(iface);
             } catch (Exception e) {
                 if (DBG) loge("exception setting default dns interface: " + e);
             }
         }
-        if (!domains.equals(SystemProperties.get("net.dns.search"))) {
-            SystemProperties.set("net.dns.search", domains);
-            changed = true;
-        }
         return changed;
     }
 
@@ -2552,13 +2552,13 @@
                 String network = nt.getNetworkInfo().getTypeName();
                 synchronized (mDnsLock) {
                     if (!mDnsOverridden) {
-                        changed = updateDns(network, p.getInterfaceName(), dnses, "");
+                        changed = updateDns(network, p.getInterfaceName(), dnses, p.getDomains());
                     }
                 }
             } else {
                 try {
                     mNetd.setDnsServersForInterface(p.getInterfaceName(),
-                            NetworkUtils.makeStrings(dnses));
+                            NetworkUtils.makeStrings(dnses), p.getDomains());
                 } catch (Exception e) {
                     if (DBG) loge("exception setting dns servers: " + e);
                 }
diff --git a/services/java/com/android/server/InputMethodManagerService.java b/services/java/com/android/server/InputMethodManagerService.java
index c33fc71..85bc259 100644
--- a/services/java/com/android/server/InputMethodManagerService.java
+++ b/services/java/com/android/server/InputMethodManagerService.java
@@ -2660,6 +2660,8 @@
                                 }
                                 InputMethodInfo im = mIms[which];
                                 int subtypeId = mSubtypeIds[which];
+                                adapter.mCheckedItem = which;
+                                adapter.notifyDataSetChanged();
                                 hideInputMethodMenu();
                                 if (im != null) {
                                     if ((subtypeId < 0)
@@ -2757,7 +2759,7 @@
         private final LayoutInflater mInflater;
         private final int mTextViewResourceId;
         private final List<ImeSubtypeListItem> mItemsList;
-        private final int mCheckedItem;
+        public int mCheckedItem;
         public ImeSubtypeListAdapter(Context context, int textViewResourceId,
                 List<ImeSubtypeListItem> itemsList, int checkedItem) {
             super(context, textViewResourceId, itemsList);
diff --git a/services/java/com/android/server/NetworkManagementService.java b/services/java/com/android/server/NetworkManagementService.java
index 3ddae3e..9ce02e3 100644
--- a/services/java/com/android/server/NetworkManagementService.java
+++ b/services/java/com/android/server/NetworkManagementService.java
@@ -1398,10 +1398,12 @@
     }
 
     @Override
-    public void setDnsServersForInterface(String iface, String[] servers) {
+    public void setDnsServersForInterface(String iface, String[] servers, String domains) {
         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
 
-        final Command cmd = new Command("resolver", "setifdns", iface);
+        final Command cmd = new Command("resolver", "setifdns", iface,
+                (domains == null ? "" : domains));
+
         for (String s : servers) {
             InetAddress a = NetworkUtils.numericToInetAddress(s);
             if (a.isAnyLocalAddress() == false) {
diff --git a/services/java/com/android/server/NetworkTimeUpdateService.java b/services/java/com/android/server/NetworkTimeUpdateService.java
index 790be55..3bfd190 100644
--- a/services/java/com/android/server/NetworkTimeUpdateService.java
+++ b/services/java/com/android/server/NetworkTimeUpdateService.java
@@ -57,15 +57,6 @@
     private static final int EVENT_POLL_NETWORK_TIME = 2;
     private static final int EVENT_NETWORK_CONNECTED = 3;
 
-    /** Normal polling frequency */
-    private static final long POLLING_INTERVAL_MS = 24L * 60 * 60 * 1000; // 24 hrs
-    /** Try-again polling interval, in case the network request failed */
-    private static final long POLLING_INTERVAL_SHORTER_MS = 60 * 1000L; // 60 seconds
-    /** Number of times to try again */
-    private static final int TRY_AGAIN_TIMES_MAX = 3;
-    /** If the time difference is greater than this threshold, then update the time. */
-    private static final int TIME_ERROR_THRESHOLD_MS = 5 * 1000;
-
     private static final String ACTION_POLL =
             "com.android.server.NetworkTimeUpdateService.action.POLL";
     private static int POLL_REQUEST = 0;
@@ -86,6 +77,15 @@
     private SettingsObserver mSettingsObserver;
     // The last time that we successfully fetched the NTP time.
     private long mLastNtpFetchTime = NOT_SET;
+
+    // Normal polling frequency
+    private final long mPollingIntervalMs;
+    // Try-again polling interval, in case the network request failed
+    private final long mPollingIntervalShorterMs;
+    // Number of times to try again
+    private final int mTryAgainTimesMax;
+    // If the time difference is greater than this threshold, then update the time.
+    private final int mTimeErrorThresholdMs;
     // Keeps track of how many quick attempts were made to fetch NTP time.
     // During bootup, the network may not have been up yet, or it's taking time for the
     // connection to happen.
@@ -97,6 +97,15 @@
         mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
         Intent pollIntent = new Intent(ACTION_POLL, null);
         mPendingPollIntent = PendingIntent.getBroadcast(mContext, POLL_REQUEST, pollIntent, 0);
+
+        mPollingIntervalMs = mContext.getResources().getInteger(
+                com.android.internal.R.integer.config_ntpPollingInterval);
+        mPollingIntervalShorterMs = mContext.getResources().getInteger(
+                com.android.internal.R.integer.config_ntpPollingIntervalShorter);
+        mTryAgainTimesMax = mContext.getResources().getInteger(
+                com.android.internal.R.integer.config_ntpRetry);
+        mTimeErrorThresholdMs = mContext.getResources().getInteger(
+                com.android.internal.R.integer.config_ntpThreshold);
     }
 
     /** Initialize the receivers and initiate the first NTP request */
@@ -143,35 +152,35 @@
         if (!isAutomaticTimeRequested()) return;
 
         final long refTime = SystemClock.elapsedRealtime();
-        // If NITZ time was received less than POLLING_INTERVAL_MS time ago,
+        // If NITZ time was received less than mPollingIntervalMs time ago,
         // no need to sync to NTP.
-        if (mNitzTimeSetTime != NOT_SET && refTime - mNitzTimeSetTime < POLLING_INTERVAL_MS) {
-            resetAlarm(POLLING_INTERVAL_MS);
+        if (mNitzTimeSetTime != NOT_SET && refTime - mNitzTimeSetTime < mPollingIntervalMs) {
+            resetAlarm(mPollingIntervalMs);
             return;
         }
         final long currentTime = System.currentTimeMillis();
         if (DBG) Log.d(TAG, "System time = " + currentTime);
         // Get the NTP time
-        if (mLastNtpFetchTime == NOT_SET || refTime >= mLastNtpFetchTime + POLLING_INTERVAL_MS
+        if (mLastNtpFetchTime == NOT_SET || refTime >= mLastNtpFetchTime + mPollingIntervalMs
                 || event == EVENT_AUTO_TIME_CHANGED) {
             if (DBG) Log.d(TAG, "Before Ntp fetch");
 
             // force refresh NTP cache when outdated
-            if (mTime.getCacheAge() >= POLLING_INTERVAL_MS) {
+            if (mTime.getCacheAge() >= mPollingIntervalMs) {
                 mTime.forceRefresh();
             }
 
             // only update when NTP time is fresh
-            if (mTime.getCacheAge() < POLLING_INTERVAL_MS) {
+            if (mTime.getCacheAge() < mPollingIntervalMs) {
                 final long ntp = mTime.currentTimeMillis();
                 mTryAgainCounter = 0;
                 // If the clock is more than N seconds off or this is the first time it's been
                 // fetched since boot, set the current time.
-                if (Math.abs(ntp - currentTime) > TIME_ERROR_THRESHOLD_MS
+                if (Math.abs(ntp - currentTime) > mTimeErrorThresholdMs
                         || mLastNtpFetchTime == NOT_SET) {
                     // Set the system time
                     if (DBG && mLastNtpFetchTime == NOT_SET
-                            && Math.abs(ntp - currentTime) <= TIME_ERROR_THRESHOLD_MS) {
+                            && Math.abs(ntp - currentTime) <= mTimeErrorThresholdMs) {
                         Log.d(TAG, "For initial setup, rtc = " + currentTime);
                     }
                     if (DBG) Log.d(TAG, "Ntp time to be set = " + ntp);
@@ -186,17 +195,17 @@
             } else {
                 // Try again shortly
                 mTryAgainCounter++;
-                if (mTryAgainCounter <= TRY_AGAIN_TIMES_MAX) {
-                    resetAlarm(POLLING_INTERVAL_SHORTER_MS);
+                if (mTryAgainTimesMax < 0 || mTryAgainCounter <= mTryAgainTimesMax) {
+                    resetAlarm(mPollingIntervalShorterMs);
                 } else {
                     // Try much later
                     mTryAgainCounter = 0;
-                    resetAlarm(POLLING_INTERVAL_MS);
+                    resetAlarm(mPollingIntervalMs);
                 }
                 return;
             }
         }
-        resetAlarm(POLLING_INTERVAL_MS);
+        resetAlarm(mPollingIntervalMs);
     }
 
     /**
diff --git a/services/java/com/android/server/SerialService.java b/services/java/com/android/server/SerialService.java
index 5d2b2a0..1abe458 100644
--- a/services/java/com/android/server/SerialService.java
+++ b/services/java/com/android/server/SerialService.java
@@ -51,7 +51,12 @@
 
     public ParcelFileDescriptor openSerialPort(String path) {
         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.SERIAL_PORT, null);
-        return native_open(path);
+        for (int i = 0; i < mSerialPorts.length; i++) {
+            if (mSerialPorts[i].equals(path)) {
+                return native_open(path);
+            }
+        }
+        throw new IllegalArgumentException("Invalid serial port " + path);
     }
 
     private native ParcelFileDescriptor native_open(String path);
diff --git a/services/java/com/android/server/WifiService.java b/services/java/com/android/server/WifiService.java
index 98794c9..2da951e 100644
--- a/services/java/com/android/server/WifiService.java
+++ b/services/java/com/android/server/WifiService.java
@@ -43,9 +43,14 @@
 import android.net.wifi.WpsResult;
 import android.net.ConnectivityManager;
 import android.net.DhcpInfo;
+import android.net.DhcpResults;
+import android.net.LinkAddress;
+import android.net.LinkProperties;
 import android.net.NetworkInfo;
 import android.net.NetworkInfo.State;
 import android.net.NetworkInfo.DetailedState;
+import android.net.NetworkUtils;
+import android.net.RouteInfo;
 import android.net.TrafficStats;
 import android.os.Binder;
 import android.os.Handler;
@@ -64,6 +69,8 @@
 import android.util.Log;
 import android.util.Slog;
 
+import java.net.InetAddress;
+import java.net.Inet4Address;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
@@ -923,10 +930,53 @@
      * Return the DHCP-assigned addresses from the last successful DHCP request,
      * if any.
      * @return the DHCP information
+     * @deprecated
      */
     public DhcpInfo getDhcpInfo() {
         enforceAccessPermission();
-        return mWifiStateMachine.syncGetDhcpInfo();
+        DhcpResults dhcpResults = mWifiStateMachine.syncGetDhcpResults();
+        if (dhcpResults.linkProperties == null) return null;
+
+        DhcpInfo info = new DhcpInfo();
+        for (LinkAddress la : dhcpResults.linkProperties.getLinkAddresses()) {
+            InetAddress addr = la.getAddress();
+            if (addr instanceof Inet4Address) {
+                info.ipAddress = NetworkUtils.inetAddressToInt((Inet4Address)addr);
+                break;
+            }
+        }
+        for (RouteInfo r : dhcpResults.linkProperties.getRoutes()) {
+            if (r.isDefaultRoute()) {
+                InetAddress gateway = r.getGateway();
+                if (gateway instanceof Inet4Address) {
+                    info.gateway = NetworkUtils.inetAddressToInt((Inet4Address)gateway);
+                }
+            } else if (r.isHostRoute()) {
+                LinkAddress dest = r.getDestination();
+                if (dest.getAddress() instanceof Inet4Address) {
+                    info.netmask = NetworkUtils.prefixLengthToNetmaskInt(
+                            dest.getNetworkPrefixLength());
+                }
+            }
+        }
+        int dnsFound = 0;
+        for (InetAddress dns : dhcpResults.linkProperties.getDnses()) {
+            if (dns instanceof Inet4Address) {
+                if (dnsFound == 0) {
+                    info.dns1 = NetworkUtils.inetAddressToInt((Inet4Address)dns);
+                } else {
+                    info.dns2 = NetworkUtils.inetAddressToInt((Inet4Address)dns);
+                }
+                if (++dnsFound > 1) break;
+            }
+        }
+        InetAddress serverAddress = dhcpResults.serverAddress;
+        if (serverAddress instanceof Inet4Address) {
+            info.serverAddress = NetworkUtils.inetAddressToInt((Inet4Address)serverAddress);
+        }
+        info.leaseDuration = dhcpResults.leaseDuration;
+
+        return info;
     }
 
     /**
diff --git a/services/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/java/com/android/server/accessibility/AccessibilityManagerService.java
index 671cbfe..65bfa7e 100644
--- a/services/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -87,7 +87,9 @@
 
 import org.xmlpull.v1.XmlPullParserException;
 
+import java.io.FileDescriptor;
 import java.io.IOException;
+import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashMap;
@@ -122,6 +124,8 @@
     private static final String TEMPORARY_ENABLE_ACCESSIBILITY_UNTIL_KEYGUARD_REMOVED =
             "temporaryEnableAccessibilityStateUntilKeyguardRemoved";
 
+    private static final String FUNCTION_DUMP = "dump";
+
     private static final char COMPONENT_NAME_SEPARATOR = ':';
 
     private static final int OWN_PROCESS_ID = android.os.Process.myPid();
@@ -1258,6 +1262,46 @@
         }
     }
 
+    @Override
+    public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) {
+        mSecurityPolicy.enforceCallingPermission(Manifest.permission.DUMP, FUNCTION_DUMP);
+        synchronized (mLock) {
+            pw.println("ACCESSIBILITY MANAGER (dumpsys accessibility)");
+            pw.println();
+            pw.println("Ui automation service: bound=" + (mUiAutomationService != null));
+            pw.println();
+            if (mUiAutomationService != null) {
+                mUiAutomationService.dump(fd, pw, args);
+                pw.println();
+            }
+            final int userCount = mUserStates.size();
+            for (int i = 0; i < userCount; i++) {
+                UserState userState = mUserStates.valueAt(i);
+                pw.append("User state[attributes:{id=" + userState.mUserId);
+                pw.append(", currentUser=" + (userState.mUserId == mCurrentUserId));
+                pw.append(", accessibilityEnabled=" + userState.mIsAccessibilityEnabled);
+                pw.append(", touchExplorationEnabled=" + userState.mIsTouchExplorationEnabled);
+                pw.append(", displayMagnificationEnabled="
+                        + userState.mIsDisplayMagnificationEnabled);
+                pw.append("}");
+                pw.println();
+                pw.append("           services:{");
+                final int serviceCount = userState.mServices.size();
+                for (int j = 0; j < serviceCount; j++) {
+                    if (j > 0) {
+                        pw.append(", ");
+                        pw.println();
+                        pw.append("                     ");
+                    }
+                    Service service = userState.mServices.get(j);
+                    service.dump(fd, pw, args);
+                }
+                pw.println("}]");
+                pw.println();
+            }
+        }
+    }
+
     private class AccessibilityConnectionWrapper implements DeathRecipient {
         private final int mWindowId;
         private final int mUserId;
@@ -1894,6 +1938,23 @@
             }
         }
 
+        @Override
+        public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) {
+            mSecurityPolicy.enforceCallingPermission(Manifest.permission.DUMP, FUNCTION_DUMP);
+            synchronized (mLock) {
+                pw.append("Service[label=" + mAccessibilityServiceInfo.getResolveInfo()
+                        .loadLabel(mContext.getPackageManager()));
+                pw.append(", feedbackType"
+                        + AccessibilityServiceInfo.feedbackTypeToString(mFeedbackType));
+                pw.append(", canRetrieveScreenContent=" + mCanRetrieveScreenContent);
+                pw.append(", eventTypes="
+                        + AccessibilityEvent.eventTypeToString(mEventTypes));
+                pw.append(", notificationTimeout=" + mNotificationTimeout);
+                pw.append("]");
+            }
+        }
+
+        @Override
         public void onServiceDisconnected(ComponentName componentName) {
             /* do nothing - #binderDied takes care */
         }
@@ -2313,7 +2374,8 @@
             }
             if (!hasPermission(permission)) {
                 throw new SecurityException("You do not have " + permission
-                        + " required to call " + function);
+                        + " required to call " + function + " from pid="
+                        + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid());
             }
         }
 
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index db64a9a..f527cc2 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -1423,7 +1423,7 @@
         context.setTheme(android.R.style.Theme_Holo);
         m.mContext = context;
         m.mFactoryTest = factoryTest;
-        m.mMainStack = new ActivityStack(m, context, true);
+        m.mMainStack = new ActivityStack(m, context, true, thr.mLooper);
         
         m.mBatteryStatsService.publish(context);
         m.mUsageStatsService.publish(context);
@@ -1444,6 +1444,7 @@
     
     static class AThread extends Thread {
         ActivityManagerService mService;
+        Looper mLooper;
         boolean mReady = false;
 
         public AThread() {
@@ -1461,6 +1462,7 @@
 
             synchronized (this) {
                 mService = m;
+                mLooper = Looper.myLooper();
                 notifyAll();
             }
 
diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java
index 4546dc3..b007bc8 100644
--- a/services/java/com/android/server/am/ActivityStack.java
+++ b/services/java/com/android/server/am/ActivityStack.java
@@ -49,6 +49,7 @@
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.IBinder;
+import android.os.Looper;
 import android.os.Message;
 import android.os.ParcelFileDescriptor;
 import android.os.PowerManager;
@@ -306,11 +307,17 @@
         }
     }
 
-    final Handler mHandler = new Handler() {
+    final Handler mHandler;
+
+    final class ActivityStackHandler extends Handler {
         //public Handler() {
         //    if (localLOGV) Slog.v(TAG, "Handler started!");
         //}
+        public ActivityStackHandler(Looper looper) {
+            super(looper);
+        }
 
+        @Override
         public void handleMessage(Message msg) {
             switch (msg.what) {
                 case SLEEP_TIMEOUT_MSG: {
@@ -410,7 +417,8 @@
         }
     };
     
-    ActivityStack(ActivityManagerService service, Context context, boolean mainStack) {
+    ActivityStack(ActivityManagerService service, Context context, boolean mainStack, Looper looper) {
+        mHandler = new ActivityStackHandler(looper);
         mService = service;
         mContext = context;
         mMainStack = mainStack;
diff --git a/services/java/com/android/server/display/LocalDisplayAdapter.java b/services/java/com/android/server/display/LocalDisplayAdapter.java
index b37d57f..ee2d617 100644
--- a/services/java/com/android/server/display/LocalDisplayAdapter.java
+++ b/services/java/com/android/server/display/LocalDisplayAdapter.java
@@ -60,31 +60,38 @@
         super.registerLocked();
 
         mHotplugReceiver = new HotplugDisplayEventReceiver(getHandler().getLooper());
-        scanDisplaysLocked();
+
+        for (int builtInDisplayId : BUILT_IN_DISPLAY_IDS_TO_SCAN) {
+            tryConnectDisplayLocked(builtInDisplayId);
+        }
     }
 
-    private void scanDisplaysLocked() {
-        for (int builtInDisplayId : BUILT_IN_DISPLAY_IDS_TO_SCAN) {
-            IBinder displayToken = Surface.getBuiltInDisplay(builtInDisplayId);
-            if (displayToken != null && Surface.getDisplayInfo(displayToken, mTempPhys)) {
-                LocalDisplayDevice device = mDevices.get(builtInDisplayId);
-                if (device == null) {
-                    // Display was added.
-                    device = new LocalDisplayDevice(displayToken, builtInDisplayId, mTempPhys);
-                    mDevices.put(builtInDisplayId, device);
-                    sendDisplayDeviceEventLocked(device, DISPLAY_DEVICE_EVENT_ADDED);
-                } else if (device.updatePhysicalDisplayInfoLocked(mTempPhys)) {
-                    // Display properties changed.
-                    sendDisplayDeviceEventLocked(device, DISPLAY_DEVICE_EVENT_CHANGED);
-                }
-            } else {
-                LocalDisplayDevice device = mDevices.get(builtInDisplayId);
-                if (device != null) {
-                    // Display was removed.
-                    mDevices.remove(builtInDisplayId);
-                    sendDisplayDeviceEventLocked(device, DISPLAY_DEVICE_EVENT_REMOVED);
-                }
+    private void tryConnectDisplayLocked(int builtInDisplayId) {
+        IBinder displayToken = Surface.getBuiltInDisplay(builtInDisplayId);
+        if (displayToken != null && Surface.getDisplayInfo(displayToken, mTempPhys)) {
+            LocalDisplayDevice device = mDevices.get(builtInDisplayId);
+            if (device == null) {
+                // Display was added.
+                device = new LocalDisplayDevice(displayToken, builtInDisplayId, mTempPhys);
+                mDevices.put(builtInDisplayId, device);
+                sendDisplayDeviceEventLocked(device, DISPLAY_DEVICE_EVENT_ADDED);
+            } else if (device.updatePhysicalDisplayInfoLocked(mTempPhys)) {
+                // Display properties changed.
+                sendDisplayDeviceEventLocked(device, DISPLAY_DEVICE_EVENT_CHANGED);
             }
+        } else {
+            // The display is no longer available. Ignore the attempt to add it.
+            // If it was connected but has already been disconnected, we'll get a
+            // disconnect event that will remove it from mDevices.
+        }
+    }
+
+    private void tryDisconnectDisplayLocked(int builtInDisplayId) {
+        LocalDisplayDevice device = mDevices.get(builtInDisplayId);
+        if (device != null) {
+            // Display was removed.
+            mDevices.remove(builtInDisplayId);
+            sendDisplayDeviceEventLocked(device, DISPLAY_DEVICE_EVENT_REMOVED);
         }
     }
 
@@ -191,7 +198,11 @@
         @Override
         public void onHotplug(long timestampNanos, int builtInDisplayId, boolean connected) {
             synchronized (getSyncRoot()) {
-                scanDisplaysLocked();
+                if (connected) {
+                    tryConnectDisplayLocked(builtInDisplayId);
+                } else {
+                    tryDisconnectDisplayLocked(builtInDisplayId);
+                }
             }
         }
     }
diff --git a/services/java/com/android/server/location/GpsLocationProvider.java b/services/java/com/android/server/location/GpsLocationProvider.java
index c272da4..efba10d 100644
--- a/services/java/com/android/server/location/GpsLocationProvider.java
+++ b/services/java/com/android/server/location/GpsLocationProvider.java
@@ -1452,11 +1452,11 @@
     private void requestRefLocation(int flags) {
         TelephonyManager phone = (TelephonyManager)
                 mContext.getSystemService(Context.TELEPHONY_SERVICE);
-        if (phone.getPhoneType() == TelephonyManager.PHONE_TYPE_GSM) {
+        final int phoneType = phone.getPhoneType();
+        if (phoneType == TelephonyManager.PHONE_TYPE_GSM) {
             GsmCellLocation gsm_cell = (GsmCellLocation) phone.getCellLocation();
-            if ((gsm_cell != null) && (phone.getPhoneType() == TelephonyManager.PHONE_TYPE_GSM) &&
-                    (phone.getNetworkOperator() != null) &&
-                        (phone.getNetworkOperator().length() > 3)) {
+            if ((gsm_cell != null) && (phone.getNetworkOperator() != null)
+                    && (phone.getNetworkOperator().length() > 3)) {
                 int type;
                 int mcc = Integer.parseInt(phone.getNetworkOperator().substring(0,3));
                 int mnc = Integer.parseInt(phone.getNetworkOperator().substring(3));
@@ -1474,9 +1474,8 @@
             } else {
                 Log.e(TAG,"Error getting cell location info.");
             }
-        }
-        else {
-            Log.e(TAG,"CDMA not supported.");
+        } else if (phoneType == TelephonyManager.PHONE_TYPE_CDMA) {
+            Log.e(TAG, "CDMA not supported.");
         }
     }
 
diff --git a/services/java/com/android/server/power/RampAnimator.java b/services/java/com/android/server/power/RampAnimator.java
index 6f063c3..4a4f080 100644
--- a/services/java/com/android/server/power/RampAnimator.java
+++ b/services/java/com/android/server/power/RampAnimator.java
@@ -102,20 +102,26 @@
             final long frameTimeNanos = mChoreographer.getFrameTimeNanos();
             final float timeDelta = (frameTimeNanos - mLastFrameTimeNanos)
                     * 0.000000001f;
-            final float amount = timeDelta * mRate / ValueAnimator.getDurationScale();
             mLastFrameTimeNanos = frameTimeNanos;
 
             // Advance the animated value towards the target at the specified rate
             // and clamp to the target. This gives us the new current value but
             // we keep the animated value around to allow for fractional increments
             // towards the target.
-            int oldCurrentValue = mCurrentValue;
-            if (mTargetValue > mCurrentValue) {
-                mAnimatedValue = Math.min(mAnimatedValue + amount, mTargetValue);
+            final float scale = ValueAnimator.getDurationScale();
+            if (scale == 0) {
+                // Animation off.
+                mAnimatedValue = mTargetValue;
             } else {
-                mAnimatedValue = Math.max(mAnimatedValue - amount, mTargetValue);
+                final float amount = timeDelta * mRate / scale;
+                if (mTargetValue > mCurrentValue) {
+                    mAnimatedValue = Math.min(mAnimatedValue + amount, mTargetValue);
+                } else {
+                    mAnimatedValue = Math.max(mAnimatedValue - amount, mTargetValue);
+                }
             }
-            mCurrentValue = (int)Math.round(mAnimatedValue);
+            final int oldCurrentValue = mCurrentValue;
+            mCurrentValue = Math.round(mAnimatedValue);
 
             if (oldCurrentValue != mCurrentValue) {
                 mProperty.setValue(mObject, mCurrentValue);
diff --git a/services/java/com/android/server/wm/AppWindowAnimator.java b/services/java/com/android/server/wm/AppWindowAnimator.java
index ca94d04..e044c6d 100644
--- a/services/java/com/android/server/wm/AppWindowAnimator.java
+++ b/services/java/com/android/server/wm/AppWindowAnimator.java
@@ -100,6 +100,10 @@
             animInitialized = false;
         }
         clearThumbnail();
+        if (mAppToken.deferClearAllDrawn) {
+            mAppToken.allDrawn = false;
+            mAppToken.deferClearAllDrawn = false;
+        }
     }
 
     public void clearThumbnail() {
diff --git a/services/java/com/android/server/wm/AppWindowToken.java b/services/java/com/android/server/wm/AppWindowToken.java
index 7efffe5..3ec6d26 100644
--- a/services/java/com/android/server/wm/AppWindowToken.java
+++ b/services/java/com/android/server/wm/AppWindowToken.java
@@ -64,6 +64,9 @@
     int numDrawnWindows;
     boolean inPendingTransaction;
     boolean allDrawn;
+    // Set to true when this app creates a surface while in the middle of an animation. In that
+    // case do not clear allDrawn until the animation completes.
+    boolean deferClearAllDrawn;
 
     // Is this token going to be hidden in a little while?  If so, it
     // won't be taken into account for setting the screen orientation.
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index 51edb44..f8a2b0c 100644
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -821,7 +821,7 @@
         mTransitionAnimationScale = Settings.Global.getFloat(context.getContentResolver(),
                 Settings.Global.TRANSITION_ANIMATION_SCALE, mTransitionAnimationScale);
         setAnimatorDurationScale(Settings.Global.getFloat(context.getContentResolver(),
-                Settings.Global.ANIMATOR_DURATION_SCALE, mTransitionAnimationScale));
+                Settings.Global.ANIMATOR_DURATION_SCALE, mAnimatorDurationScale));
 
         // Track changes to DevicePolicyManager state so we can enable/disable keyguard.
         IntentFilter filter = new IntentFilter();
@@ -4295,6 +4295,7 @@
                         // the new one.
                         if (ttoken.allDrawn) {
                             wtoken.allDrawn = true;
+                            wtoken.deferClearAllDrawn = ttoken.deferClearAllDrawn;
                         }
                         if (ttoken.firstWindowDrawn) {
                             wtoken.firstWindowDrawn = true;
@@ -4425,6 +4426,7 @@
         }
     }
 
+    @Override
     public void setAppWillBeHidden(IBinder token) {
         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
                 "setAppWillBeHidden()")) {
@@ -4548,6 +4550,7 @@
         return delayed;
     }
 
+    @Override
     public void setAppVisibility(IBinder token, boolean visible) {
         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
                 "setAppVisibility()")) {
@@ -4602,6 +4605,7 @@
                     // its windows to be ready.
                     if (wtoken.hidden) {
                         wtoken.allDrawn = false;
+                        wtoken.deferClearAllDrawn = false;
                         wtoken.waitingToShow = true;
 
                         if (wtoken.clientHidden) {
@@ -4700,6 +4704,7 @@
         }
     }
 
+    @Override
     public void startAppFreezingScreen(IBinder token, int configChanges) {
         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
                 "setAppFreezingScreen()")) {
@@ -4723,6 +4728,7 @@
         }
     }
 
+    @Override
     public void stopAppFreezingScreen(IBinder token, boolean force) {
         if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
                 "setAppFreezingScreen()")) {
@@ -5583,7 +5589,7 @@
                 if (!mSystemBooted && !haveBootMsg) {
                     return;
                 }
-    
+
                 // If we are turning on the screen after the boot is completed
                 // normally, don't do so until we have the application and
                 // wallpaper.
@@ -5733,7 +5739,7 @@
      * Takes a snapshot of the screen.  In landscape mode this grabs the whole screen.
      * In portrait mode, it grabs the upper region of the screen based on the vertical dimension
      * of the target image.
-     * 
+     *
      * @param displayId the Display to take a screenshot of.
      * @param width the width of the target bitmap
      * @param height the height of the target bitmap
@@ -5808,7 +5814,7 @@
                 if (maxLayer < ws.mWinAnimator.mSurfaceLayer) {
                     maxLayer = ws.mWinAnimator.mSurfaceLayer;
                 }
-                
+
                 // Don't include wallpaper in bounds calculation
                 if (!ws.mIsWallpaper) {
                     final Rect wf = ws.mFrame;
@@ -8362,7 +8368,7 @@
             // soon won't be visible, to avoid wasting time and funky
             // changes while a window is animating away.
             final boolean gone = (behindDream && mPolicy.canBeForceHidden(win, win.mAttrs))
-                    || win.isGoneForLayoutLw();
+                    || (win.isGoneForLayoutLw() && !win.isOnScreen());
 
             if (DEBUG_LAYOUT && !win.mLayoutAttached) {
                 Slog.v(TAG, "1ST PASS " + win
@@ -8390,8 +8396,7 @@
             // windows, since that means "perform layout as normal,
             // just don't display").
             if (!gone || !win.mHaveFrame || win.mLayoutNeeded
-                    || ((win.mAttrs.type == TYPE_KEYGUARD || win.mAttrs.type == TYPE_WALLPAPER) &&
-                        win.isConfigChanged())
+                    || (win.mAttrs.type == TYPE_KEYGUARD && win.isConfigChanged())
                     || win.mAttrs.type == TYPE_UNIVERSE_BACKGROUND) {
                 if (!win.mLayoutAttached) {
                     if (initial) {
@@ -8709,6 +8714,7 @@
                 // this guy's animations regardless of whether it's
                 // gotten drawn.
                 wtoken.allDrawn = true;
+                wtoken.deferClearAllDrawn = false;
             }
 
             if (mNextAppTransitionThumbnail != null && topOpeningApp != null
@@ -8879,6 +8885,7 @@
                     winAnimator.mDrawState = WindowStateAnimator.DRAW_PENDING;
                     if (w.mAppToken != null) {
                         w.mAppToken.allDrawn = false;
+                        w.mAppToken.deferClearAllDrawn = false;
                     }
                 }
                 if (!mResizingWindows.contains(w)) {
@@ -8954,27 +8961,29 @@
             // so we want to leave all of them as undimmed (for
             // performance reasons).
             mInnerFields.mObscured = true;
-        } else if (canBeSeen && (attrFlags & FLAG_DIM_BEHIND) != 0
-                && !(w.mAppToken != null && w.mAppToken.hiddenRequested)
+        }
+    }
+
+    private void handleFlagDimBehind(WindowState w, int innerDw, int innerDh) {
+        final WindowManager.LayoutParams attrs = w.mAttrs;
+        if ((attrs.flags & FLAG_DIM_BEHIND) != 0
+                && w.isDisplayedLw()
                 && !w.mExiting) {
-            if (localLOGV) Slog.v(TAG, "Win " + w + " obscured=" + mInnerFields.mObscured);
-            if (!mInnerFields.mDimming) {
-                //Slog.i(TAG, "DIM BEHIND: " + w);
-                mInnerFields.mDimming = true;
-                final WindowStateAnimator winAnimator = w.mWinAnimator;
-                if (!mAnimator.isDimmingLocked(winAnimator)) {
-                    final int width, height;
-                    if (attrs.type == TYPE_BOOT_PROGRESS) {
-                        final DisplayInfo displayInfo = w.mDisplayContent.getDisplayInfo();
-                        width = displayInfo.logicalWidth;
-                        height = displayInfo.logicalHeight;
-                    } else {
-                        width = innerDw;
-                        height = innerDh;
-                    }
-                    startDimmingLocked(
-                        winAnimator, w.mExiting ? 0 : w.mAttrs.dimAmount, width, height);
+            mInnerFields.mDimming = true;
+            final WindowStateAnimator winAnimator = w.mWinAnimator;
+            if (!mAnimator.isDimmingLocked(winAnimator)) {
+                final int width, height;
+                if (attrs.type == TYPE_BOOT_PROGRESS) {
+                    final DisplayInfo displayInfo = w.mDisplayContent.getDisplayInfo();
+                    width = displayInfo.logicalWidth;
+                    height = displayInfo.logicalHeight;
+                } else {
+                    width = innerDw;
+                    height = innerDh;
                 }
+                if (localLOGV) Slog.v(TAG, "Win " + w + " start dimming.");
+                startDimmingLocked(
+                        winAnimator, w.mExiting ? 0 : w.mAttrs.dimAmount, width, height);
             }
         }
     }
@@ -9153,6 +9162,10 @@
                         handleNotObscuredLocked(w, currentTime, innerDw, innerDh);
                     }
 
+                    if (!mInnerFields.mDimming) {
+                        handleFlagDimBehind(w, innerDw, innerDh);
+                    }
+
                     if (isDefaultDisplay && obscuredChanged && (mWallpaperTarget == w)
                             && w.isVisibleLw()) {
                         // This is the wallpaper target and its obscured state
diff --git a/services/java/com/android/server/wm/WindowStateAnimator.java b/services/java/com/android/server/wm/WindowStateAnimator.java
index 7b30c89..4ecc191 100644
--- a/services/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/java/com/android/server/wm/WindowStateAnimator.java
@@ -626,7 +626,14 @@
                     "createSurface " + this + ": mDrawState=DRAW_PENDING");
             mDrawState = DRAW_PENDING;
             if (mWin.mAppToken != null) {
-                mWin.mAppToken.allDrawn = false;
+                if (mWin.mAppToken.mAppAnimator.animation == null) {
+                    mWin.mAppToken.allDrawn = false;
+                    mWin.mAppToken.deferClearAllDrawn = false;
+                } else {
+                    // Currently animating, persist current state of allDrawn until animation
+                    // is complete.
+                    mWin.mAppToken.deferClearAllDrawn = true;
+                }
             }
 
             mService.makeWindowFreezingScreenIfNeededLocked(mWin);
diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java
index a9a5e90..2c171b1 100644
--- a/telephony/java/android/telephony/ServiceState.java
+++ b/telephony/java/android/telephony/ServiceState.java
@@ -36,6 +36,7 @@
 public class ServiceState implements Parcelable {
 
     static final String LOG_TAG = "PHONE";
+    static final boolean DBG = true;
 
     /**
      * Normal operation condition, the phone is registered
@@ -61,6 +62,46 @@
      */
     public static final int STATE_POWER_OFF = 3;
 
+    /**
+     * RIL level registration state values from ril.h
+     * ((const char **)response)[0] is registration state 0-6,
+     *              0 - Not registered, MT is not currently searching
+     *                  a new operator to register
+     *              1 - Registered, home network
+     *              2 - Not registered, but MT is currently searching
+     *                  a new operator to register
+     *              3 - Registration denied
+     *              4 - Unknown
+     *              5 - Registered, roaming
+     *             10 - Same as 0, but indicates that emergency calls
+     *                  are enabled.
+     *             12 - Same as 2, but indicates that emergency calls
+     *                  are enabled.
+     *             13 - Same as 3, but indicates that emergency calls
+     *                  are enabled.
+     *             14 - Same as 4, but indicates that emergency calls
+     *                  are enabled.
+     * @hide
+     */
+    public static final int RIL_REG_STATE_NOT_REG = 0;
+    /** @hide */
+    public static final int RIL_REG_STATE_HOME = 1;
+    /** @hide */
+    public static final int RIL_REG_STATE_SEARCHING = 2;
+    /** @hide */
+    public static final int RIL_REG_STATE_DENIED = 3;
+    /** @hide */
+    public static final int RIL_REG_STATE_UNKNOWN = 4;
+    /** @hide */
+    public static final int RIL_REG_STATE_ROAMING = 5;
+    /** @hide */
+    public static final int RIL_REG_STATE_NOT_REG_EMERGENCY_CALL_ENABLED = 10;
+    /** @hide */
+    public static final int RIL_REG_STATE_SEARCHING_EMERGENCY_CALL_ENABLED = 12;
+    /** @hide */
+    public static final int RIL_REG_STATE_DENIED_EMERGENCY_CALL_ENABLED = 13;
+    /** @hide */
+    public static final int RIL_REG_STATE_UNKNOWN_EMERGENCY_CALL_ENABLED = 14;
 
     /**
      * Available radio technologies for GSM, UMTS and CDMA.
@@ -122,7 +163,8 @@
     /** @hide */
     public static final int REGISTRATION_STATE_ROAMING = 5;
 
-    private int mState = STATE_OUT_OF_SERVICE;
+    private int mVoiceRegState = STATE_OUT_OF_SERVICE;
+    private int mDataRegState = STATE_OUT_OF_SERVICE;
     private boolean mRoaming;
     private String mOperatorAlphaLong;
     private String mOperatorAlphaShort;
@@ -131,8 +173,9 @@
 
     private boolean mIsEmergencyOnly;
 
-    //***** CDMA
-    private int mRadioTechnology;
+    private int mRilVoiceRadioTechnology;
+    private int mRilDataRadioTechnology;
+
     private boolean mCssIndicator;
     private int mNetworkId;
     private int mSystemId;
@@ -174,13 +217,15 @@
     }
 
     protected void copyFrom(ServiceState s) {
-        mState = s.mState;
+        mVoiceRegState = s.mVoiceRegState;
+        mDataRegState = s.mDataRegState;
         mRoaming = s.mRoaming;
         mOperatorAlphaLong = s.mOperatorAlphaLong;
         mOperatorAlphaShort = s.mOperatorAlphaShort;
         mOperatorNumeric = s.mOperatorNumeric;
         mIsManualNetworkSelection = s.mIsManualNetworkSelection;
-        mRadioTechnology = s.mRadioTechnology;
+        mRilVoiceRadioTechnology = s.mRilVoiceRadioTechnology;
+        mRilDataRadioTechnology = s.mRilDataRadioTechnology;
         mCssIndicator = s.mCssIndicator;
         mNetworkId = s.mNetworkId;
         mSystemId = s.mSystemId;
@@ -195,13 +240,15 @@
      * Construct a ServiceState object from the given parcel.
      */
     public ServiceState(Parcel in) {
-        mState = in.readInt();
+        mVoiceRegState = in.readInt();
+        mDataRegState = in.readInt();
         mRoaming = in.readInt() != 0;
         mOperatorAlphaLong = in.readString();
         mOperatorAlphaShort = in.readString();
         mOperatorNumeric = in.readString();
         mIsManualNetworkSelection = in.readInt() != 0;
-        mRadioTechnology = in.readInt();
+        mRilVoiceRadioTechnology = in.readInt();
+        mRilDataRadioTechnology = in.readInt();
         mCssIndicator = (in.readInt() != 0);
         mNetworkId = in.readInt();
         mSystemId = in.readInt();
@@ -213,13 +260,15 @@
     }
 
     public void writeToParcel(Parcel out, int flags) {
-        out.writeInt(mState);
+        out.writeInt(mVoiceRegState);
+        out.writeInt(mDataRegState);
         out.writeInt(mRoaming ? 1 : 0);
         out.writeString(mOperatorAlphaLong);
         out.writeString(mOperatorAlphaShort);
         out.writeString(mOperatorNumeric);
         out.writeInt(mIsManualNetworkSelection ? 1 : 0);
-        out.writeInt(mRadioTechnology);
+        out.writeInt(mRilVoiceRadioTechnology);
+        out.writeInt(mRilDataRadioTechnology);
         out.writeInt(mCssIndicator ? 1 : 0);
         out.writeInt(mNetworkId);
         out.writeInt(mSystemId);
@@ -246,15 +295,38 @@
     };
 
     /**
-     * Get current service state of phone
+     * Get current voice service state
+     */
+    public int getState() {
+        return getVoiceRegState();
+    }
+
+    /**
+     * Get current voice service state
      *
      * @see #STATE_IN_SERVICE
      * @see #STATE_OUT_OF_SERVICE
      * @see #STATE_EMERGENCY_ONLY
      * @see #STATE_POWER_OFF
+     *
+     * @hide
      */
-    public int getState() {
-        return mState;
+    public int getVoiceRegState() {
+        return mVoiceRegState;
+    }
+
+    /**
+     * Get current data service state
+     *
+     * @see #STATE_IN_SERVICE
+     * @see #STATE_OUT_OF_SERVICE
+     * @see #STATE_EMERGENCY_ONLY
+     * @see #STATE_POWER_OFF
+     *
+     * @hide
+     */
+    public int getDataRegState() {
+        return mDataRegState;
     }
 
     /**
@@ -354,7 +426,8 @@
 
     @Override
     public int hashCode() {
-        return ((mState * 0x1234)
+        return ((mVoiceRegState * 31)
+                + (mDataRegState * 37)
                 + (mRoaming ? 1 : 0)
                 + (mIsManualNetworkSelection ? 1 : 0)
                 + ((null == mOperatorAlphaLong) ? 0 : mOperatorAlphaLong.hashCode())
@@ -379,13 +452,15 @@
             return false;
         }
 
-        return (mState == s.mState
+        return (mVoiceRegState == s.mVoiceRegState
+                && mDataRegState == s.mDataRegState
                 && mRoaming == s.mRoaming
                 && mIsManualNetworkSelection == s.mIsManualNetworkSelection
                 && equalsHandlesNulls(mOperatorAlphaLong, s.mOperatorAlphaLong)
                 && equalsHandlesNulls(mOperatorAlphaShort, s.mOperatorAlphaShort)
                 && equalsHandlesNulls(mOperatorNumeric, s.mOperatorNumeric)
-                && equalsHandlesNulls(mRadioTechnology, s.mRadioTechnology)
+                && equalsHandlesNulls(mRilVoiceRadioTechnology, s.mRilVoiceRadioTechnology)
+                && equalsHandlesNulls(mRilDataRadioTechnology, s.mRilDataRadioTechnology)
                 && equalsHandlesNulls(mCssIndicator, s.mCssIndicator)
                 && equalsHandlesNulls(mNetworkId, s.mNetworkId)
                 && equalsHandlesNulls(mSystemId, s.mSystemId)
@@ -468,14 +543,16 @@
 
     @Override
     public String toString() {
-        String radioTechnology = rilRadioTechnologyToString(mRadioTechnology);
+        String radioTechnology = rilRadioTechnologyToString(mRilVoiceRadioTechnology);
+        String dataRadioTechnology = rilRadioTechnologyToString(mRilDataRadioTechnology);
 
-        return (mState + " " + (mRoaming ? "roaming" : "home")
+        return (mVoiceRegState + " " + mDataRegState + " " + (mRoaming ? "roaming" : "home")
                 + " " + mOperatorAlphaLong
                 + " " + mOperatorAlphaShort
                 + " " + mOperatorNumeric
                 + " " + (mIsManualNetworkSelection ? "(manual)" : "")
                 + " " + radioTechnology
+                + " " + dataRadioTechnology
                 + " " + (mCssIndicator ? "CSS supported" : "CSS not supported")
                 + " " + mNetworkId
                 + " " + mSystemId
@@ -485,13 +562,16 @@
     }
 
     private void setNullState(int state) {
-        mState = state;
+        if (DBG) Log.d(LOG_TAG, "[ServiceState] setNullState=" + state);
+        mVoiceRegState = state;
+        mDataRegState = state;
         mRoaming = false;
         mOperatorAlphaLong = null;
         mOperatorAlphaShort = null;
         mOperatorNumeric = null;
         mIsManualNetworkSelection = false;
-        mRadioTechnology = 0;
+        mRilVoiceRadioTechnology = 0;
+        mRilDataRadioTechnology = 0;
         mCssIndicator = false;
         mNetworkId = -1;
         mSystemId = -1;
@@ -511,7 +591,20 @@
     }
 
     public void setState(int state) {
-        mState = state;
+        setVoiceRegState(state);
+        if (DBG) Log.e(LOG_TAG, "[ServiceState] setState deprecated use setVoiceRegState()");
+    }
+
+    /** @hide */
+    public void setVoiceRegState(int state) {
+        mVoiceRegState = state;
+        if (DBG) Log.d(LOG_TAG, "[ServiceState] setVoiceRegState=" + mVoiceRegState);
+    }
+
+    /** @hide */
+    public void setDataRegState(int state) {
+        mDataRegState = state;
+        if (DBG) Log.d(LOG_TAG, "[ServiceState] setDataRegState=" + mDataRegState);
     }
 
     public void setRoaming(boolean roaming) {
@@ -592,13 +685,15 @@
      * @hide
      */
     private void setFromNotifierBundle(Bundle m) {
-        mState = m.getInt("state");
+        mVoiceRegState = m.getInt("voiceRegState");
+        mDataRegState = m.getInt("dataRegState");
         mRoaming = m.getBoolean("roaming");
         mOperatorAlphaLong = m.getString("operator-alpha-long");
         mOperatorAlphaShort = m.getString("operator-alpha-short");
         mOperatorNumeric = m.getString("operator-numeric");
         mIsManualNetworkSelection = m.getBoolean("manual");
-        mRadioTechnology = m.getInt("radioTechnology");
+        mRilVoiceRadioTechnology = m.getInt("radioTechnology");
+        mRilVoiceRadioTechnology = m.getInt("dataRadioTechnology");
         mCssIndicator = m.getBoolean("cssIndicator");
         mNetworkId = m.getInt("networkId");
         mSystemId = m.getInt("systemId");
@@ -614,13 +709,15 @@
      * @hide
      */
     public void fillInNotifierBundle(Bundle m) {
-        m.putInt("state", mState);
+        m.putInt("voiceRegState", mVoiceRegState);
+        m.putInt("dataRegState", mDataRegState);
         m.putBoolean("roaming", Boolean.valueOf(mRoaming));
         m.putString("operator-alpha-long", mOperatorAlphaLong);
         m.putString("operator-alpha-short", mOperatorAlphaShort);
         m.putString("operator-numeric", mOperatorNumeric);
         m.putBoolean("manual", Boolean.valueOf(mIsManualNetworkSelection));
-        m.putInt("radioTechnology", mRadioTechnology);
+        m.putInt("radioTechnology", mRilVoiceRadioTechnology);
+        m.putInt("dataRadioTechnology", mRilDataRadioTechnology);
         m.putBoolean("cssIndicator", mCssIndicator);
         m.putInt("networkId", mNetworkId);
         m.putInt("systemId", mSystemId);
@@ -629,10 +726,15 @@
         m.putBoolean("emergencyOnly", Boolean.valueOf(mIsEmergencyOnly));
     }
 
-    //***** CDMA
     /** @hide */
-    public void setRadioTechnology(int state) {
-        this.mRadioTechnology = state;
+    public void setRilVoiceRadioTechnology(int rt) {
+        this.mRilVoiceRadioTechnology = rt;
+    }
+
+    /** @hide */
+    public void setRilDataRadioTechnology(int rt) {
+        this.mRilDataRadioTechnology = rt;
+        if (DBG) Log.d(LOG_TAG, "[ServiceState] setDataRadioTechnology=" + mRilDataRadioTechnology);
     }
 
     /** @hide */
@@ -647,17 +749,25 @@
     }
 
     /** @hide */
-    public int getRilRadioTechnology() {
-        return this.mRadioTechnology;
+    public int getRilVoiceRadioTechnology() {
+        return this.mRilVoiceRadioTechnology;
     }
     /** @hide */
+    public int getRilDataRadioTechnology() {
+        return this.mRilDataRadioTechnology;
+    }
+    /**
+     * @hide
+     * @Deprecated to be removed Q3 2013 use {@link #getRilDataRadioTechnology} or
+     * {@link #getRilVoiceRadioTechnology}
+     */
     public int getRadioTechnology() {
-        return getRilRadioTechnology();
+        Log.e(LOG_TAG, "ServiceState.getRadioTechnology() DEPRECATED will be removed *******");
+        return getRilDataRadioTechnology();
     }
 
-    /** @hide */
-    public int getNetworkType() {
-        switch(mRadioTechnology) {
+    private int rilRadioTechnologyToNetworkType(int rt) {
+        switch(rt) {
         case ServiceState.RIL_RADIO_TECHNOLOGY_GPRS:
             return TelephonyManager.NETWORK_TYPE_GPRS;
         case ServiceState.RIL_RADIO_TECHNOLOGY_EDGE:
@@ -692,6 +802,25 @@
         }
     }
 
+    /**
+     * @Deprecated to be removed Q3 2013 use {@link #getVoiceNetworkType}
+     * @hide
+     */
+    public int getNetworkType() {
+        Log.e(LOG_TAG, "ServiceState.getNetworkType() DEPRECATED will be removed *******");
+        return rilRadioTechnologyToNetworkType(mRilVoiceRadioTechnology);
+    }
+
+    /** @hide */
+    public int getDataNetworkType() {
+        return rilRadioTechnologyToNetworkType(mRilDataRadioTechnology);
+    }
+
+    /** @hide */
+    public int getVoiceNetworkType() {
+        return rilRadioTechnologyToNetworkType(mRilVoiceRadioTechnology);
+    }
+
     /** @hide */
     public int getCssIndicator() {
         return this.mCssIndicator ? 1 : 0;
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 2fa41e7..261174a 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -557,6 +557,13 @@
     public static final int NETWORK_TYPE_HSPAP = 15;
 
     /**
+     * Returns the NETWORK_TYPE_xxxx for data transmission
+     */
+    public int getNetworkType() {
+        return getDataNetworkType();
+    }
+
+    /**
      * Returns a constant indicating the radio technology (network type)
      * currently in use on the device for data transmission.
      * @return the network type
@@ -577,12 +584,37 @@
      * @see #NETWORK_TYPE_LTE
      * @see #NETWORK_TYPE_EHRPD
      * @see #NETWORK_TYPE_HSPAP
+     *
+     * @hide
      */
-    public int getNetworkType() {
+    public int getDataNetworkType() {
         try{
             ITelephony telephony = getITelephony();
             if (telephony != null) {
-                return telephony.getNetworkType();
+                return telephony.getDataNetworkType();
+            } else {
+                // This can happen when the ITelephony interface is not up yet.
+                return NETWORK_TYPE_UNKNOWN;
+            }
+        } catch(RemoteException ex) {
+            // This shouldn't happen in the normal case
+            return NETWORK_TYPE_UNKNOWN;
+        } catch (NullPointerException ex) {
+            // This could happen before phone restarts due to crashing
+            return NETWORK_TYPE_UNKNOWN;
+        }
+    }
+
+    /**
+     * Returns the NETWORK_TYPE_xxxx for voice
+     *
+     * @hide
+     */
+    public int getVoiceNetworkType() {
+        try{
+            ITelephony telephony = getITelephony();
+            if (telephony != null) {
+                return telephony.getVoiceNetworkType();
             } else {
                 // This can happen when the ITelephony interface is not up yet.
                 return NETWORK_TYPE_UNKNOWN;
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 12a7286..d5f0467 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -261,11 +261,21 @@
     int getVoiceMessageCount();
 
     /**
-      * Returns the network type
+      * Returns the network type for data transmission
       */
     int getNetworkType();
 
     /**
+      * Returns the network type for data transmission
+      */
+    int getDataNetworkType();
+
+    /**
+      * Returns the network type for voice
+      */
+    int getVoiceNetworkType();
+
+    /**
      * Return true if an ICC card is present
      */
     boolean hasIccCard();
diff --git a/test-runner/src/android/test/InstrumentationTestRunner.java b/test-runner/src/android/test/InstrumentationTestRunner.java
index 91e403e..8e30875 100644
--- a/test-runner/src/android/test/InstrumentationTestRunner.java
+++ b/test-runner/src/android/test/InstrumentationTestRunner.java
@@ -555,7 +555,7 @@
                 mTestRunner.runTest();
                 long runTime = System.currentTimeMillis() - startTime;
 
-                resultPrinter.print(mTestRunner.getTestResult(), runTime);
+                resultPrinter.printResult(mTestRunner.getTestResult(), runTime);
             } catch (Throwable t) {
                 // catch all exceptions so a more verbose error message can be outputted
                 writer.println(String.format("Test run aborted due to unexpected exception: %s",
@@ -656,7 +656,7 @@
             super(writer);
         }
 
-        synchronized void print(TestResult result, long runTime) {
+        public synchronized void printResult(TestResult result, long runTime) {
             printHeader(runTime);
             printFooter(result);
         }
diff --git a/tests/GridLayoutTest/src/com/android/test/layout/LayoutInsetsTest.java b/tests/GridLayoutTest/src/com/android/test/layout/LayoutInsetsTest.java
index 103de2f..81440a5 100644
--- a/tests/GridLayoutTest/src/com/android/test/layout/LayoutInsetsTest.java
+++ b/tests/GridLayoutTest/src/com/android/test/layout/LayoutInsetsTest.java
@@ -10,9 +10,8 @@
 import android.widget.GridLayout;
 import android.widget.TextView;
 
-import static android.widget.GridLayout.ALIGN_BOUNDS;
 import static android.widget.GridLayout.LayoutParams;
-import static android.widget.GridLayout.OPTICAL_BOUNDS;
+import static android.widget.GridLayout.LAYOUT_MODE_OPTICAL_BOUNDS;
 
 public class LayoutInsetsTest extends Activity {
     static int[] GRAVITIES = {Gravity.LEFT, Gravity.LEFT, Gravity.CENTER_HORIZONTAL, Gravity.RIGHT, Gravity.RIGHT};
@@ -23,7 +22,7 @@
         GridLayout p = new GridLayout(context);
         p.setUseDefaultMargins(true);
         //p.setAlignmentMode(ALIGN_BOUNDS);
-        p.setLayoutMode(OPTICAL_BOUNDS);
+        p.setLayoutMode(LAYOUT_MODE_OPTICAL_BOUNDS);
 
         p.setColumnCount(N);
 
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/Blur25G.java b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/Blur25G.java
new file mode 100644
index 0000000..ac0dad1
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/Blur25G.java
@@ -0,0 +1,97 @@
+/*
+ * 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.image;
+
+import java.lang.Math;
+
+import android.graphics.Bitmap;
+import android.renderscript.Allocation;
+import android.renderscript.Element;
+import android.renderscript.RenderScript;
+import android.renderscript.ScriptIntrinsicBlur;
+import android.renderscript.Type;
+import android.util.Log;
+import android.widget.SeekBar;
+import android.widget.TextView;
+
+public class Blur25G extends TestBase {
+    private final int MAX_RADIUS = 25;
+    private float mRadius = MAX_RADIUS;
+
+    private ScriptIntrinsicBlur mIntrinsic;
+
+    private ScriptC_greyscale mScript;
+    private Allocation mScratchPixelsAllocation1;
+    private Allocation mScratchPixelsAllocation2;
+
+
+    public Blur25G() {
+    }
+
+    public boolean onBar1Setup(SeekBar b, TextView t) {
+        t.setText("Radius");
+        b.setProgress(100);
+        return true;
+    }
+
+
+    public void onBar1Changed(int progress) {
+        mRadius = ((float)progress) / 100.0f * MAX_RADIUS;
+        if (mRadius <= 0.10f) {
+            mRadius = 0.10f;
+        }
+        mIntrinsic.setRadius(mRadius);
+    }
+
+
+    public void createTest(android.content.res.Resources res) {
+        int width = mInPixelsAllocation.getType().getX();
+        int height = mInPixelsAllocation.getType().getY();
+
+        Type.Builder tb = new Type.Builder(mRS, Element.U8(mRS));
+        tb.setX(width);
+        tb.setY(height);
+        mScratchPixelsAllocation1 = Allocation.createTyped(mRS, tb.create());
+        mScratchPixelsAllocation2 = Allocation.createTyped(mRS, tb.create());
+
+        mScript = new ScriptC_greyscale(mRS);
+        mScript.forEach_toU8(mInPixelsAllocation, mScratchPixelsAllocation1);
+
+        mIntrinsic = ScriptIntrinsicBlur.create(mRS, Element.U8(mRS));
+        mIntrinsic.setRadius(MAX_RADIUS);
+        mIntrinsic.setInput(mScratchPixelsAllocation1);
+    }
+
+    public void runTest() {
+        mIntrinsic.forEach(mScratchPixelsAllocation2);
+    }
+
+    public void setupBenchmark() {
+        mIntrinsic.setRadius(MAX_RADIUS);
+    }
+
+    public void exitBenchmark() {
+        mIntrinsic.setRadius(mRadius);
+    }
+
+    public void updateBitmap(Bitmap b) {
+        mScript.forEach_toU8_4(mScratchPixelsAllocation2, mOutPixelsAllocation);
+        mOutPixelsAllocation.copyTo(b);
+    }
+
+}
+
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/ImageProcessingActivity.java b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/ImageProcessingActivity.java
index db0ef78..90fa74f 100644
--- a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/ImageProcessingActivity.java
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/ImageProcessingActivity.java
@@ -18,6 +18,8 @@
 
 import android.app.Activity;
 import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
 import android.graphics.BitmapFactory;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
@@ -82,11 +84,37 @@
     private boolean mDoingBenchmark;
 
     private TestBase mTest;
+    private int mRunCount;
 
     public void updateDisplay() {
+        mHandler.sendMessage(Message.obtain());
+    }
+
+    private Handler mHandler = new Handler() {
+        // Allow the filter to complete without blocking the UI
+        // thread.  When the message arrives that the op is complete
+        // we will either mark completion or start a new filter if
+        // more work is ready.  Either way, display the result.
+        @Override
+        public void handleMessage(Message msg) {
             mTest.updateBitmap(mBitmapOut);
             mDisplayView.invalidate();
-    }
+
+            boolean doTest = false;
+            synchronized(this) {
+                if (mRunCount > 0) {
+                    mRunCount--;
+                    if (mRunCount > 0) {
+                        doTest = true;
+                    }
+                }
+            }
+            if (doTest) {
+                mTest.runTestSendMessage();
+            }
+        }
+
+    };
 
     public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
         if (fromUser) {
@@ -103,8 +131,18 @@
                 mTest.onBar5Changed(progress);
             }
 
-            mTest.runTest();
-            updateDisplay();
+            boolean doTest = false;
+            synchronized(this) {
+                if (mRunCount == 0) {
+                    doTest = true;
+                    mRunCount = 1;
+                } else {
+                    mRunCount = 2;
+                }
+            }
+            if (doTest) {
+                mTest.runTestSendMessage();
+            }
         }
     }
 
@@ -232,6 +270,9 @@
         case 28:
             mTest = new Blend();
             break;
+        case 29:
+            mTest = new Blur25G();
+            break;
         }
 
         mTest.createBaseTest(this, mBitmapIn, mBitmapIn2);
@@ -243,7 +284,7 @@
     }
 
     void setupTests() {
-        mTestNames = new String[29];
+        mTestNames = new String[30];
         mTestNames[0] = "Levels Vec3 Relaxed";
         mTestNames[1] = "Levels Vec4 Relaxed";
         mTestNames[2] = "Levels Vec3 Full";
@@ -273,6 +314,7 @@
         mTestNames[26] = "Intrinsics Convolve 5x5";
         mTestNames[27] = "Mandelbrot";
         mTestNames[28] = "Intrinsics Blend";
+        mTestNames[29] = "Intrinsics Blur 25 uchar";
 
         mTestSpinner.setAdapter(new ArrayAdapter<String>(
             this, R.layout.spinner_layout, mTestNames));
@@ -296,7 +338,8 @@
 
         mBitmapIn = loadBitmap(R.drawable.img1600x1067);
         mBitmapIn2 = loadBitmap(R.drawable.img1600x1067b);
-        mBitmapOut = loadBitmap(R.drawable.img1600x1067);
+        mBitmapOut = Bitmap.createBitmap(mBitmapIn.getWidth(), mBitmapIn.getHeight(),
+                                         mBitmapIn.getConfig());
 
         mSurfaceView = (SurfaceView) findViewById(R.id.surface);
 
@@ -337,15 +380,7 @@
     private Bitmap loadBitmap(int resource) {
         final BitmapFactory.Options options = new BitmapFactory.Options();
         options.inPreferredConfig = Bitmap.Config.ARGB_8888;
-        return copyBitmap(BitmapFactory.decodeResource(getResources(), resource, options));
-    }
-
-    private static Bitmap copyBitmap(Bitmap source) {
-        Bitmap b = Bitmap.createBitmap(source.getWidth(), source.getHeight(), source.getConfig());
-        Canvas c = new Canvas(b);
-        c.drawBitmap(source, 0, 0, null);
-        source.recycle();
-        return b;
+        return BitmapFactory.decodeResource(getResources(), resource, options);
     }
 
     // button hook
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/TestBase.java b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/TestBase.java
index bb3f2f3..d4c4898 100644
--- a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/TestBase.java
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/TestBase.java
@@ -45,9 +45,22 @@
     protected Allocation mInPixelsAllocation;
     protected Allocation mInPixelsAllocation2;
     protected Allocation mOutPixelsAllocation;
+    protected ScriptC_msg mMessageScript;
 
     protected ImageProcessingActivity act;
 
+    private class MessageProcessor extends RenderScript.RSMessageHandler {
+        ImageProcessingActivity mAct;
+
+        MessageProcessor(ImageProcessingActivity act) {
+            mAct = act;
+        }
+
+        public void run() {
+            mAct.updateDisplay();
+        }
+    }
+
     // Override to use UI elements
     public void onBar1Changed(int progress) {
     }
@@ -96,6 +109,8 @@
     public final void createBaseTest(ImageProcessingActivity ipact, Bitmap b, Bitmap b2) {
         act = ipact;
         mRS = RenderScript.create(act);
+        mRS.setMessageHandler(new MessageProcessor(act));
+        mMessageScript = new ScriptC_msg(mRS);
         mInPixelsAllocation = Allocation.createFromBitmap(mRS, b,
                                                           Allocation.MipmapControl.MIPMAP_NONE,
                                                           Allocation.USAGE_SCRIPT);
@@ -110,13 +125,17 @@
 
     // Must override
     public void createTest(android.content.res.Resources res) {
-        android.util.Log.e("img", "implement createTest");
     }
 
     // Must override
     public void runTest() {
     }
 
+    final public void runTestSendMessage() {
+        runTest();
+        mMessageScript.invoke_sendMsg();
+    }
+
     public void finish() {
         mRS.finish();
     }
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/greyscale.fs b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/greyscale.fs
index 90ba058..d419459 100644
--- a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/greyscale.fs
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/greyscale.fs
@@ -27,4 +27,12 @@
     return rsPackColorTo8888(mono);
 }
 
+uchar __attribute__((kernel)) toU8(uchar4 v_in) {
+    float4 f4 = convert_float4(v_in);
+    return (uchar)dot(f4.rgb, gMonoMult);
+}
+
+uchar4 __attribute__((kernel)) toU8_4(uchar v_in) {
+    return (uchar4)v_in;
+}
 
diff --git a/include/diskusage/dirsize.h b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/msg.rs
similarity index 60%
copy from include/diskusage/dirsize.h
copy to tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/msg.rs
index 34236c0..1a19ffc 100644
--- a/include/diskusage/dirsize.h
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/msg.rs
@@ -1,12 +1,11 @@
 /*
- *
- * Copyright (C) 2010 The Android Open Source Project
+ * 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
+ *      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,
@@ -15,16 +14,10 @@
  * limitations under the License.
  */
 
-#ifndef __LIBDISKUSAGE_DIRSIZE_H
-#define __LIBDISKUSAGE_DIRSIZE_H
+#pragma version(1)
+#pragma rs java_package_name(com.android.rs.image)
 
-#include <stdint.h>
+void sendMsg() {
+    rsSendToClientBlocking(0);
+}
 
-__BEGIN_DECLS
-
-int64_t stat_size(struct stat *s);
-int64_t calculate_dir_size(int dfd);
-
-__END_DECLS
-
-#endif /* __LIBDISKUSAGE_DIRSIZE_H */
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/convolve3x3.rs b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/convolve3x3.rs
index b55190c..13f9032 100644
--- a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/convolve3x3.rs
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/convolve3x3.rs
@@ -25,9 +25,9 @@
 float gCoeffs[9];
 
 void root(uchar4 *out, uint32_t x, uint32_t y) {
-    uint32_t x1 = min((int32_t)x+1, gWidth);
+    uint32_t x1 = min((int32_t)x+1, gWidth-1);
     uint32_t x2 = max((int32_t)x-1, 0);
-    uint32_t y1 = min((int32_t)y+1, gHeight);
+    uint32_t y1 = min((int32_t)y+1, gHeight-1);
     uint32_t y2 = max((int32_t)y-1, 0);
 
     float4 p00 = convert_float4(((uchar4 *)rsGetElementAt(gIn, x1, y1))[0]);
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/convolve5x5.rs b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/convolve5x5.rs
index b110b88..b1ad241 100644
--- a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/convolve5x5.rs
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/convolve5x5.rs
@@ -68,6 +68,7 @@
               + convert_float4(rsGetElementAt_uchar4(gIn, x4, y4)) * gCoeffs[24];
 
     p0 = clamp(p0 + p1 + p2 + p3 + p4, 0.f, 255.f);
+    p0.a = 255.f;
     *out = convert_uchar4(p0);
 }
 
diff --git a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/mandelbrot.rs b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/mandelbrot.rs
index 55e5304..5b3912d 100644
--- a/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/mandelbrot.rs
+++ b/tests/RenderScriptTests/ImageProcessing2/src/com/android/rs/image/mandelbrot.rs
@@ -43,7 +43,7 @@
     // write a non-transparent black pixel
     *v_out = (uchar4){0, 0, 0, 0xff};
   } else {
-    float mi3 = gMaxIteration / 3.;
+    float mi3 = gMaxIteration / 3.f;
     if (iter <= (gMaxIteration / 3))
       *v_out = (uchar4){0xff * (iter / mi3), 0, 0, 0xff};
     else if (iter <= (((gMaxIteration / 3) * 2)))
diff --git a/cmds/ip-up-vpn/Android.mk b/tests/RenderScriptTests/ImageProcessing_jb/Android.mk
similarity index 63%
copy from cmds/ip-up-vpn/Android.mk
copy to tests/RenderScriptTests/ImageProcessing_jb/Android.mk
index de81889..6cdd1c0 100644
--- a/cmds/ip-up-vpn/Android.mk
+++ b/tests/RenderScriptTests/ImageProcessing_jb/Android.mk
@@ -1,5 +1,5 @@
 #
-# Copyright (C) 2011 The Android Open Source Project
+# 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.
@@ -17,10 +17,13 @@
 LOCAL_PATH := $(call my-dir)
 include $(CLEAR_VARS)
 
-LOCAL_SRC_FILES := ip-up-vpn.c
-LOCAL_SHARED_LIBRARIES := libcutils
-LOCAL_MODULE := ip-up-vpn
-LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/ppp
-LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_TAGS := tests
 
-include $(BUILD_EXECUTABLE)
+LOCAL_SRC_FILES := $(call all-java-files-under, src) \
+                   $(call all-renderscript-files-under, src)
+#LOCAL_STATIC_JAVA_LIBRARIES := android.renderscript
+
+LOCAL_PACKAGE_NAME := ImageProcessingJB
+LOCAL_SDK_VERSION := 16
+
+include $(BUILD_PACKAGE)
diff --git a/tests/RenderScriptTests/ImageProcessing_jb/AndroidManifest.xml b/tests/RenderScriptTests/ImageProcessing_jb/AndroidManifest.xml
new file mode 100644
index 0000000..b3fcfc4
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing_jb/AndroidManifest.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.rs.imagejb">
+    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+    <uses-sdk android:minSdkVersion="11" />
+    <application android:label="Image Processing JB"
+                 android:hardwareAccelerated="true">
+        <activity android:name="ImageProcessingActivityJB">
+            <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/ImageProcessing_jb/res/drawable-nodpi/img1600x1067.jpg b/tests/RenderScriptTests/ImageProcessing_jb/res/drawable-nodpi/img1600x1067.jpg
new file mode 100644
index 0000000..05d3ee2
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing_jb/res/drawable-nodpi/img1600x1067.jpg
Binary files differ
diff --git a/tests/RenderScriptTests/ImageProcessing_jb/res/drawable-nodpi/img1600x1067b.jpg b/tests/RenderScriptTests/ImageProcessing_jb/res/drawable-nodpi/img1600x1067b.jpg
new file mode 100644
index 0000000..aed0781
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing_jb/res/drawable-nodpi/img1600x1067b.jpg
Binary files differ
diff --git a/tests/RenderScriptTests/ImageProcessing_jb/res/layout/main.xml b/tests/RenderScriptTests/ImageProcessing_jb/res/layout/main.xml
new file mode 100644
index 0000000..f0a2b92
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing_jb/res/layout/main.xml
@@ -0,0 +1,139 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<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">
+    <SurfaceView
+        android:id="@+id/surface"
+        android:layout_width="1dip"
+        android:layout_height="1dip" />
+    <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">
+            <ImageView
+                android:id="@+id/display"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content" />
+            <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/saturation"/>
+            </LinearLayout>
+            <Spinner
+                android:id="@+id/filterselection"
+                android:layout_width="fill_parent"
+                android:layout_height="wrap_content"/>
+            <Spinner
+                android:id="@+id/spinner1"
+                android:layout_width="fill_parent"
+                android:layout_height="wrap_content"/>
+            <TextView
+                android:id="@+id/slider1Text"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:textSize="8pt"
+                android:layout_marginLeft="10sp"
+                android:layout_marginTop="15sp"
+                android:text="@string/saturation"/>
+             <SeekBar
+                android:id="@+id/slider1"
+                android:layout_marginLeft="10sp"
+                android:layout_marginRight="10sp"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"/>
+            <TextView
+                android:id="@+id/slider2Text"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:textSize="8pt"
+                android:layout_marginLeft="10sp"
+                android:layout_marginTop="15sp"
+                android:text="@string/gamma"/>
+            <SeekBar
+                android:id="@+id/slider2"
+                android:layout_marginLeft="10sp"
+                android:layout_marginRight="10sp"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"/>
+            <TextView
+                android:id="@+id/slider3Text"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_marginLeft="10sp"
+                android:layout_marginTop="15sp"
+                android:textSize="8pt"
+                android:text="@string/out_white"/>
+            <SeekBar
+                android:id="@+id/slider3"
+                android:layout_marginLeft="10sp"
+                android:layout_marginRight="10sp"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"/>
+            <TextView
+                android:id="@+id/slider4Text"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:textSize="8pt"
+                android:layout_marginLeft="10sp"
+                android:layout_marginTop="15sp"
+                android:text="@string/in_white"/>
+            <SeekBar
+                android:id="@+id/slider4"
+                android:layout_marginLeft="10sp"
+                android:layout_marginRight="10sp"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"/>
+            <TextView
+                android:id="@+id/slider5Text"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:textSize="8pt"
+                android:layout_marginLeft="10sp"
+                android:layout_marginTop="15sp"
+                android:text="@string/in_white"/>
+            <SeekBar
+                android:id="@+id/slider5"
+                android:layout_marginLeft="10sp"
+                android:layout_marginRight="10sp"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"/>
+            <Button
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text="@string/benchmark_all"
+                    android:onClick="benchmark_all"/>
+            </LinearLayout>
+    </ScrollView>
+</LinearLayout>
+
diff --git a/tests/RenderScriptTests/ImageProcessing_jb/res/layout/spinner_layout.xml b/tests/RenderScriptTests/ImageProcessing_jb/res/layout/spinner_layout.xml
new file mode 100644
index 0000000..8196bbf
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing_jb/res/layout/spinner_layout.xml
@@ -0,0 +1,23 @@
+<?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.
+-->
+
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent"
+    android:padding="10dp"
+    android:textSize="16sp"
+/>
diff --git a/tests/RenderScriptTests/ImageProcessing_jb/res/values/strings.xml b/tests/RenderScriptTests/ImageProcessing_jb/res/values/strings.xml
new file mode 100644
index 0000000..a7dd165
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing_jb/res/values/strings.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+* 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.
+*/
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!-- General -->
+    <skip />
+    <!--slider label -->
+    <string name="blur_description">Blur Radius</string>
+    <string name="in_white">In White</string>
+    <string name="out_white">Out White</string>
+    <string name="in_black">In Black</string>
+    <string name="out_black">Out Black</string>
+    <string name="gamma">Gamma</string>
+    <string name="saturation">Saturation</string>
+    <string name="benchmark">Benchmark</string>
+    <string name="benchmark_all">Benchmark All</string>
+
+</resources>
diff --git a/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/Blur25.java b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/Blur25.java
new file mode 100644
index 0000000..d7e918b
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/Blur25.java
@@ -0,0 +1,90 @@
+/*
+ * 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.imagejb;
+
+import java.lang.Math;
+
+import android.renderscript.Allocation;
+import android.renderscript.Element;
+import android.renderscript.RenderScript;
+import android.renderscript.Type;
+import android.util.Log;
+import android.widget.SeekBar;
+import android.widget.TextView;
+
+public class Blur25 extends TestBase {
+    private int MAX_RADIUS = 25;
+    private ScriptC_threshold mScript;
+    private float mRadius = MAX_RADIUS;
+    private float mSaturation = 1.0f;
+    private Allocation mScratchPixelsAllocation1;
+    private Allocation mScratchPixelsAllocation2;
+
+
+    public Blur25() {
+    }
+
+    public boolean onBar1Setup(SeekBar b, TextView t) {
+        t.setText("Radius");
+        b.setProgress(100);
+        return true;
+    }
+
+
+    public void onBar1Changed(int progress) {
+        mRadius = ((float)progress) / 100.0f * MAX_RADIUS;
+        if (mRadius <= 0.10f) {
+            mRadius = 0.10f;
+        }
+        mScript.invoke_setRadius((int)mRadius);
+    }
+
+
+    public void createTest(android.content.res.Resources res) {
+        int width = mInPixelsAllocation.getType().getX();
+        int height = mInPixelsAllocation.getType().getY();
+
+        Type.Builder tb = new Type.Builder(mRS, Element.F32_4(mRS));
+        tb.setX(width);
+        tb.setY(height);
+        mScratchPixelsAllocation1 = Allocation.createTyped(mRS, tb.create());
+        mScratchPixelsAllocation2 = Allocation.createTyped(mRS, tb.create());
+
+        mScript = new ScriptC_threshold(mRS, res, R.raw.threshold);
+        mScript.set_width(width);
+        mScript.set_height(height);
+        mScript.invoke_setRadius(MAX_RADIUS);
+
+        mScript.set_InPixel(mInPixelsAllocation);
+        mScript.set_ScratchPixel1(mScratchPixelsAllocation1);
+        mScript.set_ScratchPixel2(mScratchPixelsAllocation2);
+    }
+
+    public void runTest() {
+        mScript.forEach_copyIn(mInPixelsAllocation, mScratchPixelsAllocation1);
+        mScript.forEach_horz(mScratchPixelsAllocation2);
+        mScript.forEach_vert(mOutPixelsAllocation);
+    }
+
+    public void setupBenchmark() {
+        mScript.invoke_setRadius(MAX_RADIUS);
+    }
+
+    public void exitBenchmark() {
+        mScript.invoke_setRadius((int)mRadius);
+    }
+}
diff --git a/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/ColorMatrix.java b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/ColorMatrix.java
new file mode 100644
index 0000000..62ca694
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/ColorMatrix.java
@@ -0,0 +1,52 @@
+/*
+ * 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.imagejb;
+
+import java.lang.Math;
+
+import android.renderscript.Allocation;
+import android.renderscript.Element;
+import android.renderscript.Matrix4f;
+import android.renderscript.RenderScript;
+import android.renderscript.Script;
+import android.renderscript.ScriptC;
+import android.renderscript.Type;
+import android.util.Log;
+
+public class ColorMatrix extends TestBase {
+    private ScriptC_colormatrix mScript;
+    private boolean mUseGrey;
+
+    public ColorMatrix(boolean useGrey) {
+        mUseGrey = useGrey;
+    }
+
+    public void createTest(android.content.res.Resources res) {
+        Matrix4f m = new Matrix4f();
+        m.set(1, 0, 0.2f);
+        m.set(1, 1, 0.9f);
+        m.set(1, 2, 0.2f);
+
+        mScript = new ScriptC_colormatrix(mRS, res, R.raw.colormatrix);
+        mScript.invoke_setMatrix(m);
+    }
+
+    public void runTest() {
+        mScript.forEach_root(mInPixelsAllocation, mOutPixelsAllocation);
+    }
+
+}
diff --git a/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/Convolve3x3.java b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/Convolve3x3.java
new file mode 100644
index 0000000..6673032
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/Convolve3x3.java
@@ -0,0 +1,59 @@
+/*
+ * 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.imagejb;
+
+import java.lang.Math;
+
+import android.renderscript.Allocation;
+import android.renderscript.Element;
+import android.renderscript.Matrix4f;
+import android.renderscript.RenderScript;
+import android.renderscript.Script;
+import android.renderscript.ScriptC;
+import android.renderscript.Type;
+import android.util.Log;
+
+public class Convolve3x3 extends TestBase {
+    private ScriptC_convolve3x3 mScript;
+
+    private int mWidth;
+    private int mHeight;
+
+    public Convolve3x3() {
+    }
+
+    public void createTest(android.content.res.Resources res) {
+        mWidth = mInPixelsAllocation.getType().getX();
+        mHeight = mInPixelsAllocation.getType().getY();
+
+        float f[] = new float[9];
+        f[0] =  0.f;    f[1] = -1.f;    f[2] =  0.f;
+        f[3] = -1.f;    f[4] =  5.f;    f[5] = -1.f;
+        f[6] =  0.f;    f[7] = -1.f;    f[8] =  0.f;
+
+        mScript = new ScriptC_convolve3x3(mRS, res, R.raw.convolve3x3);
+        mScript.set_gCoeffs(f);
+        mScript.set_gIn(mInPixelsAllocation);
+        mScript.set_gWidth(mWidth);
+        mScript.set_gHeight(mHeight);
+    }
+
+    public void runTest() {
+        mScript.forEach_root(mOutPixelsAllocation);
+    }
+
+}
diff --git a/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/Convolve5x5.java b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/Convolve5x5.java
new file mode 100644
index 0000000..895d459
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/Convolve5x5.java
@@ -0,0 +1,73 @@
+/*
+ * 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.imagejb;
+
+import java.lang.Math;
+
+import android.renderscript.Allocation;
+import android.renderscript.Element;
+import android.renderscript.Matrix4f;
+import android.renderscript.RenderScript;
+import android.renderscript.Script;
+import android.renderscript.ScriptC;
+import android.renderscript.Type;
+import android.util.Log;
+
+public class Convolve5x5 extends TestBase {
+    private ScriptC_convolve5x5 mScript;
+
+    private int mWidth;
+    private int mHeight;
+
+    public Convolve5x5() {
+    }
+
+    public void createTest(android.content.res.Resources res) {
+        mWidth = mInPixelsAllocation.getType().getX();
+        mHeight = mInPixelsAllocation.getType().getY();
+
+        float f[] = new float[25];
+        //f[0] = 0.012f; f[1] = 0.025f; f[2] = 0.031f; f[3] = 0.025f; f[4] = 0.012f;
+        //f[5] = 0.025f; f[6] = 0.057f; f[7] = 0.075f; f[8] = 0.057f; f[9] = 0.025f;
+        //f[10]= 0.031f; f[11]= 0.075f; f[12]= 0.095f; f[13]= 0.075f; f[14]= 0.031f;
+        //f[15]= 0.025f; f[16]= 0.057f; f[17]= 0.075f; f[18]= 0.057f; f[19]= 0.025f;
+        //f[20]= 0.012f; f[21]= 0.025f; f[22]= 0.031f; f[23]= 0.025f; f[24]= 0.012f;
+
+        //f[0] = 1.f; f[1] = 2.f; f[2] = 0.f; f[3] = -2.f; f[4] = -1.f;
+        //f[5] = 4.f; f[6] = 8.f; f[7] = 0.f; f[8] = -8.f; f[9] = -4.f;
+        //f[10]= 6.f; f[11]=12.f; f[12]= 0.f; f[13]=-12.f; f[14]= -6.f;
+        //f[15]= 4.f; f[16]= 8.f; f[17]= 0.f; f[18]= -8.f; f[19]= -4.f;
+        //f[20]= 1.f; f[21]= 2.f; f[22]= 0.f; f[23]= -2.f; f[24]= -1.f;
+
+        f[0] = -1.f; f[1] = -3.f; f[2] = -4.f; f[3] = -3.f; f[4] = -1.f;
+        f[5] = -3.f; f[6] =  0.f; f[7] =  6.f; f[8] =  0.f; f[9] = -3.f;
+        f[10]= -4.f; f[11]=  6.f; f[12]= 20.f; f[13]=  6.f; f[14]= -4.f;
+        f[15]= -3.f; f[16]=  0.f; f[17]=  6.f; f[18]=  0.f; f[19]= -3.f;
+        f[20]= -1.f; f[21]= -3.f; f[22]= -4.f; f[23]= -3.f; f[24]= -1.f;
+
+        mScript = new ScriptC_convolve5x5(mRS, res, R.raw.convolve5x5);
+        mScript.set_gCoeffs(f);
+        mScript.set_gIn(mInPixelsAllocation);
+        mScript.set_gWidth(mWidth);
+        mScript.set_gHeight(mHeight);
+    }
+
+    public void runTest() {
+        mScript.forEach_root(mOutPixelsAllocation);
+    }
+
+}
diff --git a/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/Copy.java b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/Copy.java
new file mode 100644
index 0000000..1bdee4b
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/Copy.java
@@ -0,0 +1,40 @@
+/*
+ * 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.imagejb;
+
+import java.lang.Math;
+
+import android.renderscript.Allocation;
+import android.renderscript.Element;
+import android.renderscript.RenderScript;
+import android.renderscript.Script;
+import android.renderscript.ScriptC;
+import android.renderscript.Type;
+import android.util.Log;
+
+public class Copy extends TestBase {
+    private ScriptC_copy mScript;
+
+    public void createTest(android.content.res.Resources res) {
+        mScript = new ScriptC_copy(mRS, res, R.raw.copy);
+    }
+
+    public void runTest() {
+        mScript.forEach_root(mInPixelsAllocation, mOutPixelsAllocation);
+    }
+
+}
diff --git a/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/Grain.java b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/Grain.java
new file mode 100644
index 0000000..5cd19a2
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/Grain.java
@@ -0,0 +1,94 @@
+/*
+ * 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.imagejb;
+
+import java.lang.Math;
+
+import android.renderscript.Allocation;
+import android.renderscript.Element;
+import android.renderscript.RenderScript;
+import android.renderscript.Script;
+import android.renderscript.ScriptC;
+import android.renderscript.Type;
+import android.util.Log;
+import android.widget.SeekBar;
+import android.widget.TextView;
+
+public class Grain extends TestBase {
+    private ScriptC_grain mScript;
+    private Allocation mNoise;
+    private Allocation mNoise2;
+
+
+    public boolean onBar1Setup(SeekBar b, TextView t) {
+        t.setText("Strength");
+        b.setProgress(50);
+        return true;
+    }
+
+    public void onBar1Changed(int progress) {
+        float s = progress / 100.0f;
+        mScript.set_gNoiseStrength(s);
+    }
+
+    private int findHighBit(int v) {
+        int bit = 0;
+        while (v > 1) {
+            bit++;
+            v >>= 1;
+        }
+        return bit;
+    }
+
+
+    public void createTest(android.content.res.Resources res) {
+        int width = mInPixelsAllocation.getType().getX();
+        int height = mInPixelsAllocation.getType().getY();
+
+        int noiseW = findHighBit(width);
+        int noiseH = findHighBit(height);
+        if (noiseW > 9) {
+            noiseW = 9;
+        }
+        if (noiseH > 9) {
+            noiseH = 9;
+        }
+        noiseW = 1 << noiseW;
+        noiseH = 1 << noiseH;
+
+        Type.Builder tb = new Type.Builder(mRS, Element.U8(mRS));
+        tb.setX(noiseW);
+        tb.setY(noiseH);
+        mNoise = Allocation.createTyped(mRS, tb.create());
+        mNoise2 = Allocation.createTyped(mRS, tb.create());
+
+        mScript = new ScriptC_grain(mRS, res, R.raw.grain);
+        mScript.set_gWMask(noiseW - 1);
+        mScript.set_gHMask(noiseH - 1);
+        mScript.set_gNoiseStrength(0.5f);
+        mScript.set_gBlendSource(mNoise);
+        mScript.set_gNoise(mNoise2);
+    }
+
+    public void runTest() {
+        mScript.forEach_genRand(mNoise);
+        mScript.forEach_blend9(mNoise2);
+        mScript.forEach_root(mInPixelsAllocation, mOutPixelsAllocation);
+    }
+
+}
+
diff --git a/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/Greyscale.java b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/Greyscale.java
new file mode 100644
index 0000000..f1952e7
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/Greyscale.java
@@ -0,0 +1,40 @@
+/*
+ * 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.imagejb;
+
+import java.lang.Math;
+
+import android.renderscript.Allocation;
+import android.renderscript.Element;
+import android.renderscript.RenderScript;
+import android.renderscript.Script;
+import android.renderscript.ScriptC;
+import android.renderscript.Type;
+import android.util.Log;
+
+public class Greyscale extends TestBase {
+    private ScriptC_greyscale mScript;
+
+    public void createTest(android.content.res.Resources res) {
+        mScript = new ScriptC_greyscale(mRS, res, R.raw.greyscale);
+    }
+
+    public void runTest() {
+        mScript.forEach_root(mInPixelsAllocation, mOutPixelsAllocation);
+    }
+
+}
diff --git a/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/ImageProcessingActivityJB.java b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/ImageProcessingActivityJB.java
new file mode 100644
index 0000000..b3b06d4
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/ImageProcessingActivityJB.java
@@ -0,0 +1,386 @@
+/*
+ * 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.imagejb;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.graphics.BitmapFactory;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.renderscript.ScriptC;
+import android.renderscript.RenderScript;
+import android.renderscript.Type;
+import android.renderscript.Allocation;
+import android.renderscript.Element;
+import android.renderscript.Script;
+import android.view.SurfaceView;
+import android.view.SurfaceHolder;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
+import android.widget.ImageView;
+import android.widget.SeekBar;
+import android.widget.Spinner;
+import android.widget.TextView;
+import android.view.View;
+import android.util.Log;
+import java.lang.Math;
+
+import android.os.Environment;
+import android.app.Instrumentation;
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+
+public class ImageProcessingActivityJB extends Activity
+                                       implements SeekBar.OnSeekBarChangeListener {
+    private final String TAG = "Img";
+    private final String RESULT_FILE = "image_processing_result.csv";
+
+    Bitmap mBitmapIn;
+    Bitmap mBitmapIn2;
+    Bitmap mBitmapOut;
+    String mTestNames[];
+
+    private Spinner mSpinner;
+    private SeekBar mBar1;
+    private SeekBar mBar2;
+    private SeekBar mBar3;
+    private SeekBar mBar4;
+    private SeekBar mBar5;
+    private TextView mText1;
+    private TextView mText2;
+    private TextView mText3;
+    private TextView mText4;
+    private TextView mText5;
+
+    private float mSaturation = 1.0f;
+
+    private TextView mBenchmarkResult;
+    private Spinner mTestSpinner;
+
+    private SurfaceView mSurfaceView;
+    private ImageView mDisplayView;
+
+    private boolean mDoingBenchmark;
+
+    private TestBase mTest;
+    private int mRunCount;
+
+    public void updateDisplay() {
+        mHandler.sendMessage(Message.obtain());
+    }
+
+    private Handler mHandler = new Handler() {
+        @Override
+        public void handleMessage(Message msg) {
+            mTest.updateBitmap(mBitmapOut);
+            mDisplayView.invalidate();
+
+            android.util.Log.v("Img", "mRunCount hdl " + mRunCount);
+            boolean doTest = false;
+            synchronized(this) {
+                if (mRunCount > 0) {
+                    mRunCount--;
+                    if (mRunCount > 0) {
+                        doTest = true;
+                    }
+                }
+            }
+            if (doTest) {
+                mTest.runTestSendMessage();
+            }
+        }
+
+    };
+
+    public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
+        if (fromUser) {
+
+            if (seekBar == mBar1) {
+                mTest.onBar1Changed(progress);
+            } else if (seekBar == mBar2) {
+                mTest.onBar2Changed(progress);
+            } else if (seekBar == mBar3) {
+                mTest.onBar3Changed(progress);
+            } else if (seekBar == mBar4) {
+                mTest.onBar4Changed(progress);
+            } else if (seekBar == mBar5) {
+                mTest.onBar5Changed(progress);
+            }
+
+            boolean doTest = false;
+            synchronized(this) {
+                if (mRunCount == 0) {
+                    doTest = true;
+                    mRunCount = 1;
+                } else {
+                    mRunCount = 2;
+                }
+            }
+            if (doTest) {
+                mTest.runTestSendMessage();
+            }
+        }
+    }
+
+    public void onStartTrackingTouch(SeekBar seekBar) {
+    }
+
+    public void onStopTrackingTouch(SeekBar seekBar) {
+    }
+
+    void setupBars() {
+        mSpinner.setVisibility(View.VISIBLE);
+        mTest.onSpinner1Setup(mSpinner);
+
+        mBar1.setVisibility(View.VISIBLE);
+        mText1.setVisibility(View.VISIBLE);
+        mTest.onBar1Setup(mBar1, mText1);
+
+        mBar2.setVisibility(View.VISIBLE);
+        mText2.setVisibility(View.VISIBLE);
+        mTest.onBar2Setup(mBar2, mText2);
+
+        mBar3.setVisibility(View.VISIBLE);
+        mText3.setVisibility(View.VISIBLE);
+        mTest.onBar3Setup(mBar3, mText3);
+
+        mBar4.setVisibility(View.VISIBLE);
+        mText4.setVisibility(View.VISIBLE);
+        mTest.onBar4Setup(mBar4, mText4);
+
+        mBar5.setVisibility(View.VISIBLE);
+        mText5.setVisibility(View.VISIBLE);
+        mTest.onBar5Setup(mBar5, mText5);
+    }
+
+
+    void changeTest(int testID) {
+        if (mTest != null) {
+            mTest.destroy();
+        }
+        switch(testID) {
+        case 0:
+            mTest = new LevelsV4(false, false);
+            break;
+        case 1:
+            mTest = new LevelsV4(false, true);
+            break;
+        case 2:
+            mTest = new LevelsV4(true, false);
+            break;
+        case 3:
+            mTest = new LevelsV4(true, true);
+            break;
+        case 4:
+            mTest = new Blur25();
+            break;
+        case 5:
+            mTest = new Greyscale();
+            break;
+        case 6:
+            mTest = new Grain();
+            break;
+        case 7:
+            mTest = new Vignette(false);
+            break;
+        case 8:
+            mTest = new Vignette(true);
+            break;
+        case 9:
+            mTest = new Convolve3x3();
+            break;
+        case 10:
+            mTest = new ColorMatrix(false);
+            break;
+        case 11:
+            mTest = new Copy();
+            break;
+        case 12:
+            mTest = new Convolve5x5();
+            break;
+        case 13:
+            mTest = new Mandelbrot();
+            break;
+        }
+
+        mTest.createBaseTest(this, mBitmapIn, mBitmapIn2);
+        setupBars();
+
+        mTest.runTest();
+        updateDisplay();
+        mBenchmarkResult.setText("Result: not run");
+    }
+
+    void setupTests() {
+        mTestNames = new String[14];
+        mTestNames[0] = "Levels Vec3 Relaxed";
+        mTestNames[1] = "Levels Vec4 Relaxed";
+        mTestNames[2] = "Levels Vec3 Full";
+        mTestNames[3] = "Levels Vec4 Full";
+        mTestNames[4] = "Blur radius 25";
+        mTestNames[5] = "Greyscale";
+        mTestNames[6] = "Grain";
+        mTestNames[7] = "Vignette Full";
+        mTestNames[8] = "Vignette Relaxed";
+        mTestNames[9] = "Convolve 3x3";
+        mTestNames[10] = "ColorMatrix";
+        mTestNames[11] = "Copy";
+        mTestNames[12] = "Convolve 5x5";
+        mTestNames[13] = "Mandelbrot";
+
+        mTestSpinner.setAdapter(new ArrayAdapter<String>(
+            this, R.layout.spinner_layout, mTestNames));
+    }
+
+    private AdapterView.OnItemSelectedListener mTestSpinnerListener =
+            new AdapterView.OnItemSelectedListener() {
+                public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
+                    changeTest(pos);
+                }
+
+                public void onNothingSelected(AdapterView parent) {
+
+                }
+            };
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.main);
+
+        mBitmapIn = loadBitmap(R.drawable.img1600x1067);
+        mBitmapIn2 = loadBitmap(R.drawable.img1600x1067b);
+        mBitmapOut = Bitmap.createBitmap(mBitmapIn.getWidth(), mBitmapIn.getHeight(),
+                                         mBitmapIn.getConfig());
+
+        mSurfaceView = (SurfaceView) findViewById(R.id.surface);
+
+        mDisplayView = (ImageView) findViewById(R.id.display);
+        mDisplayView.setImageBitmap(mBitmapOut);
+
+        mSpinner = (Spinner) findViewById(R.id.spinner1);
+
+        mBar1 = (SeekBar) findViewById(R.id.slider1);
+        mBar2 = (SeekBar) findViewById(R.id.slider2);
+        mBar3 = (SeekBar) findViewById(R.id.slider3);
+        mBar4 = (SeekBar) findViewById(R.id.slider4);
+        mBar5 = (SeekBar) findViewById(R.id.slider5);
+
+        mBar1.setOnSeekBarChangeListener(this);
+        mBar2.setOnSeekBarChangeListener(this);
+        mBar3.setOnSeekBarChangeListener(this);
+        mBar4.setOnSeekBarChangeListener(this);
+        mBar5.setOnSeekBarChangeListener(this);
+
+        mText1 = (TextView) findViewById(R.id.slider1Text);
+        mText2 = (TextView) findViewById(R.id.slider2Text);
+        mText3 = (TextView) findViewById(R.id.slider3Text);
+        mText4 = (TextView) findViewById(R.id.slider4Text);
+        mText5 = (TextView) findViewById(R.id.slider5Text);
+
+        mTestSpinner = (Spinner) findViewById(R.id.filterselection);
+        mTestSpinner.setOnItemSelectedListener(mTestSpinnerListener);
+
+        mBenchmarkResult = (TextView) findViewById(R.id.benchmarkText);
+        mBenchmarkResult.setText("Result: not run");
+
+        setupTests();
+        changeTest(0);
+    }
+
+
+    private Bitmap loadBitmap(int resource) {
+        final BitmapFactory.Options options = new BitmapFactory.Options();
+        options.inPreferredConfig = Bitmap.Config.ARGB_8888;
+        return BitmapFactory.decodeResource(getResources(), resource, options);
+    }
+
+    // button hook
+    public void benchmark(View v) {
+        float t = getBenchmark();
+        //long javaTime = javaFilter();
+        //mBenchmarkResult.setText("RS: " + t + " ms  Java: " + javaTime + " ms");
+        mBenchmarkResult.setText("Result: " + t + " ms");
+        Log.v(TAG, "getBenchmark: Renderscript frame time core ms " + t);
+    }
+
+    public void benchmark_all(View v) {
+        // write result into a file
+        File externalStorage = Environment.getExternalStorageDirectory();
+        if (!externalStorage.canWrite()) {
+            Log.v(TAG, "sdcard is not writable");
+            return;
+        }
+        File resultFile = new File(externalStorage, RESULT_FILE);
+        resultFile.setWritable(true, false);
+        try {
+            BufferedWriter rsWriter = new BufferedWriter(new FileWriter(resultFile));
+            Log.v(TAG, "Saved results in: " + resultFile.getAbsolutePath());
+            for (int i = 0; i < mTestNames.length; i++ ) {
+                changeTest(i);
+                float t = getBenchmark();
+                String s = new String("" + mTestNames[i] + ", " + t);
+                rsWriter.write(s + "\n");
+                Log.v(TAG, "Test " + s + "ms\n");
+            }
+            rsWriter.close();
+        } catch (IOException e) {
+            Log.v(TAG, "Unable to write result file " + e.getMessage());
+        }
+        changeTest(0);
+    }
+
+    // For benchmark test
+    public float getBenchmark() {
+        mDoingBenchmark = true;
+
+        mTest.setupBenchmark();
+        long result = 0;
+
+        //Log.v(TAG, "Warming");
+        long t = java.lang.System.currentTimeMillis() + 250;
+        do {
+            mTest.runTest();
+            mTest.finish();
+        } while (t > java.lang.System.currentTimeMillis());
+
+
+        //Log.v(TAG, "Benchmarking");
+        int ct = 0;
+        t = java.lang.System.currentTimeMillis();
+        do {
+            mTest.runTest();
+            mTest.finish();
+            ct++;
+        } while ((t+1000) > java.lang.System.currentTimeMillis());
+        t = java.lang.System.currentTimeMillis() - t;
+        float ft = (float)t;
+        ft /= ct;
+
+        mTest.exitBenchmark();
+        mDoingBenchmark = false;
+
+        return ft;
+    }
+}
diff --git a/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/LevelsV4.java b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/LevelsV4.java
new file mode 100644
index 0000000..741e480
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/LevelsV4.java
@@ -0,0 +1,167 @@
+/*
+ * 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.imagejb;
+
+import java.lang.Math;
+
+import android.renderscript.Allocation;
+import android.renderscript.Element;
+import android.renderscript.RenderScript;
+import android.renderscript.Matrix3f;
+import android.renderscript.Script;
+import android.renderscript.ScriptC;
+import android.renderscript.Type;
+import android.util.Log;
+import android.widget.SeekBar;
+import android.widget.TextView;
+
+
+public class LevelsV4 extends TestBase {
+    private ScriptC_levels_relaxed mScriptR;
+    private ScriptC_levels_full mScriptF;
+    private float mInBlack = 0.0f;
+    private float mOutBlack = 0.0f;
+    private float mInWhite = 255.0f;
+    private float mOutWhite = 255.0f;
+    private float mSaturation = 1.0f;
+
+    Matrix3f satMatrix = new Matrix3f();
+    float mInWMinInB;
+    float mOutWMinOutB;
+    float mOverInWMinInB;
+
+    boolean mUseFull;
+    boolean mUseV4;
+
+    LevelsV4(boolean useFull, boolean useV4) {
+        mUseFull = useFull;
+        mUseV4 = useV4;
+    }
+
+
+    private void setLevels() {
+        mInWMinInB = mInWhite - mInBlack;
+        mOutWMinOutB = mOutWhite - mOutBlack;
+        mOverInWMinInB = 1.f / mInWMinInB;
+
+        mScriptR.set_inBlack(mInBlack);
+        mScriptR.set_outBlack(mOutBlack);
+        mScriptR.set_inWMinInB(mInWMinInB);
+        mScriptR.set_outWMinOutB(mOutWMinOutB);
+        mScriptR.set_overInWMinInB(mOverInWMinInB);
+        mScriptF.set_inBlack(mInBlack);
+        mScriptF.set_outBlack(mOutBlack);
+        mScriptF.set_inWMinInB(mInWMinInB);
+        mScriptF.set_outWMinOutB(mOutWMinOutB);
+        mScriptF.set_overInWMinInB(mOverInWMinInB);
+    }
+
+    private void setSaturation() {
+        float rWeight = 0.299f;
+        float gWeight = 0.587f;
+        float bWeight = 0.114f;
+        float oneMinusS = 1.0f - mSaturation;
+
+        satMatrix.set(0, 0, oneMinusS * rWeight + mSaturation);
+        satMatrix.set(0, 1, oneMinusS * rWeight);
+        satMatrix.set(0, 2, oneMinusS * rWeight);
+        satMatrix.set(1, 0, oneMinusS * gWeight);
+        satMatrix.set(1, 1, oneMinusS * gWeight + mSaturation);
+        satMatrix.set(1, 2, oneMinusS * gWeight);
+        satMatrix.set(2, 0, oneMinusS * bWeight);
+        satMatrix.set(2, 1, oneMinusS * bWeight);
+        satMatrix.set(2, 2, oneMinusS * bWeight + mSaturation);
+        mScriptR.set_colorMat(satMatrix);
+        mScriptF.set_colorMat(satMatrix);
+    }
+
+    public boolean onBar1Setup(SeekBar b, TextView t) {
+        b.setProgress(50);
+        t.setText("Saturation");
+        return true;
+    }
+    public boolean onBar2Setup(SeekBar b, TextView t) {
+        b.setMax(128);
+        b.setProgress(0);
+        t.setText("In Black");
+        return true;
+    }
+    public boolean onBar3Setup(SeekBar b, TextView t) {
+        b.setMax(128);
+        b.setProgress(0);
+        t.setText("Out Black");
+        return true;
+    }
+    public boolean onBar4Setup(SeekBar b, TextView t) {
+        b.setMax(128);
+        b.setProgress(128);
+        t.setText("Out White");
+        return true;
+    }
+    public boolean onBar5Setup(SeekBar b, TextView t) {
+        b.setMax(128);
+        b.setProgress(128);
+        t.setText("Out White");
+        return true;
+    }
+
+    public void onBar1Changed(int progress) {
+        mSaturation = (float)progress / 50.0f;
+        setSaturation();
+    }
+    public void onBar2Changed(int progress) {
+        mInBlack = (float)progress;
+        setLevels();
+    }
+    public void onBar3Changed(int progress) {
+        mOutBlack = (float)progress;
+        setLevels();
+    }
+    public void onBar4Changed(int progress) {
+        mInWhite = (float)progress + 127.0f;
+        setLevels();
+    }
+    public void onBar5Changed(int progress) {
+        mOutWhite = (float)progress + 127.0f;
+        setLevels();
+    }
+
+    public void createTest(android.content.res.Resources res) {
+        mScriptR = new ScriptC_levels_relaxed(mRS, res, R.raw.levels_relaxed);
+        mScriptF = new ScriptC_levels_full(mRS, res, R.raw.levels_full);
+        setSaturation();
+        setLevels();
+    }
+
+    public void runTest() {
+        if (mUseFull) {
+            if (mUseV4) {
+                mScriptF.forEach_root4(mInPixelsAllocation, mOutPixelsAllocation);
+            } else {
+                mScriptF.forEach_root(mInPixelsAllocation, mOutPixelsAllocation);
+            }
+        } else {
+            if (mUseV4) {
+                mScriptR.forEach_root4(mInPixelsAllocation, mOutPixelsAllocation);
+            } else {
+                mScriptR.forEach_root(mInPixelsAllocation, mOutPixelsAllocation);
+            }
+        }
+    }
+
+}
+
diff --git a/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/Mandelbrot.java b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/Mandelbrot.java
new file mode 100644
index 0000000..ca34848
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/Mandelbrot.java
@@ -0,0 +1,98 @@
+/*
+ * 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.imagejb;
+
+import java.lang.Math;
+
+import android.renderscript.Allocation;
+import android.renderscript.Element;
+import android.renderscript.RenderScript;
+import android.renderscript.Script;
+import android.renderscript.ScriptC;
+import android.renderscript.Type;
+import android.util.Log;
+import android.widget.SeekBar;
+import android.widget.TextView;
+
+public class Mandelbrot extends TestBase {
+    private ScriptC_mandelbrot mScript;
+
+    public boolean onBar1Setup(SeekBar b, TextView t) {
+        t.setText("Iterations");
+        b.setProgress(0);
+        return true;
+    }
+
+    public void onBar1Changed(int progress) {
+        int iters = progress * 3 + 50;
+        mScript.set_gMaxIteration(iters);
+    }
+
+    public boolean onBar2Setup(SeekBar b, TextView t) {
+        t.setText("Lower Bound: X");
+        b.setProgress(0);
+        return true;
+    }
+
+    public void onBar2Changed(int progress) {
+        float scaleFactor = mScript.get_scaleFactor();
+        // allow viewport to be moved by 2x scale factor
+        float lowerBoundX = -2.f + ((progress / scaleFactor) / 50.f);
+        mScript.set_lowerBoundX(lowerBoundX);
+    }
+
+    public boolean onBar3Setup(SeekBar b, TextView t) {
+        t.setText("Lower Bound: Y");
+        b.setProgress(0);
+        return true;
+    }
+
+    public void onBar3Changed(int progress) {
+        float scaleFactor = mScript.get_scaleFactor();
+        // allow viewport to be moved by 2x scale factor
+        float lowerBoundY = -2.f + ((progress / scaleFactor) / 50.f);
+        mScript.set_lowerBoundY(lowerBoundY);
+    }
+
+    public boolean onBar4Setup(SeekBar b, TextView t) {
+        t.setText("Scale Factor");
+        b.setProgress(0);
+        return true;
+    }
+
+    public void onBar4Changed(int progress) {
+        float scaleFactor = 4.f - (3.96f * (progress / 100.f));
+        mScript.set_scaleFactor(scaleFactor);
+    }
+
+    public void createTest(android.content.res.Resources res) {
+        int width = mOutPixelsAllocation.getType().getX();
+        int height = mOutPixelsAllocation.getType().getY();
+
+        mScript = new ScriptC_mandelbrot(mRS, res, R.raw.mandelbrot);
+        mScript.set_gDimX(width);
+        mScript.set_gDimY(height);
+        mScript.set_gMaxIteration(50);
+    }
+
+    public void runTest() {
+        mScript.forEach_root(mOutPixelsAllocation);
+        mRS.finish();
+    }
+
+}
+
diff --git a/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/TestBase.java b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/TestBase.java
new file mode 100644
index 0000000..ed22578
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/TestBase.java
@@ -0,0 +1,161 @@
+/*
+ * 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.imagejb;
+
+import android.app.Activity;
+import android.content.Context;
+import android.os.Bundle;
+import android.graphics.BitmapFactory;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.renderscript.ScriptC;
+import android.renderscript.RenderScript;
+import android.renderscript.Type;
+import android.renderscript.Allocation;
+import android.renderscript.Element;
+import android.renderscript.Script;
+import android.view.SurfaceView;
+import android.view.SurfaceHolder;
+import android.widget.ImageView;
+import android.widget.SeekBar;
+import android.widget.TextView;
+import android.view.View;
+import android.util.Log;
+import java.lang.Math;
+import android.widget.Spinner;
+
+public class TestBase  {
+    protected final String TAG = "Img";
+
+    protected RenderScript mRS;
+    protected Allocation mInPixelsAllocation;
+    protected Allocation mInPixelsAllocation2;
+    protected Allocation mOutPixelsAllocation;
+    protected ScriptC_msg mMessageScript;
+
+    protected ImageProcessingActivityJB act;
+
+    private class MessageProcessor extends RenderScript.RSMessageHandler {
+        ImageProcessingActivityJB mAct;
+
+        MessageProcessor(ImageProcessingActivityJB act) {
+            mAct = act;
+        }
+
+        public void run() {
+            mAct.updateDisplay();
+        }
+    }
+
+    // Override to use UI elements
+    public void onBar1Changed(int progress) {
+    }
+    public void onBar2Changed(int progress) {
+    }
+    public void onBar3Changed(int progress) {
+    }
+    public void onBar4Changed(int progress) {
+    }
+    public void onBar5Changed(int progress) {
+    }
+
+    // Override to use UI elements
+    // Unused bars will be hidden.
+    public boolean onBar1Setup(SeekBar b, TextView t) {
+        b.setVisibility(View.INVISIBLE);
+        t.setVisibility(View.INVISIBLE);
+        return false;
+    }
+    public boolean onBar2Setup(SeekBar b, TextView t) {
+        b.setVisibility(View.INVISIBLE);
+        t.setVisibility(View.INVISIBLE);
+        return false;
+    }
+    public boolean onBar3Setup(SeekBar b, TextView t) {
+        b.setVisibility(View.INVISIBLE);
+        t.setVisibility(View.INVISIBLE);
+        return false;
+    }
+    public boolean onBar4Setup(SeekBar b, TextView t) {
+        b.setVisibility(View.INVISIBLE);
+        t.setVisibility(View.INVISIBLE);
+        return false;
+    }
+    public boolean onBar5Setup(SeekBar b, TextView t) {
+        b.setVisibility(View.INVISIBLE);
+        t.setVisibility(View.INVISIBLE);
+        return false;
+    }
+
+    public boolean onSpinner1Setup(Spinner s) {
+        s.setVisibility(View.INVISIBLE);
+        return false;
+    }
+
+    public final void createBaseTest(ImageProcessingActivityJB ipact, Bitmap b, Bitmap b2) {
+        act = ipact;
+        mRS = RenderScript.create(act);
+        mRS.setMessageHandler(new MessageProcessor(act));
+        mMessageScript = new ScriptC_msg(mRS);
+        mInPixelsAllocation = Allocation.createFromBitmap(mRS, b,
+                                                          Allocation.MipmapControl.MIPMAP_NONE,
+                                                          Allocation.USAGE_SCRIPT);
+        mInPixelsAllocation2 = Allocation.createFromBitmap(mRS, b2,
+                                                          Allocation.MipmapControl.MIPMAP_NONE,
+                                                          Allocation.USAGE_SCRIPT);
+        mOutPixelsAllocation = Allocation.createFromBitmap(mRS, b,
+                                                           Allocation.MipmapControl.MIPMAP_NONE,
+                                                           Allocation.USAGE_SCRIPT);
+        createTest(act.getResources());
+    }
+
+    // Must override
+    public void createTest(android.content.res.Resources res) {
+        android.util.Log.e("img", "implement createTest");
+    }
+
+    // Must override
+    public void runTest() {
+    }
+
+    final public void runTestSendMessage() {
+        android.util.Log.v("Img", "run");
+        runTest();
+        mMessageScript.invoke_sendMsg();
+    }
+
+    public void finish() {
+        mRS.finish();
+    }
+
+    public void destroy() {
+        mRS.destroy();
+        mRS = null;
+    }
+
+    public void updateBitmap(Bitmap b) {
+        mOutPixelsAllocation.copyTo(b);
+    }
+
+    // Override to configure specific benchmark config.
+    public void setupBenchmark() {
+    }
+
+    // Override to reset after benchmark.
+    public void exitBenchmark() {
+    }
+}
diff --git a/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/Vignette.java b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/Vignette.java
new file mode 100644
index 0000000..487cd63
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/Vignette.java
@@ -0,0 +1,125 @@
+/*
+ * 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.imagejb;
+
+import android.renderscript.Allocation;
+import android.renderscript.Element;
+import android.renderscript.Sampler;
+import android.renderscript.Type;
+import android.widget.SeekBar;
+import android.widget.TextView;
+
+public class Vignette extends TestBase {
+    private ScriptC_vignette_full mScript_full = null;
+    private ScriptC_vignette_relaxed mScript_relaxed = null;
+    private final boolean relaxed;
+    private float center_x = 0.5f;
+    private float center_y = 0.5f;
+    private float scale = 0.5f;
+    private float shade = 0.5f;
+    private float slope = 20.0f;
+
+    public Vignette(boolean relaxed) {
+        this.relaxed = relaxed;
+    }
+
+    public boolean onBar1Setup(SeekBar b, TextView t) {
+        t.setText("Scale");
+        b.setMax(100);
+        b.setProgress(25);
+        return true;
+    }
+    public boolean onBar2Setup(SeekBar b, TextView t) {
+        t.setText("Shade");
+        b.setMax(100);
+        b.setProgress(50);
+        return true;
+    }
+    public boolean onBar3Setup(SeekBar b, TextView t) {
+        t.setText("Slope");
+        b.setMax(100);
+        b.setProgress(20);
+        return true;
+    }
+    public boolean onBar4Setup(SeekBar b, TextView t) {
+        t.setText("Shift center X");
+        b.setMax(100);
+        b.setProgress(50);
+        return true;
+    }
+    public boolean onBar5Setup(SeekBar b, TextView t) {
+        t.setText("Shift center Y");
+        b.setMax(100);
+        b.setProgress(50);
+        return true;
+    }
+
+    public void onBar1Changed(int progress) {
+        scale = progress / 50.0f;
+        do_init();
+    }
+    public void onBar2Changed(int progress) {
+        shade = progress / 100.0f;
+        do_init();
+    }
+    public void onBar3Changed(int progress) {
+        slope = (float)progress;
+        do_init();
+    }
+    public void onBar4Changed(int progress) {
+        center_x = progress / 100.0f;
+        do_init();
+    }
+    public void onBar5Changed(int progress) {
+        center_y = progress / 100.0f;
+        do_init();
+    }
+
+    private void do_init() {
+        if (relaxed)
+            mScript_relaxed.invoke_init_vignette(
+                    mInPixelsAllocation.getType().getX(),
+                    mInPixelsAllocation.getType().getY(), center_x, center_y,
+                    scale, shade, slope);
+        else
+            mScript_full.invoke_init_vignette(
+                    mInPixelsAllocation.getType().getX(),
+                    mInPixelsAllocation.getType().getY(), center_x, center_y,
+                    scale, shade, slope);
+    }
+
+    public void createTest(android.content.res.Resources res) {
+        if (relaxed)
+            mScript_relaxed = new ScriptC_vignette_relaxed(mRS, res,
+                    R.raw.vignette_relaxed);
+        else
+            mScript_full = new ScriptC_vignette_full(mRS, res,
+                    R.raw.vignette_full);
+        do_init();
+    }
+
+    public void runTest() {
+        if (relaxed)
+            mScript_relaxed.forEach_root(mInPixelsAllocation,
+                    mOutPixelsAllocation);
+        else
+            mScript_full.forEach_root(mInPixelsAllocation,
+                    mOutPixelsAllocation);
+    }
+
+}
+
diff --git a/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/colormatrix.rs b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/colormatrix.rs
new file mode 100644
index 0000000..772cb83
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/colormatrix.rs
@@ -0,0 +1,38 @@
+/*
+ * 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.imagejb)
+#pragma rs_fp_relaxed
+
+
+static rs_matrix4x4 Mat;
+
+void init() {
+    rsMatrixLoadIdentity(&Mat);
+}
+
+void setMatrix(rs_matrix4x4 m) {
+    Mat = m;
+}
+
+void root(const uchar4 *in, uchar4 *out) {
+    float4 f = convert_float4(*in);
+    f = rsMatrixMultiply(&Mat, f);
+    f = clamp(f, 0.f, 255.f);
+    *out = convert_uchar4(f);
+}
+
diff --git a/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/convolve3x3.rs b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/convolve3x3.rs
new file mode 100644
index 0000000..f12f6ce
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/convolve3x3.rs
@@ -0,0 +1,71 @@
+/*
+ * 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.imagejb)
+#pragma rs_fp_relaxed
+
+int32_t gWidth;
+int32_t gHeight;
+rs_allocation gIn;
+
+float gCoeffs[9];
+
+static inline uchar4 GetElementAt_uchar4(rs_allocation a, uint32_t x, uint32_t y) {
+    return ((uchar4 *)rsGetElementAt(a, x, y))[0];
+}
+
+void root(uchar4 *out, uint32_t x, uint32_t y) {
+    uint32_t x1 = min((int32_t)x+1, gWidth-1);
+    uint32_t x2 = max((int32_t)x-1, 0);
+    uint32_t y1 = min((int32_t)y+1, gHeight-1);
+    uint32_t y2 = max((int32_t)y-1, 0);
+
+    float4 p00 = convert_float4(GetElementAt_uchar4(gIn, x1, y1));
+    float4 p01 = convert_float4(GetElementAt_uchar4(gIn, x, y1));
+    float4 p02 = convert_float4(GetElementAt_uchar4(gIn, x2, y1));
+    float4 p10 = convert_float4(GetElementAt_uchar4(gIn, x1, y));
+    float4 p11 = convert_float4(GetElementAt_uchar4(gIn, x, y));
+    float4 p12 = convert_float4(GetElementAt_uchar4(gIn, x2, y));
+    float4 p20 = convert_float4(GetElementAt_uchar4(gIn, x1, y2));
+    float4 p21 = convert_float4(GetElementAt_uchar4(gIn, x, y2));
+    float4 p22 = convert_float4(GetElementAt_uchar4(gIn, x2, y2));
+    p00 *= gCoeffs[0];
+    p01 *= gCoeffs[1];
+    p02 *= gCoeffs[2];
+    p10 *= gCoeffs[3];
+    p11 *= gCoeffs[4];
+    p12 *= gCoeffs[5];
+    p20 *= gCoeffs[6];
+    p21 *= gCoeffs[7];
+    p22 *= gCoeffs[8];
+
+    p00 += p01;
+    p02 += p10;
+    p11 += p12;
+    p20 += p21;
+
+    p22 += p00;
+    p02 += p11;
+
+    p20 += p22;
+    p20 += p02;
+
+    p20 = clamp(p20, 0.f, 255.f);
+    *out = convert_uchar4(p20);
+}
+
+
diff --git a/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/convolve5x5.rs b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/convolve5x5.rs
new file mode 100644
index 0000000..6e23d79
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/convolve5x5.rs
@@ -0,0 +1,78 @@
+/*
+ * 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.imagejb)
+#pragma rs_fp_relaxed
+
+int32_t gWidth;
+int32_t gHeight;
+rs_allocation gIn;
+
+float gCoeffs[25];
+
+static inline uchar4 GetElementAt_uchar4(rs_allocation a, uint32_t x, uint32_t y) {
+    return ((uchar4 *)rsGetElementAt(a, x, y))[0];
+}
+
+void root(uchar4 *out, uint32_t x, uint32_t y) {
+    uint32_t x0 = max((int32_t)x-2, 0);
+    uint32_t x1 = max((int32_t)x-1, 0);
+    uint32_t x2 = x;
+    uint32_t x3 = min((int32_t)x+1, gWidth-1);
+    uint32_t x4 = min((int32_t)x+2, gWidth-1);
+
+    uint32_t y0 = max((int32_t)y-2, 0);
+    uint32_t y1 = max((int32_t)y-1, 0);
+    uint32_t y2 = y;
+    uint32_t y3 = min((int32_t)y+1, gHeight-1);
+    uint32_t y4 = min((int32_t)y+2, gHeight-1);
+
+    float4 p0 = convert_float4(GetElementAt_uchar4(gIn, x0, y0)) * gCoeffs[0]
+              + convert_float4(GetElementAt_uchar4(gIn, x1, y0)) * gCoeffs[1]
+              + convert_float4(GetElementAt_uchar4(gIn, x2, y0)) * gCoeffs[2]
+              + convert_float4(GetElementAt_uchar4(gIn, x3, y0)) * gCoeffs[3]
+              + convert_float4(GetElementAt_uchar4(gIn, x4, y0)) * gCoeffs[4];
+
+    float4 p1 = convert_float4(GetElementAt_uchar4(gIn, x0, y1)) * gCoeffs[5]
+              + convert_float4(GetElementAt_uchar4(gIn, x1, y1)) * gCoeffs[6]
+              + convert_float4(GetElementAt_uchar4(gIn, x2, y1)) * gCoeffs[7]
+              + convert_float4(GetElementAt_uchar4(gIn, x3, y1)) * gCoeffs[8]
+              + convert_float4(GetElementAt_uchar4(gIn, x4, y1)) * gCoeffs[9];
+
+    float4 p2 = convert_float4(GetElementAt_uchar4(gIn, x0, y2)) * gCoeffs[10]
+              + convert_float4(GetElementAt_uchar4(gIn, x1, y2)) * gCoeffs[11]
+              + convert_float4(GetElementAt_uchar4(gIn, x2, y2)) * gCoeffs[12]
+              + convert_float4(GetElementAt_uchar4(gIn, x3, y2)) * gCoeffs[13]
+              + convert_float4(GetElementAt_uchar4(gIn, x4, y2)) * gCoeffs[14];
+
+    float4 p3 = convert_float4(GetElementAt_uchar4(gIn, x0, y3)) * gCoeffs[15]
+              + convert_float4(GetElementAt_uchar4(gIn, x1, y3)) * gCoeffs[16]
+              + convert_float4(GetElementAt_uchar4(gIn, x2, y3)) * gCoeffs[17]
+              + convert_float4(GetElementAt_uchar4(gIn, x3, y3)) * gCoeffs[18]
+              + convert_float4(GetElementAt_uchar4(gIn, x4, y3)) * gCoeffs[19];
+
+    float4 p4 = convert_float4(GetElementAt_uchar4(gIn, x0, y4)) * gCoeffs[20]
+              + convert_float4(GetElementAt_uchar4(gIn, x1, y4)) * gCoeffs[21]
+              + convert_float4(GetElementAt_uchar4(gIn, x2, y4)) * gCoeffs[22]
+              + convert_float4(GetElementAt_uchar4(gIn, x3, y4)) * gCoeffs[23]
+              + convert_float4(GetElementAt_uchar4(gIn, x4, y4)) * gCoeffs[24];
+
+    p0 = clamp(p0 + p1 + p2 + p3 + p4, 0.f, 255.f);
+    *out = convert_uchar4(p0);
+}
+
+
diff --git a/include/diskusage/dirsize.h b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/copy.rs
similarity index 60%
copy from include/diskusage/dirsize.h
copy to tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/copy.rs
index 34236c0..17f7cff 100644
--- a/include/diskusage/dirsize.h
+++ b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/copy.rs
@@ -1,12 +1,11 @@
 /*
- *
- * Copyright (C) 2010 The Android Open Source Project
+ * 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
+ *      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,
@@ -15,16 +14,11 @@
  * limitations under the License.
  */
 
-#ifndef __LIBDISKUSAGE_DIRSIZE_H
-#define __LIBDISKUSAGE_DIRSIZE_H
+#pragma version(1)
+#pragma rs java_package_name(com.android.rs.imagejb)
 
-#include <stdint.h>
+void root(const uchar4 *in, uchar4 *out) {
+    *out = *in;
+}
 
-__BEGIN_DECLS
 
-int64_t stat_size(struct stat *s);
-int64_t calculate_dir_size(int dfd);
-
-__END_DECLS
-
-#endif /* __LIBDISKUSAGE_DIRSIZE_H */
diff --git a/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/grain.rs b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/grain.rs
new file mode 100644
index 0000000..885ef49
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/grain.rs
@@ -0,0 +1,101 @@
+/*
+ * 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.imagejb)
+#pragma rs_fp_relaxed
+
+void genRand(uchar *out) {
+    *out = (uchar)rsRand(0xff);
+}
+
+static inline uchar GetElementAt_uchar(rs_allocation a, uint32_t x, uint32_t y) {
+    return ((uchar *)rsGetElementAt(a, x, y))[0];
+}
+
+static inline float4 GetElementAt_float4(rs_allocation a, uint32_t x, uint32_t y) {
+    return ((float4 *)rsGetElementAt(a, x, y))[0];
+}
+
+/*
+ * Convolution matrix of distance 2 with fixed point of 'kShiftBits' bits
+ * shifted. Thus the sum of this matrix should be 'kShiftValue'. Entries of
+ * small values are not calculated to gain efficiency.
+ * The order ot pixels represented in this matrix is:
+ *  1  2  3
+ *  4  0  5
+ *  6  7  8
+ *  and the matrix should be: {230, 56, 114, 56, 114, 114, 56, 114, 56}.
+ *  However, since most of the valus are identical, we only use the first three
+ *  entries and the entries corresponding to the pixels is:
+ *  1  2  1
+ *  2  0  2
+ *  1  2  1
+ */
+
+int32_t gWMask;
+int32_t gHMask;
+
+rs_allocation gBlendSource;
+void blend9(uchar *out, uint32_t x, uint32_t y) {
+    uint32_t x1 = (x-1) & gWMask;
+    uint32_t x2 = (x+1) & gWMask;
+    uint32_t y1 = (y-1) & gHMask;
+    uint32_t y2 = (y+1) & gHMask;
+
+    uint p00 = 56 *  GetElementAt_uchar(gBlendSource, x1, y1);
+    uint p01 = 114 * GetElementAt_uchar(gBlendSource, x, y1);
+    uint p02 = 56 *  GetElementAt_uchar(gBlendSource, x2, y1);
+    uint p10 = 114 * GetElementAt_uchar(gBlendSource, x1, y);
+    uint p11 = 230 * GetElementAt_uchar(gBlendSource, x, y);
+    uint p12 = 114 * GetElementAt_uchar(gBlendSource, x2, y);
+    uint p20 = 56 *  GetElementAt_uchar(gBlendSource, x1, y2);
+    uint p21 = 114 * GetElementAt_uchar(gBlendSource, x, y2);
+    uint p22 = 56 *  GetElementAt_uchar(gBlendSource, x2, y2);
+
+    p00 += p01;
+    p02 += p10;
+    p11 += p12;
+    p20 += p21;
+
+    p22 += p00;
+    p02 += p11;
+
+    p20 += p22;
+    p20 += p02;
+
+    p20 = min(p20 >> 10, (uint)255);
+    *out = (uchar)p20;
+}
+
+float gNoiseStrength;
+
+rs_allocation gNoise;
+void root(const uchar4 *in, uchar4 *out, uint32_t x, uint32_t y) {
+    float4 ip = convert_float4(*in);
+    float pnoise = (float) GetElementAt_uchar(gNoise, x & gWMask, y & gHMask);
+
+    float energy_level = ip.r + ip.g + ip.b;
+    float energy_mask = (28.f - sqrt(energy_level)) * 0.03571f;
+    pnoise = (pnoise - 128.f) * energy_mask;
+
+    ip += pnoise * gNoiseStrength;
+    ip = clamp(ip, 0.f, 255.f);
+
+    uchar4 p = convert_uchar4(ip);
+    p.a = 0xff;
+    *out = p;
+}
diff --git a/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/greyscale.rs b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/greyscale.rs
new file mode 100644
index 0000000..b3a7ef0
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/greyscale.rs
@@ -0,0 +1,30 @@
+/*
+ * 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.imagejb)
+#pragma rs_fp_relaxed
+
+const static float3 gMonoMult = {0.299f, 0.587f, 0.114f};
+
+void root(const uchar4 *v_in, uchar4 *out) {
+    float4 f4 = rsUnpackColor8888(*v_in);
+
+    float3 mono = dot(f4.rgb, gMonoMult);
+    *out = rsPackColorTo8888(mono);
+}
+
+
diff --git a/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/levels.rsh b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/levels.rsh
new file mode 100644
index 0000000..a3a2775
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/levels.rsh
@@ -0,0 +1,44 @@
+/*
+ * 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.
+ */
+
+float inBlack;
+float outBlack;
+float inWMinInB;
+float outWMinOutB;
+float overInWMinInB;
+rs_matrix3x3 colorMat;
+
+void root(const uchar4 *in, uchar4 *out, uint32_t x, uint32_t y) {
+    float3 pixel = convert_float4(*in).rgb;
+    pixel = rsMatrixMultiply(&colorMat, pixel);
+    pixel = clamp(pixel, 0.f, 255.f);
+    pixel = (pixel - inBlack) * overInWMinInB;
+    pixel = pixel * outWMinOutB + outBlack;
+    pixel = clamp(pixel, 0.f, 255.f);
+    out->xyz = convert_uchar3(pixel);
+    out->w = 0xff;
+}
+
+void root4(const uchar4 *in, uchar4 *out, uint32_t x, uint32_t y) {
+    float4 pixel = convert_float4(*in);
+    pixel.rgb = rsMatrixMultiply(&colorMat, pixel.rgb);
+    pixel = clamp(pixel, 0.f, 255.f);
+    pixel = (pixel - inBlack) * overInWMinInB;
+    pixel = pixel * outWMinOutB + outBlack;
+    pixel = clamp(pixel, 0.f, 255.f);
+    *out = convert_uchar4(pixel);
+}
+
diff --git a/include/diskusage/dirsize.h b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/levels_full.rs
similarity index 60%
copy from include/diskusage/dirsize.h
copy to tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/levels_full.rs
index 34236c0..dead169 100644
--- a/include/diskusage/dirsize.h
+++ b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/levels_full.rs
@@ -1,12 +1,11 @@
 /*
- *
- * Copyright (C) 2010 The Android Open Source Project
+ * 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
+ *      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,
@@ -15,16 +14,8 @@
  * limitations under the License.
  */
 
-#ifndef __LIBDISKUSAGE_DIRSIZE_H
-#define __LIBDISKUSAGE_DIRSIZE_H
+#pragma version(1)
+#pragma rs java_package_name(com.android.rs.imagejb)
 
-#include <stdint.h>
+#include "levels.rsh"
 
-__BEGIN_DECLS
-
-int64_t stat_size(struct stat *s);
-int64_t calculate_dir_size(int dfd);
-
-__END_DECLS
-
-#endif /* __LIBDISKUSAGE_DIRSIZE_H */
diff --git a/include/diskusage/dirsize.h b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/levels_relaxed.rs
similarity index 60%
copy from include/diskusage/dirsize.h
copy to tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/levels_relaxed.rs
index 34236c0..b2564ef 100644
--- a/include/diskusage/dirsize.h
+++ b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/levels_relaxed.rs
@@ -1,12 +1,11 @@
 /*
- *
- * Copyright (C) 2010 The Android Open Source Project
+ * 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
+ *      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,
@@ -15,16 +14,9 @@
  * limitations under the License.
  */
 
-#ifndef __LIBDISKUSAGE_DIRSIZE_H
-#define __LIBDISKUSAGE_DIRSIZE_H
+#pragma version(1)
+#pragma rs java_package_name(com.android.rs.imagejb)
+#pragma rs_fp_relaxed
 
-#include <stdint.h>
+#include "levels.rsh"
 
-__BEGIN_DECLS
-
-int64_t stat_size(struct stat *s);
-int64_t calculate_dir_size(int dfd);
-
-__END_DECLS
-
-#endif /* __LIBDISKUSAGE_DIRSIZE_H */
diff --git a/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/mandelbrot.rs b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/mandelbrot.rs
new file mode 100644
index 0000000..7cd8488
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/mandelbrot.rs
@@ -0,0 +1,56 @@
+// 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.
+
+#pragma version(1)
+#pragma rs java_package_name(com.android.rs.imagejb)
+
+uint32_t gMaxIteration = 500;
+uint32_t gDimX = 1024;
+uint32_t gDimY = 1024;
+
+float lowerBoundX = -2.f;
+float lowerBoundY = -2.f;
+float scaleFactor = 4.f;
+
+void root(uchar4 *out, uint32_t x, uint32_t y) {
+  float2 p;
+  p.x = lowerBoundX + ((float)x / gDimX) * scaleFactor;
+  p.y = lowerBoundY + ((float)y / gDimY) * scaleFactor;
+
+  float2 t = 0;
+  float2 t2 = t * t;
+  int iter = 0;
+  while((t2.x + t2.y < 4.f) && (iter < gMaxIteration)) {
+    float xtemp = t2.x - t2.y + p.x;
+    t.y = 2 * t.x * t.y + p.y;
+    t.x = xtemp;
+    iter++;
+    t2 = t * t;
+  }
+
+  if(iter >= gMaxIteration) {
+    // write a non-transparent black pixel
+    *out = (uchar4){0, 0, 0, 0xff};
+  } else {
+    float mi3 = gMaxIteration / 3.f;
+    if (iter <= (gMaxIteration / 3))
+      *out = (uchar4){0xff * (iter / mi3), 0, 0, 0xff};
+    else if (iter <= (((gMaxIteration / 3) * 2)))
+      *out = (uchar4){0xff - (0xff * ((iter - mi3) / mi3)),
+                      (0xff * ((iter - mi3) / mi3)), 0, 0xff};
+    else
+      *out = (uchar4){0, 0xff - (0xff * ((iter - (mi3 * 2)) / mi3)),
+                      (0xff * ((iter - (mi3 * 2)) / mi3)), 0xff};
+  }
+}
diff --git a/include/diskusage/dirsize.h b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/msg.rs
similarity index 60%
copy from include/diskusage/dirsize.h
copy to tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/msg.rs
index 34236c0..645eb98 100644
--- a/include/diskusage/dirsize.h
+++ b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/msg.rs
@@ -1,12 +1,11 @@
 /*
- *
- * Copyright (C) 2010 The Android Open Source Project
+ * 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
+ *      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,
@@ -15,16 +14,10 @@
  * limitations under the License.
  */
 
-#ifndef __LIBDISKUSAGE_DIRSIZE_H
-#define __LIBDISKUSAGE_DIRSIZE_H
+#pragma version(1)
+#pragma rs java_package_name(com.android.rs.imagejb)
 
-#include <stdint.h>
+void sendMsg() {
+    rsSendToClientBlocking(0);
+}
 
-__BEGIN_DECLS
-
-int64_t stat_size(struct stat *s);
-int64_t calculate_dir_size(int dfd);
-
-__END_DECLS
-
-#endif /* __LIBDISKUSAGE_DIRSIZE_H */
diff --git a/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/threshold.rs b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/threshold.rs
new file mode 100644
index 0000000..d18117a
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/threshold.rs
@@ -0,0 +1,106 @@
+#pragma version(1)
+#pragma rs java_package_name(com.android.rs.imagejb)
+#pragma rs_fp_relaxed
+
+
+int height;
+int width;
+static int radius;
+
+rs_allocation InPixel;
+rs_allocation ScratchPixel1;
+rs_allocation ScratchPixel2;
+
+const int MAX_RADIUS = 25;
+
+// Store our coefficients here
+static float gaussian[MAX_RADIUS * 2 + 1];
+
+void setRadius(int rad) {
+    radius = rad;
+    // Compute gaussian weights for the blur
+    // e is the euler's number
+    float e = 2.718281828459045f;
+    float pi = 3.1415926535897932f;
+    // g(x) = ( 1 / sqrt( 2 * pi ) * sigma) * e ^ ( -x^2 / 2 * sigma^2 )
+    // x is of the form [-radius .. 0 .. radius]
+    // and sigma varies with radius.
+    // Based on some experimental radius values and sigma's
+    // we approximately fit sigma = f(radius) as
+    // sigma = radius * 0.4  + 0.6
+    // The larger the radius gets, the more our gaussian blur
+    // will resemble a box blur since with large sigma
+    // the gaussian curve begins to lose its shape
+    float sigma = 0.4f * (float)radius + 0.6f;
+
+    // Now compute the coefficints
+    // We will store some redundant values to save some math during
+    // the blur calculations
+    // precompute some values
+    float coeff1 = 1.0f / (sqrt( 2.0f * pi ) * sigma);
+    float coeff2 = - 1.0f / (2.0f * sigma * sigma);
+
+    float normalizeFactor = 0.0f;
+    float floatR = 0.0f;
+    for (int r = -radius; r <= radius; r ++) {
+        floatR = (float)r;
+        gaussian[r + radius] = coeff1 * pow(e, floatR * floatR * coeff2);
+        normalizeFactor += gaussian[r + radius];
+    }
+
+    //Now we need to normalize the weights because all our coefficients need to add up to one
+    normalizeFactor = 1.0f / normalizeFactor;
+    for (int r = -radius; r <= radius; r ++) {
+        floatR = (float)r;
+        gaussian[r + radius] *= normalizeFactor;
+    }
+}
+
+void copyIn(const uchar4 *in, float4 *out) {
+    *out = convert_float4(*in);
+}
+
+static inline float4 GetElementAt_float4(rs_allocation a, uint32_t x, uint32_t y) {
+    return ((float4 *)rsGetElementAt(a, x, y))[0];
+}
+
+void vert(uchar4 *out, uint32_t x, uint32_t y) {
+    float3 blurredPixel = 0;
+    int gi = 0;
+    if ((y > radius) && (y < (height - radius))) {
+        for (int r = -radius; r <= radius; r ++) {
+            float4 i = GetElementAt_float4(ScratchPixel2, x, y + r);
+            blurredPixel += i.xyz * gaussian[gi++];
+        }
+    } else {
+        for (int r = -radius; r <= radius; r ++) {
+            int validH = rsClamp((int)y + r, (int)0, (int)(height - 1));
+            float4 i = GetElementAt_float4(ScratchPixel2, x, validH);
+            blurredPixel += i.xyz * gaussian[gi++];
+        }
+    }
+
+    out->xyz = convert_uchar3(clamp(blurredPixel, 0.f, 255.f));
+    out->w = 0xff;
+}
+
+void horz(float4 *out, uint32_t x, uint32_t y) {
+    float4 blurredPixel = 0;
+    int gi = 0;
+    if ((x > radius) && (x < (width - radius))) {
+        for (int r = -radius; r <= radius; r ++) {
+            float4 i = GetElementAt_float4(ScratchPixel1, x + r, y);
+            blurredPixel += i * gaussian[gi++];
+        }
+    } else {
+        for (int r = -radius; r <= radius; r ++) {
+            // Stepping left and right away from the pixel
+            int validX = rsClamp((int)x + r, (int)0, (int)(width - 1));
+            float4 i = GetElementAt_float4(ScratchPixel1, validX, y);
+            blurredPixel += i * gaussian[gi++];
+        }
+    }
+
+    *out = blurredPixel;
+}
+
diff --git a/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/vignette.rsh b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/vignette.rsh
new file mode 100644
index 0000000..3fef0c3
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/vignette.rsh
@@ -0,0 +1,59 @@
+/*
+ * 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.
+ */
+
+static float2 neg_center, axis_scale, inv_dimensions;
+static float sloped_neg_range, sloped_inv_max_dist, shade, opp_shade;
+
+void init_vignette(uint32_t dim_x, uint32_t dim_y, float center_x, float center_y,
+        float desired_scale, float desired_shade, float desired_slope) {
+
+    neg_center.x = -center_x;
+    neg_center.y = -center_y;
+    inv_dimensions.x = 1.f / (float)dim_x;
+    inv_dimensions.y = 1.f / (float)dim_y;
+
+    axis_scale = (float2)1.f;
+    if (dim_x > dim_y)
+        axis_scale.y = (float)dim_y / (float)dim_x;
+    else
+        axis_scale.x = (float)dim_x / (float)dim_y;
+
+    const float max_dist = 0.5f * length(axis_scale);
+    sloped_inv_max_dist = desired_slope * 1.f/max_dist;
+
+    // Range needs to be between 1.3 to 0.6. When scale is zero then range is
+    // 1.3 which means no vignette at all because the luminousity difference is
+    // less than 1/256.  Expect input scale to be between 0.0 and 1.0.
+    const float neg_range = 0.7f*sqrt(desired_scale) - 1.3f;
+    sloped_neg_range = exp(neg_range * desired_slope);
+
+    shade = desired_shade;
+    opp_shade = 1.f - desired_shade;
+}
+
+void root(const uchar4 *in, uchar4 *out, uint32_t x, uint32_t y) {
+    // Convert x and y to floating point coordinates with center as origin
+    const float4 fin = convert_float4(*in);
+    const float2 inCoord = {(float)x, (float)y};
+    const float2 coord = mad(inCoord, inv_dimensions, neg_center);
+    const float sloped_dist_ratio = length(axis_scale * coord)  * sloped_inv_max_dist;
+    const float lumen = opp_shade + shade / ( 1.0f + sloped_neg_range * exp(sloped_dist_ratio) );
+    float4 fout;
+    fout.rgb = fin.rgb * lumen;
+    fout.w = fin.w;
+    *out = convert_uchar4(fout);
+}
+
diff --git a/include/diskusage/dirsize.h b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/vignette_full.rs
similarity index 60%
copy from include/diskusage/dirsize.h
copy to tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/vignette_full.rs
index 34236c0..c5b08a9 100644
--- a/include/diskusage/dirsize.h
+++ b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/vignette_full.rs
@@ -1,12 +1,11 @@
 /*
- *
- * Copyright (C) 2010 The Android Open Source Project
+ * 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
+ *      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,
@@ -15,16 +14,8 @@
  * limitations under the License.
  */
 
-#ifndef __LIBDISKUSAGE_DIRSIZE_H
-#define __LIBDISKUSAGE_DIRSIZE_H
+#pragma version(1)
+#pragma rs java_package_name(com.android.rs.imagejb)
 
-#include <stdint.h>
+#include "vignette.rsh"
 
-__BEGIN_DECLS
-
-int64_t stat_size(struct stat *s);
-int64_t calculate_dir_size(int dfd);
-
-__END_DECLS
-
-#endif /* __LIBDISKUSAGE_DIRSIZE_H */
diff --git a/include/diskusage/dirsize.h b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/vignette_relaxed.rs
similarity index 60%
copy from include/diskusage/dirsize.h
copy to tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/vignette_relaxed.rs
index 34236c0..339b747 100644
--- a/include/diskusage/dirsize.h
+++ b/tests/RenderScriptTests/ImageProcessing_jb/src/com/android/rs/image/vignette_relaxed.rs
@@ -1,12 +1,11 @@
 /*
- *
- * Copyright (C) 2010 The Android Open Source Project
+ * 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
+ *      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,
@@ -15,16 +14,9 @@
  * limitations under the License.
  */
 
-#ifndef __LIBDISKUSAGE_DIRSIZE_H
-#define __LIBDISKUSAGE_DIRSIZE_H
+#pragma version(1)
+#pragma rs java_package_name(com.android.rs.imagejb)
+#pragma rs_fp_relaxed
 
-#include <stdint.h>
+#include "vignette.rsh"
 
-__BEGIN_DECLS
-
-int64_t stat_size(struct stat *s);
-int64_t calculate_dir_size(int dfd);
-
-__END_DECLS
-
-#endif /* __LIBDISKUSAGE_DIRSIZE_H */
diff --git a/cmds/ip-up-vpn/Android.mk b/tests/RenderScriptTests/LatencyBenchmark/Android.mk
similarity index 69%
rename from cmds/ip-up-vpn/Android.mk
rename to tests/RenderScriptTests/LatencyBenchmark/Android.mk
index de81889..ef2164d 100644
--- a/cmds/ip-up-vpn/Android.mk
+++ b/tests/RenderScriptTests/LatencyBenchmark/Android.mk
@@ -1,5 +1,5 @@
 #
-# Copyright (C) 2011 The Android Open Source Project
+# 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.
@@ -17,10 +17,11 @@
 LOCAL_PATH := $(call my-dir)
 include $(CLEAR_VARS)
 
-LOCAL_SRC_FILES := ip-up-vpn.c
-LOCAL_SHARED_LIBRARIES := libcutils
-LOCAL_MODULE := ip-up-vpn
-LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/ppp
-LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_TAGS := tests
 
-include $(BUILD_EXECUTABLE)
+LOCAL_SRC_FILES := $(call all-java-files-under, src) \
+                   $(call all-renderscript-files-under, src)
+
+LOCAL_PACKAGE_NAME := RsLatencyBenchmark
+
+include $(BUILD_PACKAGE)
diff --git a/tests/RenderScriptTests/LatencyBenchmark/AndroidManifest.xml b/tests/RenderScriptTests/LatencyBenchmark/AndroidManifest.xml
new file mode 100644
index 0000000..923bb88
--- /dev/null
+++ b/tests/RenderScriptTests/LatencyBenchmark/AndroidManifest.xml
@@ -0,0 +1,30 @@
+<?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.example.android.rs.latencybench">
+
+    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+    <uses-sdk android:minSdkVersion="17" />
+    <application android:label="_RS_Latency_Bench">
+        <activity android:name="LatencyBench">
+            <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/LatencyBenchmark/res/layout/main.xml b/tests/RenderScriptTests/LatencyBenchmark/res/layout/main.xml
new file mode 100644
index 0000000..9e9dab8
--- /dev/null
+++ b/tests/RenderScriptTests/LatencyBenchmark/res/layout/main.xml
@@ -0,0 +1,31 @@
+<?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:layout_width="match_parent"
+        android:layout_height="match_parent">
+
+    <ImageView
+        android:id="@+id/displayin"
+        android:layout_width="320dip"
+        android:layout_height="266dip" />
+
+    <ImageView
+        android:id="@+id/displayout"
+        android:layout_width="320dip"
+        android:layout_height="266dip" />
+
+</LinearLayout>
diff --git a/tests/RenderScriptTests/LatencyBenchmark/src/com/example/android/rs/computebench/Benchmark.java b/tests/RenderScriptTests/LatencyBenchmark/src/com/example/android/rs/computebench/Benchmark.java
new file mode 100644
index 0000000..ee14fb9
--- /dev/null
+++ b/tests/RenderScriptTests/LatencyBenchmark/src/com/example/android/rs/computebench/Benchmark.java
@@ -0,0 +1,63 @@
+/*
+ * 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.example.android.rs.latencybench;
+import android.content.Context;
+import android.content.res.Resources;
+import android.renderscript.*;
+
+public class Benchmark implements Runnable {
+    private final RenderScript mRS;
+    private ScriptC_compute_benchmark mScript;
+    private Allocation ain;
+    private Allocation aout;
+
+    public Benchmark(RenderScript rs, Resources res) {
+        mRS = rs;
+        mScript = new ScriptC_compute_benchmark(mRS, res, R.raw.compute_benchmark);
+        ain = Allocation.createSized(rs, Element.U32(mRS), 10000);
+        aout = Allocation.createSized(rs, Element.U32(mRS), 10000);
+    }
+
+    public void run() {
+        int[] temp;
+        temp = new int[1];
+
+        long t = java.lang.System.currentTimeMillis();
+
+        for (int i = 0; i < 1000000; i++)
+            mScript.forEach_root(ain, aout);
+        aout.copy1DRangeFrom(0, 1, temp);
+
+        t = java.lang.System.currentTimeMillis() - t;
+        android.util.Log.v("LatencyBench", "Iterated Java forEach took " + t + " ms");
+
+        mScript.set_empty_kern(mScript);
+        mScript.set_in(ain);
+        mScript.set_out(aout);
+
+        t = java.lang.System.currentTimeMillis();
+        mScript.invoke_emptyKernelLauncher();
+        aout.copy1DRangeFrom(0, 1, temp);
+
+        t = java.lang.System.currentTimeMillis() - t;
+        android.util.Log.v("LatencyBench", "Invoked forEach took " + t + " ms");
+
+
+
+    }
+
+}
diff --git a/tests/RenderScriptTests/LatencyBenchmark/src/com/example/android/rs/computebench/LatencyBench.java b/tests/RenderScriptTests/LatencyBenchmark/src/com/example/android/rs/computebench/LatencyBench.java
new file mode 100644
index 0000000..fdce9a7
--- /dev/null
+++ b/tests/RenderScriptTests/LatencyBenchmark/src/com/example/android/rs/computebench/LatencyBench.java
@@ -0,0 +1,37 @@
+/*
+ * 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.example.android.rs.latencybench;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.renderscript.RenderScript;
+
+public class LatencyBench extends Activity {
+    private RenderScript mRS;
+    private Benchmark mBenchmark;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.main);
+
+        mRS = RenderScript.create(this);
+
+        mBenchmark = new Benchmark(mRS, getResources());
+        mBenchmark.run();
+    }
+}
diff --git a/tests/RenderScriptTests/LatencyBenchmark/src/com/example/android/rs/computebench/compute_benchmark.rs b/tests/RenderScriptTests/LatencyBenchmark/src/com/example/android/rs/computebench/compute_benchmark.rs
new file mode 100644
index 0000000..c6d1ea9
--- /dev/null
+++ b/tests/RenderScriptTests/LatencyBenchmark/src/com/example/android/rs/computebench/compute_benchmark.rs
@@ -0,0 +1,29 @@
+// 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.example.android.rs.latencybench)
+
+rs_script empty_kern;
+rs_allocation in, out;
+int iters = 1000000;
+
+void root(const uint32_t *ain, uint32_t *aout) {
+
+}
+
+void emptyKernelLauncher() {
+    for (int i = 0; i < iters; i++)
+        rsForEach(empty_kern, in, out);
+}
diff --git a/tools/aidl/aidl.cpp b/tools/aidl/aidl.cpp
index 0728246..071a8d7 100644
--- a/tools/aidl/aidl.cpp
+++ b/tools/aidl/aidl.cpp
@@ -23,6 +23,12 @@
 #  define O_BINARY  0
 #endif
 
+// The following are gotten as the offset from the allowable id's between
+// android.os.IBinder.FIRST_CALL_TRANSACTION=1 and
+// android.os.IBinder.LAST_CALL_TRANSACTION=16777215
+#define MIN_USER_SET_METHOD_ID                0
+#define MAX_USER_SET_METHOD_ID                16777214
+
 using namespace std;
 
 static void
@@ -847,6 +853,72 @@
     return 0;
 }
 
+static int
+check_and_assign_method_ids(const char * filename, interface_item_type* first_item)
+{
+    // Check whether there are any methods with manually assigned id's and any that are not.
+    // Either all method id's must be manually assigned or all of them must not.
+    // Also, check for duplicates of user set id's and that the id's are within the proper bounds.
+    set<int> usedIds;
+    interface_item_type* item = first_item;
+    bool hasUnassignedIds = false;
+    bool hasAssignedIds = false;
+    while (item != NULL) {
+        if (item->item_type == METHOD_TYPE) {
+            method_type* method_item = (method_type*)item;
+            if (method_item->hasId) {
+                hasAssignedIds = true;
+                method_item->assigned_id = atoi(method_item->id.data);
+                // Ensure that the user set id is not duplicated.
+                if (usedIds.find(method_item->assigned_id) != usedIds.end()) {
+                    // We found a duplicate id, so throw an error.
+                    fprintf(stderr,
+                            "%s:%d Found duplicate method id (%d) for method: %s\n",
+                            filename, method_item->id.lineno,
+                            method_item->assigned_id, method_item->name.data);
+                    return 1;
+                }
+                // Ensure that the user set id is within the appropriate limits
+                if (method_item->assigned_id < MIN_USER_SET_METHOD_ID ||
+                        method_item->assigned_id > MAX_USER_SET_METHOD_ID) {
+                    fprintf(stderr, "%s:%d Found out of bounds id (%d) for method: %s\n",
+                            filename, method_item->id.lineno,
+                            method_item->assigned_id, method_item->name.data);
+                    fprintf(stderr, "    Value for id must be between %d and %d inclusive.\n",
+                            MIN_USER_SET_METHOD_ID, MAX_USER_SET_METHOD_ID);
+                    return 1;
+                }
+                usedIds.insert(method_item->assigned_id);
+            } else {
+                hasUnassignedIds = true;
+            }
+            if (hasAssignedIds && hasUnassignedIds) {
+                fprintf(stderr,
+                        "%s: You must either assign id's to all methods or to none of them.\n",
+                        filename);
+                return 1;
+            }
+        }
+        item = item->next;
+    }
+
+    // In the case that all methods have unassigned id's, set a unique id for them.
+    if (hasUnassignedIds) {
+        int newId = 0;
+        item = first_item;
+        while (item != NULL) {
+            if (item->item_type == METHOD_TYPE) {
+                method_type* method_item = (method_type*)item;
+                method_item->assigned_id = newId++;
+            }
+            item = item->next;
+        }
+    }
+
+    // success
+    return 0;
+}
+
 // ==========================================================
 static int
 compile_aidl(Options& options)
@@ -937,6 +1009,12 @@
     bool onlyParcelable = false;
     err |= exactly_one_interface(options.inputFileName.c_str(), mainDoc, options, &onlyParcelable);
 
+    // If this includes an interface definition, then assign method ids and validate.
+    if (!onlyParcelable) {
+        err |= check_and_assign_method_ids(options.inputFileName.c_str(),
+                ((interface_type*)mainDoc)->interface_items);
+    }
+
     // after this, there shouldn't be any more errors because of the
     // input.
     if (err != 0 || mainDoc == NULL) {
diff --git a/tools/aidl/aidl_language.h b/tools/aidl/aidl_language.h
index f203dbb0..de1370c 100644
--- a/tools/aidl/aidl_language.h
+++ b/tools/aidl/aidl_language.h
@@ -57,9 +57,13 @@
     buffer_type open_paren_token;
     arg_type* args;
     buffer_type close_paren_token;
+    bool hasId;
+    buffer_type equals_token;
+    buffer_type id;
     // XXX missing comments/copy text here
     buffer_type semicolon_token;
     buffer_type* comments_token; // points into this structure, DO NOT DELETE
+    int assigned_id;
 } method_type;
 
 enum {
diff --git a/tools/aidl/aidl_language_l.l b/tools/aidl/aidl_language_l.l
index 7c5290c..3d33e7a 100644
--- a/tools/aidl/aidl_language_l.l
+++ b/tools/aidl/aidl_language_l.l
@@ -36,6 +36,7 @@
 identifier  [_a-zA-Z][_a-zA-Z0-9\.]*
 whitespace  ([ \t\n\r]+)
 brackets    \[{whitespace}?\]
+idvalue     (0|[1-9][0-9]*)
 
 %%
 
@@ -77,6 +78,7 @@
 \(              { SET_BUFFER('('); return '('; }
 \)              { SET_BUFFER(')'); return ')'; }
 ,               { SET_BUFFER(','); return ','; }
+=               { SET_BUFFER('='); return '='; }
 
     /* keywords */
 parcelable      { SET_BUFFER(PARCELABLE); return PARCELABLE; }
@@ -89,7 +91,7 @@
 oneway          { SET_BUFFER(ONEWAY); return ONEWAY; }
 
 {brackets}+     { SET_BUFFER(ARRAY); return ARRAY; }
-
+{idvalue}       { SET_BUFFER(IDVALUE); return IDVALUE; }
 {identifier}                                        { SET_BUFFER(IDENTIFIER); return IDENTIFIER; }
 {identifier}\<{whitespace}*{identifier}({whitespace}*,{whitespace}*{identifier})*{whitespace}*\>    {
                                                       SET_BUFFER(GENERIC); return GENERIC; }
diff --git a/tools/aidl/aidl_language_y.y b/tools/aidl/aidl_language_y.y
index cc04d15..9b40d28 100644
--- a/tools/aidl/aidl_language_y.y
+++ b/tools/aidl/aidl_language_y.y
@@ -15,6 +15,7 @@
 %token IMPORT
 %token PACKAGE
 %token IDENTIFIER
+%token IDVALUE
 %token GENERIC
 %token ARRAY
 %token PARCELABLE
@@ -211,13 +212,16 @@
                                                         method_type *method = (method_type*)malloc(sizeof(method_type));
                                                         method->interface_item.item_type = METHOD_TYPE;
                                                         method->interface_item.next = NULL;
-                                                        method->type = $1.type;
                                                         method->oneway = false;
+                                                        method->type = $1.type;
                                                         memset(&method->oneway_token, 0, sizeof(buffer_type));
                                                         method->name = $2.buffer;
                                                         method->open_paren_token = $3.buffer;
                                                         method->args = $4.arg;
                                                         method->close_paren_token = $5.buffer;
+                                                        method->hasId = false;
+                                                        memset(&method->equals_token, 0, sizeof(buffer_type));
+                                                        memset(&method->id, 0, sizeof(buffer_type));
                                                         method->semicolon_token = $6.buffer;
                                                         method->comments_token = &method->type.type;
                                                         $$.method = method;
@@ -233,10 +237,49 @@
                                                         method->open_paren_token = $4.buffer;
                                                         method->args = $5.arg;
                                                         method->close_paren_token = $6.buffer;
+                                                        method->hasId = false;
+                                                        memset(&method->equals_token, 0, sizeof(buffer_type));
+                                                        memset(&method->id, 0, sizeof(buffer_type));
                                                         method->semicolon_token = $7.buffer;
                                                         method->comments_token = &method->oneway_token;
                                                         $$.method = method;
                                                     }
+    |    type IDENTIFIER '(' arg_list ')' '=' IDVALUE ';'  {
+                                                        method_type *method = (method_type*)malloc(sizeof(method_type));
+                                                        method->interface_item.item_type = METHOD_TYPE;
+                                                        method->interface_item.next = NULL;
+                                                        method->oneway = false;
+                                                        memset(&method->oneway_token, 0, sizeof(buffer_type));
+                                                        method->type = $1.type;
+                                                        method->name = $2.buffer;
+                                                        method->open_paren_token = $3.buffer;
+                                                        method->args = $4.arg;
+                                                        method->close_paren_token = $5.buffer;
+                                                        method->hasId = true;
+                                                        method->equals_token = $6.buffer;
+                                                        method->id = $7.buffer;
+                                                        method->semicolon_token = $8.buffer;
+                                                        method->comments_token = &method->type.type;
+                                                        $$.method = method;
+                                                    }
+    |   ONEWAY type IDENTIFIER '(' arg_list ')' '=' IDVALUE ';'  {
+                                                        method_type *method = (method_type*)malloc(sizeof(method_type));
+                                                        method->interface_item.item_type = METHOD_TYPE;
+                                                        method->interface_item.next = NULL;
+                                                        method->oneway = true;
+                                                        method->oneway_token = $1.buffer;
+                                                        method->type = $2.type;
+                                                        method->name = $3.buffer;
+                                                        method->open_paren_token = $4.buffer;
+                                                        method->args = $5.arg;
+                                                        method->close_paren_token = $6.buffer;
+                                                        method->hasId = true;
+                                                        method->equals_token = $7.buffer;
+                                                        method->id = $8.buffer;
+                                                        method->semicolon_token = $9.buffer;
+                                                        method->comments_token = &method->oneway_token;
+                                                        $$.method = method;
+                                                    }
     ;
 
 arg_list:
diff --git a/tools/aidl/generate_java_binder.cpp b/tools/aidl/generate_java_binder.cpp
index f80a388..f291ceb 100644
--- a/tools/aidl/generate_java_binder.cpp
+++ b/tools/aidl/generate_java_binder.cpp
@@ -260,7 +260,7 @@
     string transactCodeName = "TRANSACTION_";
     transactCodeName += method->name.data;
 
-    char transactCodeValue[50];
+    char transactCodeValue[60];
     sprintf(transactCodeValue, "(android.os.IBinder.FIRST_CALL_TRANSACTION + %d)", index);
 
     Field* transactCode = new Field(STATIC | FINAL,
@@ -548,7 +548,8 @@
     interface_item_type* item = iface->interface_items;
     while (item != NULL) {
         if (item->item_type == METHOD_TYPE) {
-            generate_method((method_type*)item, interface, stub, proxy, index);
+            method_type * method_item = (method_type*) item;
+            generate_method(method_item, interface, stub, proxy, method_item->assigned_id);
         }
         item = item->next;
         index++;
diff --git a/voip/jni/rtp/Android.mk b/voip/jni/rtp/Android.mk
index 82d7912..b265cdd 100644
--- a/voip/jni/rtp/Android.mk
+++ b/voip/jni/rtp/Android.mk
@@ -37,7 +37,6 @@
 	libcutils \
 	libutils \
 	libmedia \
-	libmedia_native \
 	libstagefright_amrnb_common
 
 LOCAL_STATIC_LIBRARIES := libgsm libstagefright_amrnbdec libstagefright_amrnbenc
diff --git a/voip/jni/rtp/AudioGroup.cpp b/voip/jni/rtp/AudioGroup.cpp
index 1579e6a..2f0829e 100644
--- a/voip/jni/rtp/AudioGroup.cpp
+++ b/voip/jni/rtp/AudioGroup.cpp
@@ -785,8 +785,8 @@
     int deviceSocket = mGroup->mDeviceSocket;
 
     // Find out the frame count for AudioTrack and AudioRecord.
-    int output = 0;
-    int input = 0;
+    size_t output = 0;
+    size_t input = 0;
     if (AudioTrack::getMinFrameCount(&output, AUDIO_STREAM_VOICE_CALL,
         sampleRate) != NO_ERROR || output <= 0 ||
         AudioRecord::getMinFrameCount(&input, sampleRate,
diff --git a/wifi/java/android/net/wifi/WifiConfigStore.java b/wifi/java/android/net/wifi/WifiConfigStore.java
index 84506b6..c3278a9 100644
--- a/wifi/java/android/net/wifi/WifiConfigStore.java
+++ b/wifi/java/android/net/wifi/WifiConfigStore.java
@@ -18,7 +18,6 @@
 
 import android.content.Context;
 import android.content.Intent;
-import android.net.DhcpInfoInternal;
 import android.net.LinkAddress;
 import android.net.LinkProperties;
 import android.net.NetworkUtils;
@@ -502,45 +501,12 @@
     }
 
     /**
-     * get IP configuration for a given network id
-     * TODO: We cannot handle IPv6 addresses for configuration
-     *       right now until NetworkUtils is fixed. When we do
-     *       that, we should remove handling DhcpInfo and move
-     *       to using LinkProperties
-     * @return DhcpInfoInternal for the given network id
-     */
-    DhcpInfoInternal getIpConfiguration(int netId) {
-        DhcpInfoInternal dhcpInfoInternal = new DhcpInfoInternal();
-        LinkProperties linkProperties = getLinkProperties(netId);
-
-        if (linkProperties != null) {
-            Iterator<LinkAddress> iter = linkProperties.getLinkAddresses().iterator();
-            if (iter.hasNext()) {
-                LinkAddress linkAddress = iter.next();
-                dhcpInfoInternal.ipAddress = linkAddress.getAddress().getHostAddress();
-                for (RouteInfo route : linkProperties.getRoutes()) {
-                    dhcpInfoInternal.addRoute(route);
-                }
-                dhcpInfoInternal.prefixLength = linkAddress.getNetworkPrefixLength();
-                Iterator<InetAddress> dnsIterator = linkProperties.getDnses().iterator();
-                dhcpInfoInternal.dns1 = dnsIterator.next().getHostAddress();
-                if (dnsIterator.hasNext()) {
-                    dhcpInfoInternal.dns2 = dnsIterator.next().getHostAddress();
-                }
-            }
-        }
-        return dhcpInfoInternal;
-    }
-
-    /**
      * set IP configuration for a given network id
      */
-    void setIpConfiguration(int netId, DhcpInfoInternal dhcpInfo) {
-        LinkProperties linkProperties = dhcpInfo.makeLinkProperties();
-
+    void setLinkProperties(int netId, LinkProperties linkProperties) {
         WifiConfiguration config = mConfiguredNetworks.get(netId);
         if (config != null) {
-            // add old proxy details
+            // add old proxy details - TODO - is this still needed?
             if(config.linkProperties != null) {
                 linkProperties.setHttpProxy(config.linkProperties.getHttpProxy());
             }
@@ -552,7 +518,7 @@
      * clear IP configuration for a given network id
      * @param network id
      */
-    void clearIpConfiguration(int netId) {
+    void clearLinkProperties(int netId) {
         WifiConfiguration config = mConfiguredNetworks.get(netId);
         if (config != null && config.linkProperties != null) {
             // Clear everything except proxy
diff --git a/wifi/java/android/net/wifi/WifiInfo.java b/wifi/java/android/net/wifi/WifiInfo.java
index 05db571..502d1ab 100644
--- a/wifi/java/android/net/wifi/WifiInfo.java
+++ b/wifi/java/android/net/wifi/WifiInfo.java
@@ -23,7 +23,7 @@
 import android.text.TextUtils;
 
 import java.net.InetAddress;
-import java.net.Inet6Address;
+import java.net.Inet4Address;
 import java.net.UnknownHostException;
 import java.util.EnumMap;
 
@@ -231,8 +231,11 @@
     }
 
     public int getIpAddress() {
-        if (mIpAddress == null || mIpAddress instanceof Inet6Address) return 0;
-        return NetworkUtils.inetAddressToInt(mIpAddress);
+        int result = 0;
+        if (mIpAddress instanceof Inet4Address) {
+            result = NetworkUtils.inetAddressToInt((Inet4Address)mIpAddress);
+        }
+        return result;
     }
 
     /**
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 0e29882..4861759 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -862,6 +862,7 @@
      * Return the DHCP-assigned addresses from the last successful DHCP request,
      * if any.
      * @return the DHCP information
+     * @deprecated - use ConnectivityManager.getLinkProperties instead.  TODO - remove 11/2013
      */
     public DhcpInfo getDhcpInfo() {
         try {
@@ -871,7 +872,6 @@
         }
     }
 
-
     /**
      * Enable or disable Wi-Fi.
      * @param enabled {@code true} to enable, {@code false} to disable.
diff --git a/wifi/java/android/net/wifi/WifiStateMachine.java b/wifi/java/android/net/wifi/WifiStateMachine.java
index dafa8e8..44b2eac 100644
--- a/wifi/java/android/net/wifi/WifiStateMachine.java
+++ b/wifi/java/android/net/wifi/WifiStateMachine.java
@@ -43,8 +43,7 @@
 import android.content.pm.PackageManager;
 import android.database.ContentObserver;
 import android.net.ConnectivityManager;
-import android.net.DhcpInfo;
-import android.net.DhcpInfoInternal;
+import android.net.DhcpResults;
 import android.net.DhcpStateMachine;
 import android.net.InterfaceConfiguration;
 import android.net.LinkAddress;
@@ -87,6 +86,7 @@
 import java.util.List;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.Iterator;
 import java.util.regex.Pattern;
 
 /**
@@ -196,7 +196,8 @@
 
     private Context mContext;
 
-    private DhcpInfoInternal mDhcpInfoInternal;
+    private final Object mDhcpResultsLock = new Object();
+    private DhcpResults mDhcpResults;
     private WifiInfo mWifiInfo;
     private NetworkInfo mNetworkInfo;
     private SupplicantStateTracker mSupplicantStateTracker;
@@ -585,7 +586,6 @@
         mWifiNative = new WifiNative(mInterfaceName);
         mWifiConfigStore = new WifiConfigStore(context, mWifiNative);
         mWifiMonitor = new WifiMonitor(this, mWifiNative);
-        mDhcpInfoInternal = new DhcpInfoInternal();
         mWifiInfo = new WifiInfo();
         mSupplicantStateTracker = new SupplicantStateTracker(context, this, mWifiConfigStore,
                 getHandler());
@@ -858,9 +858,9 @@
         return mWifiInfo;
     }
 
-    public DhcpInfo syncGetDhcpInfo() {
-        synchronized (mDhcpInfoInternal) {
-            return mDhcpInfoInternal.makeDhcpInfo();
+    public DhcpResults syncGetDhcpResults() {
+        synchronized (mDhcpResultsLock) {
+            return new DhcpResults(mDhcpResults);
         }
     }
 
@@ -1169,7 +1169,7 @@
         sb.append("current HSM state: ").append(getCurrentState().getName()).append(LS);
         sb.append("mLinkProperties ").append(mLinkProperties).append(LS);
         sb.append("mWifiInfo ").append(mWifiInfo).append(LS);
-        sb.append("mDhcpInfoInternal ").append(mDhcpInfoInternal).append(LS);
+        sb.append("mDhcpResults ").append(mDhcpResults).append(LS);
         sb.append("mNetworkInfo ").append(mNetworkInfo).append(LS);
         sb.append("mLastSignalLevel ").append(mLastSignalLevel).append(LS);
         sb.append("mLastBssid ").append(mLastBssid).append(LS);
@@ -1607,16 +1607,15 @@
         if (mWifiConfigStore.isUsingStaticIp(mLastNetworkId)) {
             mLinkProperties = mWifiConfigStore.getLinkProperties(mLastNetworkId);
         } else {
-            synchronized (mDhcpInfoInternal) {
-                mLinkProperties = mDhcpInfoInternal.makeLinkProperties();
+            synchronized (mDhcpResultsLock) {
+                if ((mDhcpResults != null) && (mDhcpResults.linkProperties != null)) {
+                    mLinkProperties = mDhcpResults.linkProperties;
+                }
             }
             mLinkProperties.setHttpProxy(mWifiConfigStore.getProxyProperties(mLastNetworkId));
         }
         mLinkProperties.setInterfaceName(mInterfaceName);
-        if (DBG) {
-            log("netId=" + mLastNetworkId  + " Link configured: " +
-                    mLinkProperties.toString());
-        }
+        if (DBG) log("netId=" + mLastNetworkId  + " Link configured: " + mLinkProperties);
     }
 
     private int getMaxDhcpRetries() {
@@ -1751,9 +1750,10 @@
 
         /* Clear network properties */
         mLinkProperties.clear();
+
         /* Clear IP settings if the network used DHCP */
         if (!mWifiConfigStore.isUsingStaticIp(mLastNetworkId)) {
-            mWifiConfigStore.clearIpConfiguration(mLastNetworkId);
+            mWifiConfigStore.clearLinkProperties(mLastNetworkId);
         }
 
         mLastBssid= null;
@@ -1802,21 +1802,27 @@
                 mWifiNative.BLUETOOTH_COEXISTENCE_MODE_SENSE);
     }
 
-    private void handleSuccessfulIpConfiguration(DhcpInfoInternal dhcpInfoInternal) {
-        synchronized (mDhcpInfoInternal) {
-            mDhcpInfoInternal = dhcpInfoInternal;
-        }
+    private void handleSuccessfulIpConfiguration(DhcpResults dhcpResults) {
         mLastSignalLevel = -1; // force update of signal strength
         mReconnectCount = 0; //Reset IP failure tracking
-        mWifiConfigStore.setIpConfiguration(mLastNetworkId, dhcpInfoInternal);
-        InetAddress addr = NetworkUtils.numericToInetAddress(dhcpInfoInternal.ipAddress);
+        if (dhcpResults.serverAddress == null) {
+            dhcpResults = null;
+        }
+        synchronized (mDhcpResultsLock) {
+            mDhcpResults = dhcpResults;
+        }
+        LinkProperties linkProperties = dhcpResults.linkProperties;
+        mWifiConfigStore.setLinkProperties(mLastNetworkId, linkProperties);
+        InetAddress addr = null;
+        Iterator<InetAddress> addrs = linkProperties.getAddresses().iterator();
+        if (addrs.hasNext()) {
+            addr = addrs.next();
+        }
         mWifiInfo.setInetAddress(addr);
-        mWifiInfo.setMeteredHint(dhcpInfoInternal.hasMeteredHint());
+        mWifiInfo.setMeteredHint(dhcpResults.hasMeteredHint());
         if (getNetworkDetailedState() == DetailedState.CONNECTED) {
             //DHCP renewal in connected state
-            LinkProperties linkProperties = dhcpInfoInternal.makeLinkProperties();
             linkProperties.setHttpProxy(mWifiConfigStore.getProxyProperties(mLastNetworkId));
-            linkProperties.setInterfaceName(mInterfaceName);
             if (!linkProperties.equals(mLinkProperties)) {
                 if (DBG) {
                     log("Link configuration changed for netId: " + mLastNetworkId
@@ -3247,7 +3253,7 @@
                   handlePostDhcpSetup();
                   if (message.arg1 == DhcpStateMachine.DHCP_SUCCESS) {
                       if (DBG) log("DHCP successful");
-                      handleSuccessfulIpConfiguration((DhcpInfoInternal) message.obj);
+                      handleSuccessfulIpConfiguration((DhcpResults) message.obj);
                       transitionTo(mVerifyingLinkState);
                   } else if (message.arg1 == DhcpStateMachine.DHCP_FAILURE) {
                       if (DBG) log("DHCP failed");
@@ -3375,21 +3381,29 @@
                 mDhcpStateMachine.registerForPreDhcpNotification();
                 mDhcpStateMachine.sendMessage(DhcpStateMachine.CMD_START_DHCP);
             } else {
-                DhcpInfoInternal dhcpInfoInternal = mWifiConfigStore.getIpConfiguration(
-                        mLastNetworkId);
+                DhcpResults dhcpResults = new DhcpResults(
+                        mWifiConfigStore.getLinkProperties(mLastNetworkId));
+                dhcpResults.linkProperties.setInterfaceName(mInterfaceName);
                 InterfaceConfiguration ifcg = new InterfaceConfiguration();
-                ifcg.setLinkAddress(dhcpInfoInternal.makeLinkAddress());
-                ifcg.setInterfaceUp();
-                try {
-                    mNwService.setInterfaceConfig(mInterfaceName, ifcg);
-                    if (DBG) log("Static IP configuration succeeded");
-                    sendMessage(CMD_STATIC_IP_SUCCESS, dhcpInfoInternal);
-                } catch (RemoteException re) {
-                    loge("Static IP configuration failed: " + re);
+                Iterator<LinkAddress> addrs =
+                        dhcpResults.linkProperties.getLinkAddresses().iterator();
+                if (!addrs.hasNext()) {
+                    loge("Static IP lacks address");
                     sendMessage(CMD_STATIC_IP_FAILURE);
-                } catch (IllegalStateException e) {
-                    loge("Static IP configuration failed: " + e);
-                    sendMessage(CMD_STATIC_IP_FAILURE);
+                } else {
+                    ifcg.setLinkAddress(addrs.next());
+                    ifcg.setInterfaceUp();
+                    try {
+                        mNwService.setInterfaceConfig(mInterfaceName, ifcg);
+                        if (DBG) log("Static IP configuration succeeded");
+                        sendMessage(CMD_STATIC_IP_SUCCESS, dhcpResults);
+                    } catch (RemoteException re) {
+                        loge("Static IP configuration failed: " + re);
+                        sendMessage(CMD_STATIC_IP_FAILURE);
+                    } catch (IllegalStateException e) {
+                        loge("Static IP configuration failed: " + e);
+                        sendMessage(CMD_STATIC_IP_FAILURE);
+                    }
                 }
             }
         }
@@ -3398,7 +3412,7 @@
           if (DBG) log(getName() + message.toString() + "\n");
           switch(message.what) {
             case CMD_STATIC_IP_SUCCESS:
-                  handleSuccessfulIpConfiguration((DhcpInfoInternal) message.obj);
+                  handleSuccessfulIpConfiguration((DhcpResults) message.obj);
                   transitionTo(mVerifyingLinkState);
                   break;
               case CMD_STATIC_IP_FAILURE:
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pService.java b/wifi/java/android/net/wifi/p2p/WifiP2pService.java
index 4a4320c..fdb21ad 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pService.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pService.java
@@ -34,7 +34,7 @@
 import android.content.res.Resources;
 import android.net.IConnectivityManager;
 import android.net.ConnectivityManager;
-import android.net.DhcpInfoInternal;
+import android.net.DhcpResults;
 import android.net.DhcpStateMachine;
 import android.net.InterfaceConfiguration;
 import android.net.LinkAddress;
@@ -86,6 +86,7 @@
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
+import java.net.InetAddress;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashMap;
@@ -1479,7 +1480,7 @@
 
             //DHCP server has already been started if I am a group owner
             if (mGroup.isGroupOwner()) {
-                setWifiP2pInfoOnGroupFormation(SERVER_ADDRESS);
+                setWifiP2pInfoOnGroupFormation(NetworkUtils.numericToInetAddress(SERVER_ADDRESS));
             }
 
             // In case of a negotiation group, connection changed is sent
@@ -1543,11 +1544,11 @@
                     }
                     break;
                 case DhcpStateMachine.CMD_POST_DHCP_ACTION:
-                    DhcpInfoInternal dhcpInfo = (DhcpInfoInternal) message.obj;
+                    DhcpResults dhcpResults = (DhcpResults) message.obj;
                     if (message.arg1 == DhcpStateMachine.DHCP_SUCCESS &&
-                            dhcpInfo != null) {
-                        if (DBG) logd("DhcpInfo: " + dhcpInfo);
-                        setWifiP2pInfoOnGroupFormation(dhcpInfo.serverAddress);
+                            dhcpResults != null) {
+                        if (DBG) logd("DhcpResults: " + dhcpResults);
+                        setWifiP2pInfoOnGroupFormation(dhcpResults.serverAddress);
                         sendP2pConnectionChangedBroadcast();
                         //Turn on power save on client
                         mWifiNative.setP2pPowerSave(mGroup.getInterface(), true);
@@ -2221,10 +2222,10 @@
         return true;
     }
 
-    private void setWifiP2pInfoOnGroupFormation(String serverAddress) {
+    private void setWifiP2pInfoOnGroupFormation(InetAddress serverInetAddress) {
         mWifiP2pInfo.groupFormed = true;
         mWifiP2pInfo.isGroupOwner = mGroup.isGroupOwner();
-        mWifiP2pInfo.groupOwnerAddress = NetworkUtils.numericToInetAddress(serverAddress);
+        mWifiP2pInfo.groupOwnerAddress = serverInetAddress;
     }
 
     private void resetWifiP2pInfo() {