Merge "Add performAccessibilityAction to AccessibilityDelegate." into jb-dev
diff --git a/Android.mk b/Android.mk
index 678ae55..eef900a 100644
--- a/Android.mk
+++ b/Android.mk
@@ -94,7 +94,6 @@
 	core/java/android/bluetooth/IBluetoothHealthCallback.aidl \
 	core/java/android/bluetooth/IBluetoothPbap.aidl \
 	core/java/android/bluetooth/IBluetoothStateChangeCallback.aidl \
-	core/java/android/content/ICancellationSignal.aidl \
 	core/java/android/content/IClipboard.aidl \
 	core/java/android/content/IContentService.aidl \
 	core/java/android/content/IIntentReceiver.aidl \
@@ -126,6 +125,7 @@
 	core/java/android/nfc/INfcAdapter.aidl \
 	core/java/android/nfc/INfcAdapterExtras.aidl \
 	core/java/android/nfc/INfcTag.aidl \
+	core/java/android/os/ICancellationSignal.aidl \
 	core/java/android/os/IHardwareService.aidl \
 	core/java/android/os/IMessenger.aidl \
 	core/java/android/os/INetworkManagementService.aidl \
diff --git a/api/current.txt b/api/current.txt
index 695ba76..bb4430b 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -103,7 +103,6 @@
     field public static final java.lang.String SET_ALWAYS_FINISH = "android.permission.SET_ALWAYS_FINISH";
     field public static final java.lang.String SET_ANIMATION_SCALE = "android.permission.SET_ANIMATION_SCALE";
     field public static final java.lang.String SET_DEBUG_APP = "android.permission.SET_DEBUG_APP";
-    field public static final java.lang.String SET_KEYBOARD_LAYOUT = "android.permission.SET_KEYBOARD_LAYOUT";
     field public static final java.lang.String SET_ORIENTATION = "android.permission.SET_ORIENTATION";
     field public static final java.lang.String SET_POINTER_SPEED = "android.permission.SET_POINTER_SPEED";
     field public static final deprecated java.lang.String SET_PREFERRED_APPLICATIONS = "android.permission.SET_PREFERRED_APPLICATIONS";
@@ -4910,18 +4909,6 @@
     method public final void setResultExtras(android.os.Bundle);
   }
 
-  public final class CancellationSignal {
-    ctor public CancellationSignal();
-    method public void cancel();
-    method public boolean isCanceled();
-    method public void setOnCancelListener(android.content.CancellationSignal.OnCancelListener);
-    method public void throwIfCanceled();
-  }
-
-  public static abstract interface CancellationSignal.OnCancelListener {
-    method public abstract void onCancel();
-  }
-
   public class ClipData implements android.os.Parcelable {
     ctor public ClipData(java.lang.CharSequence, java.lang.String[], android.content.ClipData.Item);
     ctor public ClipData(android.content.ClipDescription, android.content.ClipData.Item);
@@ -5052,7 +5039,7 @@
     method public android.os.ParcelFileDescriptor openPipeHelper(android.net.Uri, java.lang.String, android.os.Bundle, T, android.content.ContentProvider.PipeDataWriter<T>) throws java.io.FileNotFoundException;
     method public android.content.res.AssetFileDescriptor openTypedAssetFile(android.net.Uri, java.lang.String, android.os.Bundle) throws java.io.FileNotFoundException;
     method public abstract android.database.Cursor query(android.net.Uri, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String);
-    method public android.database.Cursor query(android.net.Uri, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String, android.content.CancellationSignal);
+    method public android.database.Cursor query(android.net.Uri, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String, android.os.CancellationSignal);
     method protected final void setPathPermissions(android.content.pm.PathPermission[]);
     method protected final void setReadPermission(java.lang.String);
     method protected final void setWritePermission(java.lang.String);
@@ -5076,7 +5063,7 @@
     method public android.os.ParcelFileDescriptor openFile(android.net.Uri, java.lang.String) throws java.io.FileNotFoundException, android.os.RemoteException;
     method public final android.content.res.AssetFileDescriptor openTypedAssetFileDescriptor(android.net.Uri, java.lang.String, android.os.Bundle) throws java.io.FileNotFoundException, android.os.RemoteException;
     method public android.database.Cursor query(android.net.Uri, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String) throws android.os.RemoteException;
-    method public android.database.Cursor query(android.net.Uri, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String, android.content.CancellationSignal) throws android.os.RemoteException;
+    method public android.database.Cursor query(android.net.Uri, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String, android.os.CancellationSignal) throws android.os.RemoteException;
     method public boolean release();
     method public int update(android.net.Uri, android.content.ContentValues, java.lang.String, java.lang.String[]) throws android.os.RemoteException;
   }
@@ -5163,7 +5150,7 @@
     method public final java.io.OutputStream openOutputStream(android.net.Uri, java.lang.String) throws java.io.FileNotFoundException;
     method public final android.content.res.AssetFileDescriptor openTypedAssetFileDescriptor(android.net.Uri, java.lang.String, android.os.Bundle) throws java.io.FileNotFoundException;
     method public final android.database.Cursor query(android.net.Uri, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String);
-    method public final android.database.Cursor query(android.net.Uri, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String, android.content.CancellationSignal);
+    method public final android.database.Cursor query(android.net.Uri, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String, android.os.CancellationSignal);
     method public final void registerContentObserver(android.net.Uri, boolean, android.database.ContentObserver);
     method public static void removePeriodicSync(android.accounts.Account, java.lang.String, android.os.Bundle);
     method public static void removeStatusChangeListener(java.lang.Object);
@@ -6040,11 +6027,6 @@
     method public int getNumSuccessfulYieldPoints();
   }
 
-  public class OperationCanceledException extends java.lang.RuntimeException {
-    ctor public OperationCanceledException();
-    ctor public OperationCanceledException(java.lang.String);
-  }
-
   public class PeriodicSync implements android.os.Parcelable {
     ctor public PeriodicSync(android.accounts.Account, java.lang.String, android.os.Bundle, long);
     method public int describeContents();
@@ -7504,15 +7486,15 @@
     method public static android.database.sqlite.SQLiteDatabase openOrCreateDatabase(java.lang.String, android.database.sqlite.SQLiteDatabase.CursorFactory);
     method public static android.database.sqlite.SQLiteDatabase openOrCreateDatabase(java.lang.String, android.database.sqlite.SQLiteDatabase.CursorFactory, android.database.DatabaseErrorHandler);
     method public android.database.Cursor query(boolean, java.lang.String, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String, java.lang.String, java.lang.String, java.lang.String);
-    method public android.database.Cursor query(boolean, java.lang.String, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String, java.lang.String, java.lang.String, java.lang.String, android.content.CancellationSignal);
+    method public android.database.Cursor query(boolean, java.lang.String, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String, java.lang.String, java.lang.String, java.lang.String, android.os.CancellationSignal);
     method public android.database.Cursor query(java.lang.String, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String, java.lang.String, java.lang.String);
     method public android.database.Cursor query(java.lang.String, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String, java.lang.String, java.lang.String, java.lang.String);
     method public android.database.Cursor queryWithFactory(android.database.sqlite.SQLiteDatabase.CursorFactory, boolean, java.lang.String, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String, java.lang.String, java.lang.String, java.lang.String);
-    method public android.database.Cursor queryWithFactory(android.database.sqlite.SQLiteDatabase.CursorFactory, boolean, java.lang.String, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String, java.lang.String, java.lang.String, java.lang.String, android.content.CancellationSignal);
+    method public android.database.Cursor queryWithFactory(android.database.sqlite.SQLiteDatabase.CursorFactory, boolean, java.lang.String, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String, java.lang.String, java.lang.String, java.lang.String, android.os.CancellationSignal);
     method public android.database.Cursor rawQuery(java.lang.String, java.lang.String[]);
-    method public android.database.Cursor rawQuery(java.lang.String, java.lang.String[], android.content.CancellationSignal);
+    method public android.database.Cursor rawQuery(java.lang.String, java.lang.String[], android.os.CancellationSignal);
     method public android.database.Cursor rawQueryWithFactory(android.database.sqlite.SQLiteDatabase.CursorFactory, java.lang.String, java.lang.String[], java.lang.String);
-    method public android.database.Cursor rawQueryWithFactory(android.database.sqlite.SQLiteDatabase.CursorFactory, java.lang.String, java.lang.String[], java.lang.String, android.content.CancellationSignal);
+    method public android.database.Cursor rawQueryWithFactory(android.database.sqlite.SQLiteDatabase.CursorFactory, java.lang.String, java.lang.String[], java.lang.String, android.os.CancellationSignal);
     method public static int releaseMemory();
     method public long replace(java.lang.String, java.lang.String, android.content.ContentValues);
     method public long replaceOrThrow(java.lang.String, java.lang.String, android.content.ContentValues) throws android.database.SQLException;
@@ -7638,7 +7620,7 @@
     method public java.lang.String getTables();
     method public android.database.Cursor query(android.database.sqlite.SQLiteDatabase, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String, java.lang.String, java.lang.String);
     method public android.database.Cursor query(android.database.sqlite.SQLiteDatabase, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String, java.lang.String, java.lang.String, java.lang.String);
-    method public android.database.Cursor query(android.database.sqlite.SQLiteDatabase, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String, java.lang.String, java.lang.String, java.lang.String, android.content.CancellationSignal);
+    method public android.database.Cursor query(android.database.sqlite.SQLiteDatabase, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String, java.lang.String, java.lang.String, java.lang.String, android.os.CancellationSignal);
     method public void setCursorFactory(android.database.sqlite.SQLiteDatabase.CursorFactory);
     method public void setDistinct(boolean);
     method public void setProjectionMap(java.util.Map<java.lang.String, java.lang.String>);
@@ -15365,6 +15347,18 @@
     field public static final android.os.Bundle EMPTY;
   }
 
+  public final class CancellationSignal {
+    ctor public CancellationSignal();
+    method public void cancel();
+    method public boolean isCanceled();
+    method public void setOnCancelListener(android.os.CancellationSignal.OnCancelListener);
+    method public void throwIfCanceled();
+  }
+
+  public static abstract interface CancellationSignal.OnCancelListener {
+    method public abstract void onCancel();
+  }
+
   public class ConditionVariable {
     ctor public ConditionVariable();
     ctor public ConditionVariable(boolean);
@@ -15729,6 +15723,11 @@
     ctor public NetworkOnMainThreadException();
   }
 
+  public class OperationCanceledException extends java.lang.RuntimeException {
+    ctor public OperationCanceledException();
+    ctor public OperationCanceledException(java.lang.String);
+  }
+
   public final class Parcel {
     method public final void appendFrom(android.os.Parcel, int, int);
     method public final android.os.IBinder[] createBinderArray();
@@ -25182,6 +25181,7 @@
     method public boolean isPassword();
     method public boolean isScrollable();
     method public boolean isSelected();
+    method public boolean isVisibleToUser();
     method public static android.view.accessibility.AccessibilityNodeInfo obtain(android.view.View);
     method public static android.view.accessibility.AccessibilityNodeInfo obtain(android.view.View, int);
     method public static android.view.accessibility.AccessibilityNodeInfo obtain();
@@ -25211,6 +25211,7 @@
     method public void setSource(android.view.View);
     method public void setSource(android.view.View, int);
     method public void setText(java.lang.CharSequence);
+    method public void setVisibleToUser(boolean);
     method public void writeToParcel(android.os.Parcel, int);
     field public static final int ACTION_ACCESSIBILITY_FOCUS = 64; // 0x40
     field public static final java.lang.String ACTION_ARGUMENT_HTML_ELEMENT_STRING = "ACTION_ARGUMENT_HTML_ELEMENT_STRING";
diff --git a/cmds/pm/src/com/android/commands/pm/Pm.java b/cmds/pm/src/com/android/commands/pm/Pm.java
index e19ad66..f9ff861 100644
--- a/cmds/pm/src/com/android/commands/pm/Pm.java
+++ b/cmds/pm/src/com/android/commands/pm/Pm.java
@@ -16,9 +16,12 @@
 
 package com.android.commands.pm;
 
+import com.android.internal.content.PackageHelper;
+
 import android.app.ActivityManagerNative;
 import android.content.ComponentName;
 import android.content.pm.ApplicationInfo;
+import android.content.pm.ContainerEncryptionParams;
 import android.content.pm.FeatureInfo;
 import android.content.pm.IPackageDataObserver;
 import android.content.pm.IPackageDeleteObserver;
@@ -40,17 +43,20 @@
 import android.os.RemoteException;
 import android.os.ServiceManager;
 
-import com.android.internal.content.PackageHelper;
-
 import java.io.File;
 import java.lang.reflect.Field;
 import java.lang.reflect.Modifier;
+import java.security.InvalidAlgorithmParameterException;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.List;
 import java.util.WeakHashMap;
 
+import javax.crypto.SecretKey;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+
 public final class Pm {
     IPackageManager mPm;
 
@@ -763,6 +769,15 @@
         String installerPackageName = null;
 
         String opt;
+
+        String algo = null;
+        byte[] iv = null;
+        byte[] key = null;
+
+        String macAlgo = null;
+        byte[] macKey = null;
+        byte[] tag = null;
+
         while ((opt=nextOption()) != null) {
             if (opt.equals("-l")) {
                 installFlags |= PackageManager.INSTALL_FORWARD_LOCK;
@@ -783,6 +798,48 @@
             } else if (opt.equals("-f")) {
                 // Override if -s option is specified.
                 installFlags |= PackageManager.INSTALL_INTERNAL;
+            } else if (opt.equals("--algo")) {
+                algo = nextOptionData();
+                if (algo == null) {
+                    System.err.println("Error: must supply argument for --algo");
+                    showUsage();
+                    return;
+                }
+            } else if (opt.equals("--iv")) {
+                iv = hexToBytes(nextOptionData());
+                if (iv == null) {
+                    System.err.println("Error: must supply argument for --iv");
+                    showUsage();
+                    return;
+                }
+            } else if (opt.equals("--key")) {
+                key = hexToBytes(nextOptionData());
+                if (key == null) {
+                    System.err.println("Error: must supply argument for --key");
+                    showUsage();
+                    return;
+                }
+            } else if (opt.equals("--macalgo")) {
+                macAlgo = nextOptionData();
+                if (macAlgo == null) {
+                    System.err.println("Error: must supply argument for --macalgo");
+                    showUsage();
+                    return;
+                }
+            } else if (opt.equals("--mackey")) {
+                macKey = hexToBytes(nextOptionData());
+                if (macKey == null) {
+                    System.err.println("Error: must supply argument for --mackey");
+                    showUsage();
+                    return;
+                }
+            } else if (opt.equals("--tag")) {
+                tag = hexToBytes(nextOptionData());
+                if (tag == null) {
+                    System.err.println("Error: must supply argument for --tag");
+                    showUsage();
+                    return;
+                }
             } else {
                 System.err.println("Error: Unknown option: " + opt);
                 showUsage();
@@ -790,6 +847,44 @@
             }
         }
 
+        final ContainerEncryptionParams encryptionParams;
+        if (algo != null || iv != null || key != null || macAlgo != null || macKey != null
+                || tag != null) {
+            if (algo == null || iv == null || key == null) {
+                System.err.println("Error: all of --algo, --iv, and --key must be specified");
+                showUsage();
+                return;
+            }
+
+            if (macAlgo != null || macKey != null || tag != null) {
+                if (macAlgo == null || macKey == null || tag == null) {
+                    System.err.println("Error: all of --macalgo, --mackey, and --tag must "
+                            + "be specified");
+                    showUsage();
+                    return;
+                }
+            }
+
+            try {
+                final SecretKey encKey = new SecretKeySpec(key, "RAW");
+
+                final SecretKey macSecretKey;
+                if (macKey == null || macKey.length == 0) {
+                    macSecretKey = null;
+                } else {
+                    macSecretKey = new SecretKeySpec(macKey, "RAW");
+                }
+
+                encryptionParams = new ContainerEncryptionParams(algo, new IvParameterSpec(iv),
+                        encKey, macAlgo, null, macSecretKey, tag, -1, -1, -1);
+            } catch (InvalidAlgorithmParameterException e) {
+                e.printStackTrace();
+                return;
+            }
+        } else {
+            encryptionParams = null;
+        }
+
         final Uri apkURI;
         final Uri verificationURI;
 
@@ -816,7 +911,7 @@
         PackageInstallObserver obs = new PackageInstallObserver();
         try {
             mPm.installPackageWithVerification(apkURI, obs, installFlags, installerPackageName,
-                    verificationURI, null);
+                    verificationURI, null, encryptionParams);
 
             synchronized (obs) {
                 while (!obs.finished) {
@@ -839,6 +934,37 @@
         }
     }
 
+    /**
+     * Convert a string containing hex-encoded bytes to a byte array.
+     *
+     * @param input String containing hex-encoded bytes
+     * @return input as an array of bytes
+     */
+    private byte[] hexToBytes(String input) {
+        if (input == null) {
+            return null;
+        }
+
+        final int inputLength = input.length();
+        if ((inputLength % 2) != 0) {
+            System.err.print("Invalid length; must be multiple of 2");
+            return null;
+        }
+
+        final int byteLength = inputLength / 2;
+        final byte[] output = new byte[byteLength];
+
+        int inputIndex = 0;
+        int byteIndex = 0;
+        while (inputIndex < inputLength) {
+            output[byteIndex++] = (byte) Integer.parseInt(
+                    input.substring(inputIndex, inputIndex + 2), 16);
+            inputIndex += 2;
+        }
+
+        return output;
+    }
+
     public void runCreateUser() {
         // Need to be run as root
         if (Process.myUid() != ROOT_UID) {
@@ -1236,7 +1362,8 @@
         System.err.println("       pm list libraries");
         System.err.println("       pm list users");
         System.err.println("       pm path PACKAGE");
-        System.err.println("       pm install [-l] [-r] [-t] [-i INSTALLER_PACKAGE_NAME] [-s] [-f] PATH");
+        System.err.println("       pm install [-l] [-r] [-t] [-i INSTALLER_PACKAGE_NAME] [-s] [-f]");
+        System.err.println("                  [--algo <algorithm name> --key <key-in-hex> --iv <IV-in-hex>] PATH");
         System.err.println("       pm uninstall [-k] PACKAGE");
         System.err.println("       pm clear PACKAGE");
         System.err.println("       pm enable [--user USER_ID] PACKAGE_OR_COMPONENT");
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 781eea5..ac55abe 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -2493,7 +2493,7 @@
         if (featureId == Window.FEATURE_OPTIONS_PANEL && menu != null) {
             boolean goforit = onPrepareOptionsMenu(menu);
             goforit |= mFragments.dispatchPrepareOptionsMenu(menu);
-            return goforit && menu.hasVisibleItems();
+            return goforit;
         }
         return true;
     }
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 314f5c2..8799194 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -2639,6 +2639,7 @@
                     if (DEBUG_CONFIGURATION) Slog.v(TAG, "Resuming activity "
                             + r.activityInfo.name + " with newConfig " + r.newConfig);
                     performConfigurationChanged(r.activity, r.newConfig);
+                    freeTextLayoutCachesIfNeeded(r.activity.mCurrentConfig.diff(r.newConfig));
                     r.newConfig = null;
                 }
                 if (localLOGV) Slog.v(TAG, "Resuming " + r + " with isForward="
@@ -2955,6 +2956,7 @@
                     if (DEBUG_CONFIGURATION) Slog.v(TAG, "Updating activity vis "
                             + r.activityInfo.name + " with new config " + r.newConfig);
                     performConfigurationChanged(r.activity, r.newConfig);
+                    freeTextLayoutCachesIfNeeded(r.activity.mCurrentConfig.diff(r.newConfig));
                     r.newConfig = null;
                 }
             } else {
@@ -3669,6 +3671,7 @@
     final void handleConfigurationChanged(Configuration config, CompatibilityInfo compat) {
 
         ArrayList<ComponentCallbacks2> callbacks = null;
+        int configDiff = 0;
 
         synchronized (mPackages) {
             if (mPendingConfiguration != null) {
@@ -3693,6 +3696,7 @@
             if (!mConfiguration.isOtherSeqNewer(config) && compat == null) {
                 return;
             }
+            configDiff = mConfiguration.diff(config);
             mConfiguration.updateFrom(config);
             config = applyCompatConfiguration();
             callbacks = collectComponentCallbacksLocked(false, config);
@@ -3701,6 +3705,8 @@
         // Cleanup hardware accelerated stuff
         WindowManagerImpl.getDefault().trimLocalMemory();
 
+        freeTextLayoutCachesIfNeeded(configDiff);
+
         if (callbacks != null) {
             final int N = callbacks.size();
             for (int i=0; i<N; i++) {
@@ -3709,6 +3715,17 @@
         }
     }
 
+    final void freeTextLayoutCachesIfNeeded(int configDiff) {
+        if (configDiff != 0) {
+            // Ask text layout engine to free its caches if there is a locale change
+            boolean hasLocaleConfigChange = ((configDiff & ActivityInfo.CONFIG_LOCALE) != 0);
+            if (hasLocaleConfigChange) {
+                Canvas.freeTextLayoutCaches();
+                if (DEBUG_CONFIGURATION) Slog.v(TAG, "Cleared TextLayout Caches");
+            }
+        }
+    }
+
     final void handleActivityConfigurationChanged(IBinder token) {
         ActivityClientRecord r = mActivities.get(token);
         if (r == null || r.activity == null) {
@@ -3719,6 +3736,8 @@
                 + r.activityInfo.name);
         
         performConfigurationChanged(r.activity, mCompatConfiguration);
+
+        freeTextLayoutCachesIfNeeded(r.activity.mCurrentConfig.diff(mCompatConfiguration));
     }
 
     final void handleProfilerControl(boolean start, ProfilerControlData pcd, int profileType) {
@@ -3821,6 +3840,9 @@
         // Ask graphics to free up as much as possible (font/image caches)
         Canvas.freeCaches();
 
+        // Ask text layout engine to free also as much as possible
+        Canvas.freeTextLayoutCaches();
+
         BinderInternal.forceGc("mem");
     }
 
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index 0510de1..191a696 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -24,6 +24,7 @@
 import android.content.pm.ActivityInfo;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.ComponentInfo;
+import android.content.pm.ContainerEncryptionParams;
 import android.content.pm.FeatureInfo;
 import android.content.pm.IPackageDataObserver;
 import android.content.pm.IPackageDeleteObserver;
@@ -973,10 +974,10 @@
     @Override
     public void installPackageWithVerification(Uri packageURI, IPackageInstallObserver observer,
             int flags, String installerPackageName, Uri verificationURI,
-            ManifestDigest manifestDigest) {
+            ManifestDigest manifestDigest, ContainerEncryptionParams encryptionParams) {
         try {
             mPM.installPackageWithVerification(packageURI, observer, flags, installerPackageName,
-                    verificationURI, manifestDigest);
+                    verificationURI, manifestDigest, encryptionParams);
         } catch (RemoteException e) {
             // Should never happen!
         }
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 0d76877..f962259 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -1436,6 +1436,7 @@
                 // Log.d("Notification", "has actions: " + mContentText);
                 big.setViewVisibility(R.id.actions, View.VISIBLE);
                 if (N>3) N=3;
+                big.removeAllViews(R.id.actions);
                 for (int i=0; i<N; i++) {
                     final RemoteViews button = generateActionButton(mActions.get(i));
                     //Log.d("Notification", "adding action " + i + ": " + mActions.get(i).title);
diff --git a/core/java/android/content/AsyncTaskLoader.java b/core/java/android/content/AsyncTaskLoader.java
index da51952..f9025d9 100644
--- a/core/java/android/content/AsyncTaskLoader.java
+++ b/core/java/android/content/AsyncTaskLoader.java
@@ -18,6 +18,7 @@
 
 import android.os.AsyncTask;
 import android.os.Handler;
+import android.os.OperationCanceledException;
 import android.os.SystemClock;
 import android.util.Slog;
 import android.util.TimeUtils;
diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java
index 1206056..b22179e 100644
--- a/core/java/android/content/ContentProvider.java
+++ b/core/java/android/content/ContentProvider.java
@@ -29,6 +29,9 @@
 import android.os.AsyncTask;
 import android.os.Binder;
 import android.os.Bundle;
+import android.os.CancellationSignal;
+import android.os.ICancellationSignal;
+import android.os.OperationCanceledException;
 import android.os.ParcelFileDescriptor;
 import android.os.Process;
 import android.os.RemoteException;
diff --git a/core/java/android/content/ContentProviderClient.java b/core/java/android/content/ContentProviderClient.java
index 3ac5e07..da2ab94 100644
--- a/core/java/android/content/ContentProviderClient.java
+++ b/core/java/android/content/ContentProviderClient.java
@@ -19,6 +19,8 @@
 import android.database.Cursor;
 import android.net.Uri;
 import android.os.Bundle;
+import android.os.CancellationSignal;
+import android.os.ICancellationSignal;
 import android.os.RemoteException;
 import android.os.ParcelFileDescriptor;
 import android.content.res.AssetFileDescriptor;
diff --git a/core/java/android/content/ContentProviderNative.java b/core/java/android/content/ContentProviderNative.java
index 4b31552..550a1c9 100644
--- a/core/java/android/content/ContentProviderNative.java
+++ b/core/java/android/content/ContentProviderNative.java
@@ -30,6 +30,7 @@
 import android.os.Bundle;
 import android.os.RemoteException;
 import android.os.IBinder;
+import android.os.ICancellationSignal;
 import android.os.Parcel;
 import android.os.ParcelFileDescriptor;
 import android.os.Parcelable;
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
index 722fdc6..d4bca0a 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -33,7 +33,10 @@
 import android.database.IContentObserver;
 import android.net.Uri;
 import android.os.Bundle;
+import android.os.CancellationSignal;
 import android.os.IBinder;
+import android.os.ICancellationSignal;
+import android.os.OperationCanceledException;
 import android.os.ParcelFileDescriptor;
 import android.os.RemoteException;
 import android.os.ServiceManager;
diff --git a/core/java/android/content/CursorLoader.java b/core/java/android/content/CursorLoader.java
index aed3728..9f7a104 100644
--- a/core/java/android/content/CursorLoader.java
+++ b/core/java/android/content/CursorLoader.java
@@ -19,6 +19,8 @@
 import android.database.ContentObserver;
 import android.database.Cursor;
 import android.net.Uri;
+import android.os.CancellationSignal;
+import android.os.OperationCanceledException;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
diff --git a/core/java/android/content/IContentProvider.java b/core/java/android/content/IContentProvider.java
index 16478b7..eeba1e0 100644
--- a/core/java/android/content/IContentProvider.java
+++ b/core/java/android/content/IContentProvider.java
@@ -21,6 +21,7 @@
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.IBinder;
+import android.os.ICancellationSignal;
 import android.os.IInterface;
 import android.os.ParcelFileDescriptor;
 import android.os.RemoteException;
diff --git a/core/java/android/content/ICancellationSignal.aidl b/core/java/android/content/pm/ContainerEncryptionParams.aidl
similarity index 70%
copy from core/java/android/content/ICancellationSignal.aidl
copy to core/java/android/content/pm/ContainerEncryptionParams.aidl
index cf1c5d3..c13d946 100644
--- a/core/java/android/content/ICancellationSignal.aidl
+++ b/core/java/android/content/pm/ContainerEncryptionParams.aidl
@@ -1,11 +1,11 @@
 /*
- * Copyright (C) 2012 The Android Open Source Project
+ * Copyright 2012, The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
- *      http://www.apache.org/licenses/LICENSE-2.0
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
@@ -14,11 +14,6 @@
  * limitations under the License.
  */
 
-package android.content;
+package android.content.pm;
 
-/**
- * @hide
- */
-interface ICancellationSignal {
-    oneway void cancel();
-}
+parcelable ContainerEncryptionParams;
diff --git a/core/java/android/content/pm/ContainerEncryptionParams.java b/core/java/android/content/pm/ContainerEncryptionParams.java
new file mode 100644
index 0000000..5b1440d
--- /dev/null
+++ b/core/java/android/content/pm/ContainerEncryptionParams.java
@@ -0,0 +1,378 @@
+/*
+ * 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.content.pm;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.text.TextUtils;
+import android.util.Slog;
+
+import java.security.InvalidAlgorithmParameterException;
+import java.security.spec.AlgorithmParameterSpec;
+import java.util.Arrays;
+
+import javax.crypto.SecretKey;
+import javax.crypto.spec.IvParameterSpec;
+
+/**
+ * Represents encryption parameters used to read a container.
+ *
+ * @hide
+ */
+public class ContainerEncryptionParams implements Parcelable {
+    protected static final String TAG = "ContainerEncryptionParams";
+
+    /** What we print out first when toString() is called. */
+    private static final String TO_STRING_PREFIX = "ContainerEncryptionParams{";
+
+    /**
+     * Parameter type for parceling that indicates the next parameters are
+     * IvParameters.
+     */
+    private static final int ENC_PARAMS_IV_PARAMETERS = 1;
+
+    /** Parameter type for paceling that indicates there are no MAC parameters. */
+    private static final int MAC_PARAMS_NONE = 1;
+
+    /** The encryption algorithm used. */
+    private final String mEncryptionAlgorithm;
+
+    /** The parameter spec to be used for encryption. */
+    private final IvParameterSpec mEncryptionSpec;
+
+    /** Secret key to be used for decryption. */
+    private final SecretKey mEncryptionKey;
+
+    /** Algorithm name for the MAC to be used. */
+    private final String mMacAlgorithm;
+
+    /** The parameter spec to be used for the MAC tag authentication. */
+    private final AlgorithmParameterSpec mMacSpec;
+
+    /** Secret key to be used for MAC tag authentication. */
+    private final SecretKey mMacKey;
+
+    /** MAC tag authenticating the data in the container. */
+    private final byte[] mMacTag;
+
+    /** Offset into file where authenticated (e.g., MAC protected) data begins. */
+    private final int mAuthenticatedDataStart;
+
+    /** Offset into file where encrypted data begins. */
+    private final int mEncryptedDataStart;
+
+    /**
+     * Offset into file for the end of encrypted data (and, by extension,
+     * authenticated data) in file.
+     */
+    private final int mDataEnd;
+
+    public ContainerEncryptionParams(String encryptionAlgorithm,
+            AlgorithmParameterSpec encryptionSpec, SecretKey encryptionKey)
+            throws InvalidAlgorithmParameterException {
+        this(encryptionAlgorithm, encryptionSpec, encryptionKey, null, null, null, null, -1, -1,
+                -1);
+    }
+
+    /**
+     * Creates container encryption specifications for installing from encrypted
+     * containers.
+     *
+     * @param encryptionAlgorithm encryption algorithm to use; format matches
+     *            JCE
+     * @param encryptionSpec algorithm parameter specification
+     * @param encryptionKey key used for decryption
+     * @param macAlgorithm MAC algorithm to use; format matches JCE
+     * @param macSpec algorithm parameters specification, may be {@code null}
+     * @param macKey key used for authentication (i.e., for the MAC tag)
+     * @param authenticatedDataStart offset of start of authenticated data in
+     *            stream
+     * @param encryptedDataStart offset of start of encrypted data in stream
+     * @param dataEnd offset of the end of both the authenticated and encrypted
+     *            data
+     * @throws InvalidAlgorithmParameterException
+     */
+    public ContainerEncryptionParams(String encryptionAlgorithm,
+            AlgorithmParameterSpec encryptionSpec, SecretKey encryptionKey, String macAlgorithm,
+            AlgorithmParameterSpec macSpec, SecretKey macKey, byte[] macTag,
+            int authenticatedDataStart, int encryptedDataStart, int dataEnd)
+            throws InvalidAlgorithmParameterException {
+        if (TextUtils.isEmpty(encryptionAlgorithm)) {
+            throw new NullPointerException("algorithm == null");
+        } else if (encryptionSpec == null) {
+            throw new NullPointerException("encryptionSpec == null");
+        } else if (encryptionKey == null) {
+            throw new NullPointerException("encryptionKey == null");
+        }
+
+        if (!TextUtils.isEmpty(macAlgorithm)) {
+            if (macKey == null) {
+                throw new NullPointerException("macKey == null");
+            }
+        }
+
+        if (!(encryptionSpec instanceof IvParameterSpec)) {
+            throw new InvalidAlgorithmParameterException(
+                    "Unknown parameter spec class; must be IvParameters");
+        }
+
+        mEncryptionAlgorithm = encryptionAlgorithm;
+        mEncryptionSpec = (IvParameterSpec) encryptionSpec;
+        mEncryptionKey = encryptionKey;
+
+        mMacAlgorithm = macAlgorithm;
+        mMacSpec = macSpec;
+        mMacKey = macKey;
+        mMacTag = macTag;
+
+        mAuthenticatedDataStart = authenticatedDataStart;
+        mEncryptedDataStart = encryptedDataStart;
+        mDataEnd = dataEnd;
+    }
+
+    public String getEncryptionAlgorithm() {
+        return mEncryptionAlgorithm;
+    }
+
+    public AlgorithmParameterSpec getEncryptionSpec() {
+        return mEncryptionSpec;
+    }
+
+    public SecretKey getEncryptionKey() {
+        return mEncryptionKey;
+    }
+
+    public String getMacAlgorithm() {
+        return mMacAlgorithm;
+    }
+
+    public AlgorithmParameterSpec getMacSpec() {
+        return mMacSpec;
+    }
+
+    public SecretKey getMacKey() {
+        return mMacKey;
+    }
+
+    public byte[] getMacTag() {
+        return mMacTag;
+    }
+
+    public int getAuthenticatedDataStart() {
+        return mAuthenticatedDataStart;
+    }
+
+    public int getEncryptedDataStart() {
+        return mEncryptedDataStart;
+    }
+
+    public int getDataEnd() {
+        return mDataEnd;
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+
+        if (!(o instanceof ContainerEncryptionParams)) {
+            return false;
+        }
+
+        final ContainerEncryptionParams other = (ContainerEncryptionParams) o;
+
+        // Primitive comparison
+        if ((mAuthenticatedDataStart != other.mAuthenticatedDataStart)
+                || (mEncryptedDataStart != other.mEncryptedDataStart)
+                || (mDataEnd != other.mDataEnd)) {
+            return false;
+        }
+
+        // String comparison
+        if (!mEncryptionAlgorithm.equals(other.mEncryptionAlgorithm)
+                || !mMacAlgorithm.equals(other.mMacAlgorithm)) {
+            return false;
+        }
+
+        // Object comparison
+        if (!isSecretKeyEqual(mEncryptionKey, other.mEncryptionKey)
+                || !isSecretKeyEqual(mMacKey, other.mMacKey)) {
+            return false;
+        }
+
+        if (!Arrays.equals(mEncryptionSpec.getIV(), other.mEncryptionSpec.getIV())
+                || !Arrays.equals(mMacTag, other.mMacTag) || (mMacSpec != other.mMacSpec)) {
+            return false;
+        }
+
+        return true;
+    }
+
+    private static final boolean isSecretKeyEqual(SecretKey key1, SecretKey key2) {
+        final String keyFormat = key1.getFormat();
+        final String otherKeyFormat = key2.getFormat();
+
+        if (keyFormat == null) {
+            if (keyFormat != otherKeyFormat) {
+                return false;
+            }
+
+            if (key1.getEncoded() != key2.getEncoded()) {
+                return false;
+            }
+        } else {
+            if (!keyFormat.equals(key2.getFormat())) {
+                return false;
+            }
+
+            if (!Arrays.equals(key1.getEncoded(), key2.getEncoded())) {
+                return false;
+            }
+        }
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        int hash = 3;
+
+        hash += 5 * mEncryptionAlgorithm.hashCode();
+        hash += 7 * Arrays.hashCode(mEncryptionSpec.getIV());
+        hash += 11 * mEncryptionKey.hashCode();
+        hash += 13 * mMacAlgorithm.hashCode();
+        hash += 17 * mMacKey.hashCode();
+        hash += 19 * Arrays.hashCode(mMacTag);
+        hash += 23 * mAuthenticatedDataStart;
+        hash += 29 * mEncryptedDataStart;
+        hash += 31 * mDataEnd;
+
+        return hash;
+    }
+
+    @Override
+    public String toString() {
+        final StringBuilder sb = new StringBuilder(TO_STRING_PREFIX);
+
+        sb.append("mEncryptionAlgorithm=\"");
+        sb.append(mEncryptionAlgorithm);
+        sb.append("\",");
+        sb.append("mEncryptionSpec=");
+        sb.append(mEncryptionSpec.toString());
+        sb.append("mEncryptionKey=");
+        sb.append(mEncryptionKey.toString());
+
+        sb.append("mMacAlgorithm=\"");
+        sb.append(mMacAlgorithm);
+        sb.append("\",");
+        sb.append("mMacSpec=");
+        sb.append(mMacSpec.toString());
+        sb.append("mMacKey=");
+        sb.append(mMacKey.toString());
+
+        sb.append(",mAuthenticatedDataStart=");
+        sb.append(mAuthenticatedDataStart);
+        sb.append(",mEncryptedDataStart=");
+        sb.append(mEncryptedDataStart);
+        sb.append(",mDataEnd=");
+        sb.append(mDataEnd);
+        sb.append('}');
+
+        return sb.toString();
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeString(mEncryptionAlgorithm);
+        dest.writeInt(ENC_PARAMS_IV_PARAMETERS);
+        dest.writeByteArray(mEncryptionSpec.getIV());
+        dest.writeSerializable(mEncryptionKey);
+
+        dest.writeString(mMacAlgorithm);
+        dest.writeInt(MAC_PARAMS_NONE);
+        dest.writeByteArray(new byte[0]);
+        dest.writeSerializable(mMacKey);
+
+        dest.writeByteArray(mMacTag);
+
+        dest.writeInt(mAuthenticatedDataStart);
+        dest.writeInt(mEncryptedDataStart);
+        dest.writeInt(mDataEnd);
+    }
+
+    private ContainerEncryptionParams(Parcel source) throws InvalidAlgorithmParameterException {
+        mEncryptionAlgorithm = source.readString();
+        final int encParamType = source.readInt();
+        final byte[] encParamsEncoded = source.createByteArray();
+        mEncryptionKey = (SecretKey) source.readSerializable();
+
+        mMacAlgorithm = source.readString();
+        final int macParamType = source.readInt();
+        source.createByteArray(); // byte[] macParamsEncoded
+        mMacKey = (SecretKey) source.readSerializable();
+
+        mMacTag = source.createByteArray();
+
+        mAuthenticatedDataStart = source.readInt();
+        mEncryptedDataStart = source.readInt();
+        mDataEnd = source.readInt();
+
+        switch (encParamType) {
+            case ENC_PARAMS_IV_PARAMETERS:
+                mEncryptionSpec = new IvParameterSpec(encParamsEncoded);
+                break;
+            default:
+                throw new InvalidAlgorithmParameterException("Unknown parameter type "
+                        + encParamType);
+        }
+
+        switch (macParamType) {
+            case MAC_PARAMS_NONE:
+                mMacSpec = null;
+                break;
+            default:
+                throw new InvalidAlgorithmParameterException("Unknown parameter type "
+                        + macParamType);
+        }
+
+        if (mEncryptionKey == null) {
+            throw new NullPointerException("encryptionKey == null");
+        }
+    }
+
+    public static final Parcelable.Creator<ContainerEncryptionParams> CREATOR =
+            new Parcelable.Creator<ContainerEncryptionParams>() {
+        public ContainerEncryptionParams createFromParcel(Parcel source) {
+            try {
+                return new ContainerEncryptionParams(source);
+            } catch (InvalidAlgorithmParameterException e) {
+                Slog.e(TAG, "Invalid algorithm parameters specified", e);
+                return null;
+            }
+        }
+
+        public ContainerEncryptionParams[] newArray(int size) {
+            return new ContainerEncryptionParams[size];
+        }
+    };
+}
\ No newline at end of file
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index 9b8454a..70c0c48 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -22,6 +22,7 @@
 import android.content.IntentFilter;
 import android.content.pm.ActivityInfo;
 import android.content.pm.ApplicationInfo;
+import android.content.pm.ContainerEncryptionParams;
 import android.content.pm.FeatureInfo;
 import android.content.pm.IPackageInstallObserver;
 import android.content.pm.IPackageDeleteObserver;
@@ -362,7 +363,7 @@
 
     void installPackageWithVerification(in Uri packageURI, in IPackageInstallObserver observer,
             int flags, in String installerPackageName, in Uri verificationURI,
-            in ManifestDigest manifestDigest);
+            in ManifestDigest manifestDigest, in ContainerEncryptionParams encryptionParams);
 
     void verifyPendingInstall(int id, int verificationCode);
 
diff --git a/core/java/android/content/pm/LimitedLengthInputStream.java b/core/java/android/content/pm/LimitedLengthInputStream.java
new file mode 100644
index 0000000..25a490f
--- /dev/null
+++ b/core/java/android/content/pm/LimitedLengthInputStream.java
@@ -0,0 +1,82 @@
+package android.content.pm;
+
+import java.io.FilterInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * A class that limits the amount of data that is read from an InputStream. When
+ * the specified length is reached, the stream returns an EOF even if the
+ * underlying stream still has more data.
+ *
+ * @hide
+ */
+public class LimitedLengthInputStream extends FilterInputStream {
+    /**
+     * The end of the stream where we don't want to allow more data to be read.
+     */
+    private final int mEnd;
+
+    /**
+     * Current offset in the stream.
+     */
+    private int mOffset;
+
+    /**
+     * @param in underlying stream to wrap
+     * @param offset offset into stream where data starts
+     * @param length length of data at offset
+     * @throws IOException if an error occured with the underlying stream
+     */
+    public LimitedLengthInputStream(InputStream in, int offset, int length) throws IOException {
+        super(in);
+
+        if (in == null) {
+            throw new IOException("in == null");
+        }
+
+        if (offset < 0) {
+            throw new IOException("offset == " + offset);
+        }
+
+        if (length < 0) {
+            throw new IOException("length must be non-negative; is " + length);
+        }
+
+        mEnd = offset + length;
+
+        skip(offset);
+        mOffset = offset;
+    }
+
+    @Override
+    public synchronized int read() throws IOException {
+        if (mOffset >= mEnd) {
+            return -1;
+        }
+
+        mOffset++;
+        return super.read();
+    }
+
+    @Override
+    public int read(byte[] buffer, int offset, int byteCount) throws IOException {
+        if (mOffset >= mEnd) {
+            return -1;
+        }
+
+        if (mOffset + byteCount > mEnd) {
+            byteCount = mEnd - mOffset;
+        }
+
+        final int numRead = super.read(buffer, offset, byteCount);
+        mOffset += numRead;
+
+        return numRead;
+    }
+
+    @Override
+    public int read(byte[] buffer) throws IOException {
+        return read(buffer, 0, buffer.length);
+    }
+}
diff --git a/core/java/android/content/pm/MacAuthenticatedInputStream.java b/core/java/android/content/pm/MacAuthenticatedInputStream.java
new file mode 100644
index 0000000..11f4b94
--- /dev/null
+++ b/core/java/android/content/pm/MacAuthenticatedInputStream.java
@@ -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.
+ */
+
+package android.content.pm;
+
+import java.io.FilterInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+import javax.crypto.Mac;
+
+/**
+ * An input stream filter that applies a MAC to the data passing through it. At
+ * the end of the data that should be authenticated, the tag can be calculated.
+ * After that, the stream should not be used.
+ *
+ * @hide
+ */
+public class MacAuthenticatedInputStream extends FilterInputStream {
+    private final Mac mMac;
+
+    public MacAuthenticatedInputStream(InputStream in, Mac mac) {
+        super(in);
+
+        mMac = mac;
+    }
+
+    public boolean isTagEqual(byte[] tag) {
+        final byte[] actualTag = mMac.doFinal();
+
+        if (tag == null || actualTag == null || tag.length != actualTag.length) {
+            return false;
+        }
+
+        /*
+         * Attempt to prevent timing attacks by doing the same amount of work
+         * whether the first byte matches or not. Do not change this to a loop
+         * that exits early when a byte does not match.
+         */
+        int value = 0;
+        for (int i = 0; i < tag.length; i++) {
+            value |= tag[i] ^ actualTag[i];
+        }
+
+        return value == 0;
+    }
+
+    @Override
+    public int read() throws IOException {
+        final int b = super.read();
+        if (b >= 0) {
+            mMac.update((byte) b);
+        }
+        return b;
+    }
+
+    @Override
+    public int read(byte[] buffer, int offset, int count) throws IOException {
+        int numRead = super.read(buffer, offset, count);
+        if (numRead > 0) {
+            mMac.update(buffer, offset, numRead);
+        }
+        return numRead;
+    }
+}
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index c3ce1cf..a48924e 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -28,7 +28,6 @@
 import android.content.res.XmlResourceParser;
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
-import android.os.Build;
 import android.os.Environment;
 import android.util.AndroidException;
 import android.util.DisplayMetrics;
@@ -2199,12 +2198,19 @@
      *            is performing the installation. This identifies which market
      *            the package came from.
      * @param verificationURI The location of the supplementary verification
-     *            file. This can be a 'file:' or a 'content:' URI.
+     *            file. This can be a 'file:' or a 'content:' URI. May be
+     *            {@code null}.
+     * @param manifestDigest an object that holds the digest of the package
+     *            which can be used to verify ownership. May be {@code null}.
+     * @param encryptionParams if the package to be installed is encrypted,
+     *            these parameters describing the encryption and authentication
+     *            used. May be {@code null}.
      * @hide
      */
     public abstract void installPackageWithVerification(Uri packageURI,
             IPackageInstallObserver observer, int flags, String installerPackageName,
-            Uri verificationURI, ManifestDigest manifestDigest);
+            Uri verificationURI, ManifestDigest manifestDigest,
+            ContainerEncryptionParams encryptionParams);
 
     /**
      * Allows a package listening to the
diff --git a/core/java/android/database/DatabaseUtils.java b/core/java/android/database/DatabaseUtils.java
index 40a54cf..a6af5c2 100644
--- a/core/java/android/database/DatabaseUtils.java
+++ b/core/java/android/database/DatabaseUtils.java
@@ -21,7 +21,6 @@
 import android.content.ContentValues;
 import android.content.Context;
 import android.content.OperationApplicationException;
-import android.content.OperationCanceledException;
 import android.database.sqlite.SQLiteAbortException;
 import android.database.sqlite.SQLiteConstraintException;
 import android.database.sqlite.SQLiteDatabase;
@@ -31,6 +30,7 @@
 import android.database.sqlite.SQLiteFullException;
 import android.database.sqlite.SQLiteProgram;
 import android.database.sqlite.SQLiteStatement;
+import android.os.OperationCanceledException;
 import android.os.Parcel;
 import android.os.ParcelFileDescriptor;
 import android.text.TextUtils;
diff --git a/core/java/android/database/sqlite/SQLiteConnection.java b/core/java/android/database/sqlite/SQLiteConnection.java
index acdc488..6f7c1f3 100644
--- a/core/java/android/database/sqlite/SQLiteConnection.java
+++ b/core/java/android/database/sqlite/SQLiteConnection.java
@@ -19,12 +19,12 @@
 import dalvik.system.BlockGuard;
 import dalvik.system.CloseGuard;
 
-import android.content.CancellationSignal;
-import android.content.OperationCanceledException;
 import android.database.Cursor;
 import android.database.CursorWindow;
 import android.database.DatabaseUtils;
 import android.database.sqlite.SQLiteDebug.DbStats;
+import android.os.CancellationSignal;
+import android.os.OperationCanceledException;
 import android.os.ParcelFileDescriptor;
 import android.util.Log;
 import android.util.LruCache;
diff --git a/core/java/android/database/sqlite/SQLiteConnectionPool.java b/core/java/android/database/sqlite/SQLiteConnectionPool.java
index a175662..3a1714c 100644
--- a/core/java/android/database/sqlite/SQLiteConnectionPool.java
+++ b/core/java/android/database/sqlite/SQLiteConnectionPool.java
@@ -18,9 +18,9 @@
 
 import dalvik.system.CloseGuard;
 
-import android.content.CancellationSignal;
-import android.content.OperationCanceledException;
 import android.database.sqlite.SQLiteDebug.DbStats;
+import android.os.CancellationSignal;
+import android.os.OperationCanceledException;
 import android.os.SystemClock;
 import android.util.Log;
 import android.util.PrefixPrinter;
diff --git a/core/java/android/database/sqlite/SQLiteDatabase.java b/core/java/android/database/sqlite/SQLiteDatabase.java
index 7bd0c8d..e2d44f2 100644
--- a/core/java/android/database/sqlite/SQLiteDatabase.java
+++ b/core/java/android/database/sqlite/SQLiteDatabase.java
@@ -16,16 +16,16 @@
 
 package android.database.sqlite;
 
-import android.content.CancellationSignal;
 import android.content.ContentValues;
-import android.content.OperationCanceledException;
 import android.database.Cursor;
 import android.database.DatabaseErrorHandler;
 import android.database.DatabaseUtils;
 import android.database.DefaultDatabaseErrorHandler;
 import android.database.SQLException;
 import android.database.sqlite.SQLiteDebug.DbStats;
+import android.os.CancellationSignal;
 import android.os.Looper;
+import android.os.OperationCanceledException;
 import android.text.TextUtils;
 import android.util.EventLog;
 import android.util.Log;
diff --git a/core/java/android/database/sqlite/SQLiteDirectCursorDriver.java b/core/java/android/database/sqlite/SQLiteDirectCursorDriver.java
index 294edc4..797430a 100644
--- a/core/java/android/database/sqlite/SQLiteDirectCursorDriver.java
+++ b/core/java/android/database/sqlite/SQLiteDirectCursorDriver.java
@@ -16,9 +16,9 @@
 
 package android.database.sqlite;
 
-import android.content.CancellationSignal;
 import android.database.Cursor;
 import android.database.sqlite.SQLiteDatabase.CursorFactory;
+import android.os.CancellationSignal;
 
 /**
  * A cursor driver that uses the given query directly.
diff --git a/core/java/android/database/sqlite/SQLiteProgram.java b/core/java/android/database/sqlite/SQLiteProgram.java
index e9b06c6..26e8c31 100644
--- a/core/java/android/database/sqlite/SQLiteProgram.java
+++ b/core/java/android/database/sqlite/SQLiteProgram.java
@@ -16,8 +16,8 @@
 
 package android.database.sqlite;
 
-import android.content.CancellationSignal;
 import android.database.DatabaseUtils;
+import android.os.CancellationSignal;
 
 import java.util.Arrays;
 
diff --git a/core/java/android/database/sqlite/SQLiteQuery.java b/core/java/android/database/sqlite/SQLiteQuery.java
index 30e77b5..62bcc20 100644
--- a/core/java/android/database/sqlite/SQLiteQuery.java
+++ b/core/java/android/database/sqlite/SQLiteQuery.java
@@ -16,9 +16,9 @@
 
 package android.database.sqlite;
 
-import android.content.CancellationSignal;
-import android.content.OperationCanceledException;
 import android.database.CursorWindow;
+import android.os.CancellationSignal;
+import android.os.OperationCanceledException;
 import android.util.Log;
 
 /**
diff --git a/core/java/android/database/sqlite/SQLiteQueryBuilder.java b/core/java/android/database/sqlite/SQLiteQueryBuilder.java
index 6f84b5e..91884ab 100644
--- a/core/java/android/database/sqlite/SQLiteQueryBuilder.java
+++ b/core/java/android/database/sqlite/SQLiteQueryBuilder.java
@@ -16,10 +16,10 @@
 
 package android.database.sqlite;
 
-import android.content.CancellationSignal;
-import android.content.OperationCanceledException;
 import android.database.Cursor;
 import android.database.DatabaseUtils;
+import android.os.CancellationSignal;
+import android.os.OperationCanceledException;
 import android.provider.BaseColumns;
 import android.text.TextUtils;
 import android.util.Log;
diff --git a/core/java/android/database/sqlite/SQLiteSession.java b/core/java/android/database/sqlite/SQLiteSession.java
index 9410243..beb5b3a 100644
--- a/core/java/android/database/sqlite/SQLiteSession.java
+++ b/core/java/android/database/sqlite/SQLiteSession.java
@@ -16,10 +16,10 @@
 
 package android.database.sqlite;
 
-import android.content.CancellationSignal;
-import android.content.OperationCanceledException;
 import android.database.CursorWindow;
 import android.database.DatabaseUtils;
+import android.os.CancellationSignal;
+import android.os.OperationCanceledException;
 import android.os.ParcelFileDescriptor;
 
 /**
diff --git a/core/java/android/content/CancellationSignal.java b/core/java/android/os/CancellationSignal.java
similarity index 98%
rename from core/java/android/content/CancellationSignal.java
rename to core/java/android/os/CancellationSignal.java
index dcaeeb7..dcba9b7 100644
--- a/core/java/android/content/CancellationSignal.java
+++ b/core/java/android/os/CancellationSignal.java
@@ -14,9 +14,10 @@
  * limitations under the License.
  */
 
-package android.content;
+package android.os;
 
-import android.os.RemoteException;
+import android.os.ICancellationSignal;
+import android.os.ICancellationSignal.Stub;
 
 /**
  * Provides the ability to cancel an operation in progress.
diff --git a/core/java/android/content/ICancellationSignal.aidl b/core/java/android/os/ICancellationSignal.aidl
similarity index 96%
rename from core/java/android/content/ICancellationSignal.aidl
rename to core/java/android/os/ICancellationSignal.aidl
index cf1c5d3..d92464c 100644
--- a/core/java/android/content/ICancellationSignal.aidl
+++ b/core/java/android/os/ICancellationSignal.aidl
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package android.content;
+package android.os;
 
 /**
  * @hide
diff --git a/core/java/android/content/OperationCanceledException.java b/core/java/android/os/OperationCanceledException.java
similarity index 97%
rename from core/java/android/content/OperationCanceledException.java
rename to core/java/android/os/OperationCanceledException.java
index d783a07..b0cd663 100644
--- a/core/java/android/content/OperationCanceledException.java
+++ b/core/java/android/os/OperationCanceledException.java
@@ -14,7 +14,8 @@
  * limitations under the License.
  */
 
-package android.content;
+package android.os;
+
 
 /**
  * An exception type that is thrown when an operation in progress is canceled.
diff --git a/core/java/android/preference/MultiCheckPreference.java b/core/java/android/preference/MultiCheckPreference.java
new file mode 100644
index 0000000..735f66ae
--- /dev/null
+++ b/core/java/android/preference/MultiCheckPreference.java
@@ -0,0 +1,313 @@
+/*
+ * 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.preference;
+
+import java.util.Arrays;
+
+import android.app.AlertDialog.Builder;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.res.TypedArray;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.AttributeSet;
+
+/**
+ * @hide
+ * A {@link Preference} that displays a list of entries as
+ * a dialog which allow the user to toggle each individually on and off.
+ * 
+ * @attr ref android.R.styleable#ListPreference_entries
+ * @attr ref android.R.styleable#ListPreference_entryValues
+ */
+public class MultiCheckPreference extends DialogPreference {
+    private CharSequence[] mEntries;
+    private String[] mEntryValues;
+    private boolean[] mSetValues;
+    private boolean[] mOrigValues;
+    private String mSummary;
+    
+    public MultiCheckPreference(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        
+        TypedArray a = context.obtainStyledAttributes(attrs,
+                com.android.internal.R.styleable.ListPreference, 0, 0);
+        mEntries = a.getTextArray(com.android.internal.R.styleable.ListPreference_entries);
+        if (mEntries != null) {
+            setEntries(mEntries);
+        }
+        setEntryValuesCS(a.getTextArray(
+                com.android.internal.R.styleable.ListPreference_entryValues));
+        a.recycle();
+
+        /* Retrieve the Preference summary attribute since it's private
+         * in the Preference class.
+         */
+        a = context.obtainStyledAttributes(attrs,
+                com.android.internal.R.styleable.Preference, 0, 0);
+        mSummary = a.getString(com.android.internal.R.styleable.Preference_summary);
+        a.recycle();
+    }
+
+    public MultiCheckPreference(Context context) {
+        this(context, null);
+    }
+
+    /**
+     * Sets the human-readable entries to be shown in the list. This will be
+     * shown in subsequent dialogs.
+     * <p>
+     * Each entry must have a corresponding index in
+     * {@link #setEntryValues(CharSequence[])}.
+     * 
+     * @param entries The entries.
+     * @see #setEntryValues(CharSequence[])
+     */
+    public void setEntries(CharSequence[] entries) {
+        mEntries = entries;
+        mSetValues = new boolean[entries.length];
+        mOrigValues = new boolean[entries.length];
+    }
+    
+    /**
+     * @see #setEntries(CharSequence[])
+     * @param entriesResId The entries array as a resource.
+     */
+    public void setEntries(int entriesResId) {
+        setEntries(getContext().getResources().getTextArray(entriesResId));
+    }
+    
+    /**
+     * The list of entries to be shown in the list in subsequent dialogs.
+     * 
+     * @return The list as an array.
+     */
+    public CharSequence[] getEntries() {
+        return mEntries;
+    }
+    
+    /**
+     * The array to find the value to save for a preference when an entry from
+     * entries is selected. If a user clicks on the second item in entries, the
+     * second item in this array will be saved to the preference.
+     * 
+     * @param entryValues The array to be used as values to save for the preference.
+     */
+    public void setEntryValues(String[] entryValues) {
+        mEntryValues = entryValues;
+        Arrays.fill(mSetValues, false);
+        Arrays.fill(mOrigValues, false);
+    }
+
+    /**
+     * @see #setEntryValues(CharSequence[])
+     * @param entryValuesResId The entry values array as a resource.
+     */
+    public void setEntryValues(int entryValuesResId) {
+        setEntryValuesCS(getContext().getResources().getTextArray(entryValuesResId));
+    }
+
+    private void setEntryValuesCS(CharSequence[] values) {
+        setValues(null);
+        if (values != null) {
+            mEntryValues = new String[values.length];
+            for (int i=0; i<values.length; i++) {
+                mEntryValues[i] = values[i].toString();
+            }
+        }
+    }
+
+    /**
+     * Returns the array of values to be saved for the preference.
+     * 
+     * @return The array of values.
+     */
+    public CharSequence[] getEntryValues() {
+        return mEntryValues;
+    }
+
+    /**
+     * Sets the current values.
+     */
+    public void setValues(boolean[] values) {
+        if (mSetValues != null) {
+            Arrays.fill(mSetValues, false);
+            Arrays.fill(mOrigValues, false);
+            if (values != null) {
+                System.arraycopy(values, 0, mSetValues, 0,
+                        values.length < mSetValues.length ? values.length : mSetValues.length);
+            }
+        }
+    }
+
+    /**
+     * Returns the summary of this ListPreference. If the summary
+     * has a {@linkplain java.lang.String#format String formatting}
+     * marker in it (i.e. "%s" or "%1$s"), then the current entry
+     * value will be substituted in its place.
+     *
+     * @return the summary with appropriate string substitution
+     */
+    @Override
+    public CharSequence getSummary() {
+        if (mSummary == null) {
+            return super.getSummary();
+        } else {
+            return mSummary;
+        }
+    }
+
+    /**
+     * Sets the summary for this Preference with a CharSequence.
+     * If the summary has a
+     * {@linkplain java.lang.String#format String formatting}
+     * marker in it (i.e. "%s" or "%1$s"), then the current entry
+     * value will be substituted in its place when it's retrieved.
+     *
+     * @param summary The summary for the preference.
+     */
+    @Override
+    public void setSummary(CharSequence summary) {
+        super.setSummary(summary);
+        if (summary == null && mSummary != null) {
+            mSummary = null;
+        } else if (summary != null && !summary.equals(mSummary)) {
+            mSummary = summary.toString();
+        }
+    }
+    
+    /**
+     * Returns the currently selected values.
+     */
+    public boolean[] getValues() {
+        return mSetValues;
+    }
+    
+    /**
+     * Returns the index of the given value (in the entry values array).
+     * 
+     * @param value The value whose index should be returned.
+     * @return The index of the value, or -1 if not found.
+     */
+    public int findIndexOfValue(String value) {
+        if (value != null && mEntryValues != null) {
+            for (int i = mEntryValues.length - 1; i >= 0; i--) {
+                if (mEntryValues[i].equals(value)) {
+                    return i;
+                }
+            }
+        }
+        return -1;
+    }
+    
+    @Override
+    protected void onPrepareDialogBuilder(Builder builder) {
+        super.onPrepareDialogBuilder(builder);
+        
+        if (mEntries == null || mEntryValues == null) {
+            throw new IllegalStateException(
+                    "ListPreference requires an entries array and an entryValues array.");
+        }
+
+        mOrigValues = Arrays.copyOf(mSetValues, mSetValues.length);
+        builder.setMultiChoiceItems(mEntries, mSetValues,
+                new DialogInterface.OnMultiChoiceClickListener() {
+                    @Override
+                    public void onClick(DialogInterface dialog, int which, boolean isChecked) {
+                        mSetValues[which] = isChecked;
+                    }
+        });
+    }
+
+    @Override
+    protected void onDialogClosed(boolean positiveResult) {
+        super.onDialogClosed(positiveResult);
+
+        if (positiveResult) {
+            if (callChangeListener(getValues())) {
+                return;
+            }
+        }
+        System.arraycopy(mOrigValues, 0, mSetValues, 0, mSetValues.length);
+    }
+
+    @Override
+    protected Object onGetDefaultValue(TypedArray a, int index) {
+        return a.getString(index);
+    }
+
+    @Override
+    protected void onSetInitialValue(boolean restoreValue, Object defaultValue) {
+    }
+
+    @Override
+    protected Parcelable onSaveInstanceState() {
+        final Parcelable superState = super.onSaveInstanceState();
+        if (isPersistent()) {
+            // No need to save instance state since it's persistent
+            return superState;
+        }
+        
+        final SavedState myState = new SavedState(superState);
+        myState.values = getValues();
+        return myState;
+    }
+
+    @Override
+    protected void onRestoreInstanceState(Parcelable state) {
+        if (state == null || !state.getClass().equals(SavedState.class)) {
+            // Didn't save state for us in onSaveInstanceState
+            super.onRestoreInstanceState(state);
+            return;
+        }
+         
+        SavedState myState = (SavedState) state;
+        super.onRestoreInstanceState(myState.getSuperState());
+        setValues(myState.values);
+    }
+    
+    private static class SavedState extends BaseSavedState {
+        boolean[] values;
+        
+        public SavedState(Parcel source) {
+            super(source);
+            values = source.createBooleanArray();
+        }
+
+        @Override
+        public void writeToParcel(Parcel dest, int flags) {
+            super.writeToParcel(dest, flags);
+            dest.writeBooleanArray(values);
+        }
+
+        public SavedState(Parcelable superState) {
+            super(superState);
+        }
+
+        public static final Parcelable.Creator<SavedState> CREATOR =
+                new Parcelable.Creator<SavedState>() {
+            public SavedState createFromParcel(Parcel in) {
+                return new SavedState(in);
+            }
+
+            public SavedState[] newArray(int size) {
+                return new SavedState[size];
+            }
+        };
+    }
+    
+}
diff --git a/core/java/android/view/AccessibilityInteractionController.java b/core/java/android/view/AccessibilityInteractionController.java
index 6387148..881594d 100644
--- a/core/java/android/view/AccessibilityInteractionController.java
+++ b/core/java/android/view/AccessibilityInteractionController.java
@@ -126,6 +126,16 @@
         }
     }
 
+    private boolean isShown(View view) {
+        // The first two checks are made also made by isShown() which
+        // however traverses the tree up to the parent to catch that.
+        // Therefore, we do some fail fast check to minimize the up
+        // tree traversal.
+        return (view.mAttachInfo != null
+                && view.mAttachInfo.mWindowVisibility == View.VISIBLE
+                && view.isShown());
+    }
+
     public void findAccessibilityNodeInfoByAccessibilityIdClientThread(
             long accessibilityNodeId, int interactionId,
             IAccessibilityInteractionConnectionCallback callback, int flags, int interrogatingPid,
@@ -174,7 +184,7 @@
             } else {
                 root = findViewByAccessibilityId(accessibilityViewId);
             }
-            if (root != null && root.isDisplayedOnScreen()) {
+            if (root != null && isShown(root)) {
                 mPrefetcher.prefetchAccessibilityNodeInfos(root, virtualDescendantId, flags, infos);
             }
         } finally {
@@ -236,7 +246,7 @@
             }
             if (root != null) {
                 View target = root.findViewById(viewId);
-                if (target != null && target.isDisplayedOnScreen()) {
+                if (target != null && isShown(target)) {
                     info = target.createAccessibilityNodeInfo();
                 }
             }
@@ -298,7 +308,7 @@
             } else {
                 root = mViewRootImpl.mView;
             }
-            if (root != null && root.isDisplayedOnScreen()) {
+            if (root != null && isShown(root)) {
                 AccessibilityNodeProvider provider = root.getAccessibilityNodeProvider();
                 if (provider != null) {
                     infos = provider.findAccessibilityNodeInfosByText(text,
@@ -315,7 +325,7 @@
                         final int viewCount = foundViews.size();
                         for (int i = 0; i < viewCount; i++) {
                             View foundView = foundViews.get(i);
-                            if (foundView.isDisplayedOnScreen()) {
+                            if (isShown(foundView)) {
                                 provider = foundView.getAccessibilityNodeProvider();
                                 if (provider != null) {
                                     List<AccessibilityNodeInfo> infosFromProvider =
@@ -390,7 +400,7 @@
             } else {
                 root = mViewRootImpl.mView;
             }
-            if (root != null && root.isDisplayedOnScreen()) {
+            if (root != null && isShown(root)) {
                 switch (focusType) {
                     case AccessibilityNodeInfo.FOCUS_ACCESSIBILITY: {
                         View host = mViewRootImpl.mAccessibilityFocusedHost;
@@ -411,7 +421,7 @@
                     case AccessibilityNodeInfo.FOCUS_INPUT: {
                         // Input focus cannot go to virtual views.
                         View target = root.findFocus();
-                        if (target != null && target.isDisplayedOnScreen()) {
+                        if (target != null && isShown(target)) {
                             focused = target.createAccessibilityNodeInfo();
                         }
                     } break;
@@ -477,7 +487,7 @@
             } else {
                 root = mViewRootImpl.mView;
             }
-            if (root != null && root.isDisplayedOnScreen()) {
+            if (root != null && isShown(root)) {
                 if ((direction & View.FOCUS_ACCESSIBILITY) ==  View.FOCUS_ACCESSIBILITY) {
                     AccessibilityNodeProvider provider = root.getAccessibilityNodeProvider();
                     if (provider != null) {
@@ -565,7 +575,7 @@
             } else {
                 target = mViewRootImpl.mView;
             }
-            if (target != null && target.isDisplayedOnScreen()) {
+            if (target != null && isShown(target)) {
                 AccessibilityNodeProvider provider = target.getAccessibilityNodeProvider();
                 if (provider != null) {
                     succeeded = provider.performAction(virtualDescendantId, action,
@@ -590,7 +600,7 @@
             return null;
         }
         View foundView = root.findViewByAccessibilityId(accessibilityId);
-        if (foundView != null && !foundView.isDisplayedOnScreen()) {
+        if (foundView != null && !isShown(foundView)) {
             return null;
         }
         return foundView;
@@ -670,7 +680,7 @@
                         }
                         View child = children.getChildAt(i);
                         if (child.getAccessibilityViewId() != current.getAccessibilityViewId()
-                                &&  child.isDisplayedOnScreen()) {
+                                &&  isShown(child)) {
                             AccessibilityNodeInfo info = null;
                             AccessibilityNodeProvider provider = child.getAccessibilityNodeProvider();
                             if (provider == null) {
@@ -706,7 +716,7 @@
                         return;
                     }
                     View child = children.getChildAt(i);
-                    if (child.isDisplayedOnScreen()) {
+                    if (isShown(child)) {
                         AccessibilityNodeProvider provider = child.getAccessibilityNodeProvider();
                         if (provider == null) {
                             AccessibilityNodeInfo info = child.createAccessibilityNodeInfo();
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 0e8723f..5032fe0 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -4666,6 +4666,51 @@
     }
 
     /**
+     * Gets the location of this view in screen coordintates.
+     *
+     * @param outRect The output location
+     */
+    private void getBoundsOnScreen(Rect outRect) {
+        if (mAttachInfo == null) {
+            return;
+        }
+
+        RectF position = mAttachInfo.mTmpTransformRect;
+        position.setEmpty();
+
+        if (!hasIdentityMatrix()) {
+            getMatrix().mapRect(position);
+        }
+
+        position.offset(mLeft, mRight);
+
+        ViewParent parent = mParent;
+        while (parent instanceof View) {
+            View parentView = (View) parent;
+
+            position.offset(-parentView.mScrollX, -parentView.mScrollY);
+
+            if (!parentView.hasIdentityMatrix()) {
+                parentView.getMatrix().mapRect(position);
+            }
+
+            position.offset(parentView.mLeft, parentView.mTop);
+
+            parent = parentView.mParent;
+        }
+
+        if (parent instanceof ViewRootImpl) {
+            ViewRootImpl viewRootImpl = (ViewRootImpl) parent;
+            position.offset(0, -viewRootImpl.mCurScrollY);
+        }
+
+        position.offset(mAttachInfo.mWindowLeft, mAttachInfo.mWindowTop);
+
+        outRect.set((int) (position.left + 0.5f), (int) (position.top + 0.5f),
+                (int) (position.right + 0.5f), (int) (position.bottom + 0.5f));
+    }
+
+    /**
      * @see #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
      *
      * Note: Called from the default {@link AccessibilityDelegate}.
@@ -4675,8 +4720,7 @@
         getDrawingRect(bounds);
         info.setBoundsInParent(bounds);
 
-        getGlobalVisibleRect(bounds);
-        bounds.offset(mAttachInfo.mWindowLeft, mAttachInfo.mWindowTop);
+        getBoundsOnScreen(bounds);
         info.setBoundsInScreen(bounds);
 
         if ((mPrivateFlags & IS_ROOT_NAMESPACE) == 0) {
@@ -4686,6 +4730,8 @@
             }
         }
 
+        info.setVisibleToUser(isVisibleToUser());
+
         info.setPackageName(mContext.getPackageName());
         info.setClassName(View.class.getName());
         info.setContentDescription(getContentDescription());
@@ -4736,11 +4782,13 @@
     }
 
     /**
-     * Computes whether this view is visible on the screen.
+     * Computes whether this view is visible to the user. Such a view is
+     * attached, visible, all its predecessors are visible, it is not clipped
+     * entirely by its predecessors, and has an alpha greater than zero.
      *
      * @return Whether the view is visible on the screen.
      */
-    boolean isDisplayedOnScreen() {
+    private boolean isVisibleToUser() {
         // The first two checks are made also made by isShown() which
         // however traverses the tree up to the parent to catch that.
         // Therefore, we do some fail fast check to minimize the up
@@ -6395,9 +6443,9 @@
     boolean includeForAccessibility() {
         if (mAttachInfo != null) {
             if (!mAttachInfo.mIncludeNotImportantViews) {
-                return isImportantForAccessibility() && isDisplayedOnScreen();
+                return isImportantForAccessibility();
             } else {
-                return isDisplayedOnScreen();
+                return true;
             }
         }
         return false;
@@ -6684,6 +6732,7 @@
      * @hide
      */
     public void dispatchStartTemporaryDetach() {
+        clearAccessibilityFocus();
         onStartTemporaryDetach();
     }
 
@@ -11298,7 +11347,6 @@
         resetResolvedLayoutDirection();
         resetResolvedTextAlignment();
         resetAccessibilityStateChanged();
-        clearAccessibilityFocus();
     }
 
     /**
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 29613d5..acfca26 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -3586,6 +3586,8 @@
             clearChildFocus = true;
         }
 
+        view.clearAccessibilityFocus();
+
         cancelTouchTarget(view);
         cancelHoverTarget(view);
 
@@ -3669,6 +3671,8 @@
                 clearChildFocus = view;
             }
 
+            view.clearAccessibilityFocus();
+
             cancelTouchTarget(view);
             cancelHoverTarget(view);
 
@@ -3742,6 +3746,8 @@
                 clearChildFocus = view;
             }
 
+            view.clearAccessibilityFocus();
+
             cancelTouchTarget(view);
             cancelHoverTarget(view);
 
@@ -3790,6 +3796,8 @@
             child.clearFocus();
         }
 
+        child.clearAccessibilityFocus();
+
         cancelTouchTarget(child);
         cancelHoverTarget(child);
 
diff --git a/core/java/android/view/WindowOrientationListener.java b/core/java/android/view/WindowOrientationListener.java
index c28b220..4c34dd4 100755
--- a/core/java/android/view/WindowOrientationListener.java
+++ b/core/java/android/view/WindowOrientationListener.java
@@ -21,6 +21,7 @@
 import android.hardware.SensorEvent;
 import android.hardware.SensorEventListener;
 import android.hardware.SensorManager;
+import android.os.SystemProperties;
 import android.util.FloatMath;
 import android.util.Log;
 import android.util.Slog;
@@ -34,20 +35,15 @@
  * "App/Activity/Screen Orientation" to ensure that all orientation
  * modes still work correctly.
  *
- * You can also visualize the behavior of the WindowOrientationListener by
- * enabling the window orientation listener log using the Development Settings
- * in the Dev Tools application (Development.apk)
- * and running frameworks/base/tools/orientationplot/orientationplot.py.
- *
- * More information about how to tune this algorithm in
- * frameworks/base/tools/orientationplot/README.txt.
+ * You can also visualize the behavior of the WindowOrientationListener.
+ * Refer to frameworks/base/tools/orientationplot/README.txt for details.
  *
  * @hide
  */
 public abstract class WindowOrientationListener {
     private static final String TAG = "WindowOrientationListener";
-    private static final boolean DEBUG = false;
-    private static final boolean localLOGV = DEBUG || false;
+    private static final boolean LOG = SystemProperties.getBoolean(
+            "debug.orientation.log", false);
 
     private static final boolean USE_GRAVITY_SENSOR = false;
 
@@ -56,7 +52,6 @@
     private int mRate;
     private Sensor mSensor;
     private SensorEventListenerImpl mSensorEventListener;
-    boolean mLogEnabled;
     int mCurrentRotation = -1;
 
     /**
@@ -100,7 +95,9 @@
             return;
         }
         if (mEnabled == false) {
-            if (localLOGV) Log.d(TAG, "WindowOrientationListener enabled");
+            if (LOG) {
+                Log.d(TAG, "WindowOrientationListener enabled");
+            }
             mSensorManager.registerListener(mSensorEventListener, mSensor, mRate);
             mEnabled = true;
         }
@@ -115,7 +112,9 @@
             return;
         }
         if (mEnabled == true) {
-            if (localLOGV) Log.d(TAG, "WindowOrientationListener disabled");
+            if (LOG) {
+                Log.d(TAG, "WindowOrientationListener disabled");
+            }
             mSensorManager.unregisterListener(mSensorEventListener);
             mEnabled = false;
         }
@@ -165,16 +164,6 @@
     public abstract void onProposedRotationChanged(int rotation);
 
     /**
-     * Enables or disables the window orientation listener logging for use with
-     * the orientationplot.py tool.
-     * Logging is usually enabled via Development Settings.  (See class comments.)
-     * @param enable True to enable logging.
-     */
-    public void setLogEnabled(boolean enable) {
-        mLogEnabled = enable;
-    }
-
-    /**
      * This class filters the raw accelerometer data and tries to detect actual changes in
      * orientation. This is a very ill-defined problem so there are a lot of tweakable parameters,
      * but here's the outline:
@@ -238,11 +227,16 @@
         // can change.
         private static final long PROPOSAL_MIN_TIME_SINCE_FLAT_ENDED_NANOS = 500 * NANOS_PER_MS;
 
-        // The mininum amount of time that must have elapsed since the device stopped
+        // The minimum amount of time that must have elapsed since the device stopped
         // swinging (time since device appeared to be in the process of being put down
         // or put away into a pocket) before the proposed rotation can change.
         private static final long PROPOSAL_MIN_TIME_SINCE_SWING_ENDED_NANOS = 300 * NANOS_PER_MS;
 
+        // The minimum amount of time that must have elapsed since the device stopped
+        // undergoing external acceleration before the proposed rotation can change.
+        private static final long PROPOSAL_MIN_TIME_SINCE_ACCELERATION_ENDED_NANOS =
+                500 * NANOS_PER_MS;
+
         // If the tilt angle remains greater than the specified angle for a minimum of
         // the specified time, then the device is deemed to be lying flat
         // (just chillin' on a table).
@@ -300,10 +294,15 @@
         // singularities in the tilt and orientation calculations.
         //
         // In both cases, we postpone choosing an orientation.
+        //
+        // However, we need to tolerate some acceleration because the angular momentum
+        // of turning the device can skew the observed acceleration for a short period of time.
+        private static final float NEAR_ZERO_MAGNITUDE = 1; // m/s^2
+        private static final float ACCELERATION_TOLERANCE = 4; // m/s^2
         private static final float MIN_ACCELERATION_MAGNITUDE =
-                SensorManager.STANDARD_GRAVITY * 0.3f;
+                SensorManager.STANDARD_GRAVITY - ACCELERATION_TOLERANCE;
         private static final float MAX_ACCELERATION_MAGNITUDE =
-            SensorManager.STANDARD_GRAVITY * 1.25f;
+            SensorManager.STANDARD_GRAVITY + ACCELERATION_TOLERANCE;
 
         // Maximum absolute tilt angle at which to consider orientation data.  Beyond this (i.e.
         // when screen is facing the sky or ground), we completely ignore orientation data.
@@ -353,6 +352,9 @@
         // Timestamp when the device last appeared to be swinging.
         private long mSwingTimestampNanos;
 
+        // Timestamp when the device last appeared to be undergoing external acceleration.
+        private long mAccelerationTimestampNanos;
+
         // History of observed tilt angles.
         private static final int TILT_HISTORY_SIZE = 40;
         private float[] mTiltHistory = new float[TILT_HISTORY_SIZE];
@@ -374,15 +376,13 @@
 
         @Override
         public void onSensorChanged(SensorEvent event) {
-            final boolean log = mOrientationListener.mLogEnabled;
-
             // The vector given in the SensorEvent points straight up (towards the sky) under ideal
             // conditions (the phone is not accelerating).  I'll call this up vector elsewhere.
             float x = event.values[ACCELEROMETER_DATA_X];
             float y = event.values[ACCELEROMETER_DATA_Y];
             float z = event.values[ACCELEROMETER_DATA_Z];
 
-            if (log) {
+            if (LOG) {
                 Slog.v(TAG, "Raw acceleration vector: "
                         + "x=" + x + ", y=" + y + ", z=" + z
                         + ", magnitude=" + FloatMath.sqrt(x * x + y * y + z * z));
@@ -399,7 +399,7 @@
             if (now < then
                     || now > then + MAX_FILTER_DELTA_TIME_NANOS
                     || (x == 0 && y == 0 && z == 0)) {
-                if (log) {
+                if (LOG) {
                     Slog.v(TAG, "Resetting orientation listener.");
                 }
                 reset();
@@ -409,7 +409,7 @@
                 x = alpha * (x - mLastFilteredX) + mLastFilteredX;
                 y = alpha * (y - mLastFilteredY) + mLastFilteredY;
                 z = alpha * (z - mLastFilteredZ) + mLastFilteredZ;
-                if (log) {
+                if (LOG) {
                     Slog.v(TAG, "Filtered acceleration vector: "
                             + "x=" + x + ", y=" + y + ", z=" + z
                             + ", magnitude=" + FloatMath.sqrt(x * x + y * y + z * z));
@@ -421,18 +421,24 @@
             mLastFilteredY = y;
             mLastFilteredZ = z;
 
+            boolean isAccelerating = false;
             boolean isFlat = false;
             boolean isSwinging = false;
             if (!skipSample) {
                 // Calculate the magnitude of the acceleration vector.
                 final float magnitude = FloatMath.sqrt(x * x + y * y + z * z);
-                if (magnitude < MIN_ACCELERATION_MAGNITUDE
-                        || magnitude > MAX_ACCELERATION_MAGNITUDE) {
-                    if (log) {
-                        Slog.v(TAG, "Ignoring sensor data, magnitude out of range.");
+                if (magnitude < NEAR_ZERO_MAGNITUDE) {
+                    if (LOG) {
+                        Slog.v(TAG, "Ignoring sensor data, magnitude too close to zero.");
                     }
                     clearPredictedRotation();
                 } else {
+                    // Determine whether the device appears to be undergoing external acceleration.
+                    if (isAccelerating(magnitude)) {
+                        isAccelerating = true;
+                        mAccelerationTimestampNanos = now;
+                    }
+
                     // Calculate the tilt angle.
                     // This is the angle between the up vector and the x-y plane (the plane of
                     // the screen) in a range of [-90, 90] degrees.
@@ -441,6 +447,7 @@
                     //    90 degrees: screen horizontal and facing the sky (on table)
                     final int tiltAngle = (int) Math.round(
                             Math.asin(z / magnitude) * RADIANS_TO_DEGREES);
+                    addTiltHistoryEntry(now, tiltAngle);
 
                     // Determine whether the device appears to be flat or swinging.
                     if (isFlat(now)) {
@@ -451,12 +458,11 @@
                         isSwinging = true;
                         mSwingTimestampNanos = now;
                     }
-                    addTiltHistoryEntry(now, tiltAngle);
 
                     // If the tilt angle is too close to horizontal then we cannot determine
                     // the orientation angle of the screen.
                     if (Math.abs(tiltAngle) > MAX_TILT) {
-                        if (log) {
+                        if (LOG) {
                             Slog.v(TAG, "Ignoring sensor data, tilt angle too high: "
                                     + "tiltAngle=" + tiltAngle);
                         }
@@ -483,7 +489,7 @@
                                 && isOrientationAngleAcceptable(nearestRotation,
                                         orientationAngle)) {
                             updatePredictedRotation(now, nearestRotation);
-                            if (log) {
+                            if (LOG) {
                                 Slog.v(TAG, "Predicted: "
                                         + "tiltAngle=" + tiltAngle
                                         + ", orientationAngle=" + orientationAngle
@@ -493,7 +499,7 @@
                                                         * 0.000001f));
                             }
                         } else {
-                            if (log) {
+                            if (LOG) {
                                 Slog.v(TAG, "Ignoring sensor data, no predicted rotation: "
                                         + "tiltAngle=" + tiltAngle
                                         + ", orientationAngle=" + orientationAngle);
@@ -511,15 +517,18 @@
             }
 
             // Write final statistics about where we are in the orientation detection process.
-            if (log) {
+            if (LOG) {
                 Slog.v(TAG, "Result: currentRotation=" + mOrientationListener.mCurrentRotation
                         + ", proposedRotation=" + mProposedRotation
                         + ", predictedRotation=" + mPredictedRotation
                         + ", timeDeltaMS=" + timeDeltaMS
+                        + ", isAccelerating=" + isAccelerating
                         + ", isFlat=" + isFlat
                         + ", isSwinging=" + isSwinging
                         + ", timeUntilSettledMS=" + remainingMS(now,
                                 mPredictedRotationTimestampNanos + PROPOSAL_SETTLE_TIME_NANOS)
+                        + ", timeUntilAccelerationDelayExpiredMS=" + remainingMS(now,
+                                mAccelerationTimestampNanos + PROPOSAL_MIN_TIME_SINCE_ACCELERATION_ENDED_NANOS)
                         + ", timeUntilFlatDelayExpiredMS=" + remainingMS(now,
                                 mFlatTimestampNanos + PROPOSAL_MIN_TIME_SINCE_FLAT_ENDED_NANOS)
                         + ", timeUntilSwingDelayExpiredMS=" + remainingMS(now,
@@ -528,7 +537,7 @@
 
             // Tell the listener.
             if (mProposedRotation != oldProposedRotation && mProposedRotation >= 0) {
-                if (log) {
+                if (LOG) {
                     Slog.v(TAG, "Proposed rotation changed!  proposedRotation=" + mProposedRotation
                             + ", oldProposedRotation=" + oldProposedRotation);
                 }
@@ -618,6 +627,12 @@
                 return false;
             }
 
+            // The last acceleration state must have been sufficiently long ago.
+            if (now < mAccelerationTimestampNanos
+                    + PROPOSAL_MIN_TIME_SINCE_ACCELERATION_ENDED_NANOS) {
+                return false;
+            }
+
             // Looks good!
             return true;
         }
@@ -627,6 +642,7 @@
             mProposedRotation = -1;
             mFlatTimestampNanos = Long.MIN_VALUE;
             mSwingTimestampNanos = Long.MIN_VALUE;
+            mAccelerationTimestampNanos = Long.MIN_VALUE;
             clearPredictedRotation();
             clearTiltHistory();
         }
@@ -643,6 +659,11 @@
             }
         }
 
+        private boolean isAccelerating(float magnitude) {
+            return magnitude < MIN_ACCELERATION_MAGNITUDE
+                    || magnitude > MAX_ACCELERATION_MAGNITUDE;
+        }
+
         private void clearTiltHistory() {
             mTiltHistoryTimestampNanos[0] = Long.MIN_VALUE;
             mTiltHistoryIndex = 1;
diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
index fef24e2..6b14ba5 100644
--- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
@@ -287,6 +287,8 @@
 
     private static final int PROPERTY_ACCESSIBILITY_FOCUSED = 0x00000400;
 
+    private static final int PROPERTY_VISIBLE_TO_USER = 0x00000800;
+
     /**
      * Bits that provide the id of a virtual descendant of a view.
      */
@@ -910,6 +912,31 @@
     }
 
     /**
+     * Sets whether this node is visible to the user.
+     *
+     * @return Whether the node is visible to the user.
+     */
+    public boolean isVisibleToUser() {
+        return getBooleanProperty(PROPERTY_VISIBLE_TO_USER);
+    }
+
+    /**
+     * Sets whether this node is visible to the user.
+     * <p>
+     *   <strong>Note:</strong> Cannot be called from an
+     *   {@link android.accessibilityservice.AccessibilityService}.
+     *   This class is made immutable before being delivered to an AccessibilityService.
+     * </p>
+     *
+     * @param visibleToUser Whether the node is visible to the user.
+     *
+     * @throws IllegalStateException If called from an AccessibilityService.
+     */
+    public void setVisibleToUser(boolean visibleToUser) {
+        setBooleanProperty(PROPERTY_VISIBLE_TO_USER, visibleToUser);
+    }
+
+    /**
      * Gets whether this node is accessibility focused.
      *
      * @return True if the node is accessibility focused.
diff --git a/core/java/android/view/inputmethod/InputMethodSubtype.java b/core/java/android/view/inputmethod/InputMethodSubtype.java
index c22750e..b7c94a3 100644
--- a/core/java/android/view/inputmethod/InputMethodSubtype.java
+++ b/core/java/android/view/inputmethod/InputMethodSubtype.java
@@ -58,7 +58,7 @@
     private final String mSubtypeLocale;
     private final String mSubtypeMode;
     private final String mSubtypeExtraValue;
-    private HashMap<String, String> mExtraValueHashMapCache;
+    private volatile HashMap<String, String> mExtraValueHashMapCache;
 
     /**
      * Constructor.
@@ -237,18 +237,22 @@
 
     private HashMap<String, String> getExtraValueHashMap() {
         if (mExtraValueHashMapCache == null) {
-            mExtraValueHashMapCache = new HashMap<String, String>();
-            final String[] pairs = mSubtypeExtraValue.split(EXTRA_VALUE_PAIR_SEPARATOR);
-            final int N = pairs.length;
-            for (int i = 0; i < N; ++i) {
-                final String[] pair = pairs[i].split(EXTRA_VALUE_KEY_VALUE_SEPARATOR);
-                if (pair.length == 1) {
-                    mExtraValueHashMapCache.put(pair[0], null);
-                } else if (pair.length > 1) {
-                    if (pair.length > 2) {
-                        Slog.w(TAG, "ExtraValue has two or more '='s");
+            synchronized(this) {
+                if (mExtraValueHashMapCache == null) {
+                    mExtraValueHashMapCache = new HashMap<String, String>();
+                    final String[] pairs = mSubtypeExtraValue.split(EXTRA_VALUE_PAIR_SEPARATOR);
+                    final int N = pairs.length;
+                    for (int i = 0; i < N; ++i) {
+                        final String[] pair = pairs[i].split(EXTRA_VALUE_KEY_VALUE_SEPARATOR);
+                        if (pair.length == 1) {
+                            mExtraValueHashMapCache.put(pair[0], null);
+                        } else if (pair.length > 1) {
+                            if (pair.length > 2) {
+                                Slog.w(TAG, "ExtraValue has two or more '='s");
+                            }
+                            mExtraValueHashMapCache.put(pair[0], pair[1]);
+                        }
                     }
-                    mExtraValueHashMapCache.put(pair[0], pair[1]);
                 }
             }
         }
diff --git a/core/java/android/webkit/WebHistoryItem.java b/core/java/android/webkit/WebHistoryItem.java
index ccf3d6b..788d05c 100644
--- a/core/java/android/webkit/WebHistoryItem.java
+++ b/core/java/android/webkit/WebHistoryItem.java
@@ -32,12 +32,8 @@
     private static int sNextId = 0;
     // Unique identifier.
     private final int mId;
-    // The title of this item's document.
-    private String mTitle;
-    // The base url of this item.
-    private String mUrl;
-    // The original requested url of this item.
-    private String mOriginalUrl;
+    // A point to a native WebHistoryItem instance which contains the actual data
+    private int mNativeBridge;
     // The favicon for this item.
     private Bitmap mFavicon;
     // The pre-flattened data used for saving the state.
@@ -55,10 +51,19 @@
      * Basic constructor that assigns a unique id to the item. Called by JNI
      * only.
      */
-    private WebHistoryItem() {
+    private WebHistoryItem(int nativeBridge) {
         synchronized (WebHistoryItem.class) {
             mId = sNextId++;
         }
+        mNativeBridge = nativeBridge;
+        nativeRef(mNativeBridge);
+    }
+
+    protected void finalize() throws Throwable {
+        if (mNativeBridge != 0) {
+            nativeUnref(mNativeBridge);
+            mNativeBridge = 0;
+        }
     }
 
     /**
@@ -66,7 +71,6 @@
      * @param data The pre-flattened data coming from restoreState.
      */
     /*package*/ WebHistoryItem(byte[] data) {
-        mUrl = null; // This will be updated natively
         mFlattenedData = data;
         synchronized (WebHistoryItem.class) {
             mId = sNextId++;
@@ -78,12 +82,14 @@
      * @param item The history item to clone.
      */
     private WebHistoryItem(WebHistoryItem item) {
-        mUrl = item.mUrl;
-        mTitle = item.mTitle;
         mFlattenedData = item.mFlattenedData;
-        mFavicon = item.mFavicon;
         mId = item.mId;
-}
+        mFavicon = item.mFavicon;
+        mNativeBridge = item.mNativeBridge;
+        if (mNativeBridge != 0) {
+            nativeRef(mNativeBridge);
+        }
+    }
 
     /**
      * Return an identifier for this history item. If an item is a copy of
@@ -106,7 +112,8 @@
      * to synchronize this method.
      */
     public String getUrl() {
-        return mUrl;
+        if (mNativeBridge == 0) return null;
+        return nativeGetUrl(mNativeBridge);
     }
 
     /**
@@ -116,7 +123,8 @@
      * @return The original url of this history item.
      */
     public String getOriginalUrl() {
-        return mOriginalUrl;
+        if (mNativeBridge == 0) return null;
+        return nativeGetOriginalUrl(mNativeBridge);
     }
     
     /**
@@ -126,7 +134,8 @@
      * to synchronize this method.
      */
     public String getTitle() {
-        return mTitle;
+        if (mNativeBridge == 0) return null;
+        return nativeGetTitle(mNativeBridge);
     }
 
     /**
@@ -136,6 +145,9 @@
      * to synchronize this method.
      */
     public Bitmap getFavicon() {
+        if (mFavicon == null && mNativeBridge != 0) {
+            mFavicon = nativeGetFavicon(mNativeBridge);
+        }
         return mFavicon;
     }
 
@@ -156,7 +168,7 @@
         }
 
         try {
-            URL url = new URL(mOriginalUrl);
+            URL url = new URL(getOriginalUrl());
             mTouchIconUrlServerDefault = new URL(url.getProtocol(), url.getHost(), url.getPort(),
                     "/apple-touch-icon.png").toString();
         } catch (MalformedURLException e) {
@@ -214,6 +226,9 @@
      * to synchronize this method.
      */
     /*package*/ byte[] getFlattenedData() {
+        if (mNativeBridge != 0) {
+            return nativeGetFlattenedData(mNativeBridge);
+        }
         return mFlattenedData;
     }
 
@@ -223,7 +238,8 @@
      * to synchronize this method.
      */
     /*package*/ void inflate(int nativeFrame) {
-        inflate(nativeFrame, mFlattenedData);
+        mNativeBridge = inflate(nativeFrame, mFlattenedData);
+        mFlattenedData = null;
     }
 
     /**
@@ -235,15 +251,13 @@
 
     /* Natively inflate this item, this method is called in the WebCore thread.
      */
-    private native void inflate(int nativeFrame, byte[] data);
+    private native int inflate(int nativeFrame, byte[] data);
+    private native void nativeRef(int nptr);
+    private native void nativeUnref(int nptr);
+    private native String nativeGetTitle(int nptr);
+    private native String nativeGetUrl(int nptr);
+    private native String nativeGetOriginalUrl(int nptr);
+    private native byte[] nativeGetFlattenedData(int nptr);
+    private native Bitmap nativeGetFavicon(int nptr);
 
-    /* Called by jni when the item is updated */
-    private void update(String url, String originalUrl, String title, 
-            Bitmap favicon, byte[] data) {
-        mUrl = url;
-        mOriginalUrl = originalUrl;
-        mTitle = title;
-        mFavicon = favicon;
-        mFlattenedData = data;
-    }
 }
diff --git a/core/java/android/webkit/WebViewClassic.java b/core/java/android/webkit/WebViewClassic.java
index eb5f835..92143203 100644
--- a/core/java/android/webkit/WebViewClassic.java
+++ b/core/java/android/webkit/WebViewClassic.java
@@ -149,24 +149,6 @@
 @SuppressWarnings("deprecation")
 public final class WebViewClassic implements WebViewProvider, WebViewProvider.ScrollDelegate,
         WebViewProvider.ViewDelegate {
-    private class InnerGlobalLayoutListener implements ViewTreeObserver.OnGlobalLayoutListener {
-        @Override
-        public void onGlobalLayout() {
-            if (mWebView.isShown()) {
-                setInvScreenRect();
-            }
-        }
-    }
-
-    private class InnerScrollChangedListener implements ViewTreeObserver.OnScrollChangedListener {
-        @Override
-        public void onScrollChanged() {
-            if (mWebView.isShown()) {
-                setInvScreenRect();
-            }
-        }
-    }
-
     /**
      * InputConnection used for ContentEditable. This captures changes
      * to the text and sends them either as key strokes or text changes.
@@ -617,12 +599,6 @@
         }
     }
 
-    // The listener to capture global layout change event.
-    private InnerGlobalLayoutListener mGlobalLayoutListener = null;
-
-    // The listener to capture scroll event.
-    private InnerScrollChangedListener mScrollChangedListener = null;
-
     // if AUTO_REDRAW_HACK is true, then the CALL key will toggle redrawing
     // the screen all-the-time. Good for profiling our drawing code
     static private final boolean AUTO_REDRAW_HACK = false;
@@ -647,7 +623,7 @@
     private final Rect mInvScreenRect = new Rect();
     private final Rect mScreenRect = new Rect();
     private final RectF mVisibleContentRect = new RectF();
-    private boolean mGLViewportEmpty = false;
+    private boolean mIsWebViewVisible = true;
     WebViewInputConnection mInputConnection = null;
     private int mFieldPointer;
     private PastePopupWindow mPasteWindow;
@@ -2979,7 +2955,10 @@
             // updated when we get out of that mode.
             if (!mDrawHistory) {
                 // repin our scroll, taking into account the new content size
-                updateScrollCoordinates(pinLocX(getScrollX()), pinLocY(getScrollY()));
+                if (updateScrollCoordinates(pinLocX(getScrollX()),
+                        pinLocY(getScrollY()))) {
+                    invalidate();
+                }
                 if (!mScroller.isFinished()) {
                     // We are in the middle of a scroll.  Repin the final scroll
                     // position.
@@ -3050,21 +3029,14 @@
         r.bottom = viewToContentY(r.bottom);
     }
 
-    private Rect mContentVisibleRect = new Rect();
+    private final Rect mTempContentVisibleRect = new Rect();
     // Sets r to be our visible rectangle in content coordinates. We use this
     // method on the native side to compute the position of the fixed layers.
     // Uses floating coordinates (necessary to correctly place elements when
     // the scale factor is not 1)
     private void calcOurContentVisibleRectF(RectF r) {
-        calcOurVisibleRect(mContentVisibleRect);
-        r.left = viewToContentXf(mContentVisibleRect.left) / mWebView.getScaleX();
-        // viewToContentY will remove the total height of the title bar.  Add
-        // the visible height back in to account for the fact that if the title
-        // bar is partially visible, the part of the visible rect which is
-        // displaying our content is displaced by that amount.
-        r.top = viewToContentYf(mContentVisibleRect.top + getVisibleTitleHeightImpl()) / mWebView.getScaleY();
-        r.right = viewToContentXf(mContentVisibleRect.right) / mWebView.getScaleX();
-        r.bottom = viewToContentYf(mContentVisibleRect.bottom) / mWebView.getScaleY();
+        calcOurVisibleRect(mTempContentVisibleRect);
+        viewToContentVisibleRect(r, mTempContentVisibleRect);
     }
 
     static class ViewSizeData {
@@ -4224,8 +4196,8 @@
 
         calcOurContentVisibleRectF(mVisibleContentRect);
         if (canvas.isHardwareAccelerated()) {
-            Rect invScreenRect = mGLViewportEmpty ? null : mInvScreenRect;
-            Rect screenRect = mGLViewportEmpty ? null : mScreenRect;
+            Rect invScreenRect = mIsWebViewVisible ? mInvScreenRect : null;
+            Rect screenRect = mIsWebViewVisible ? mScreenRect : null;
 
             int functor = nativeCreateDrawGLFunction(mNativeClass, invScreenRect,
                     screenRect, mVisibleContentRect, getScale(), extras);
@@ -5405,15 +5377,6 @@
     @Override
     public void onAttachedToWindow() {
         if (mWebView.hasWindowFocus()) setActive(true);
-        final ViewTreeObserver treeObserver = mWebView.getViewTreeObserver();
-        if (mGlobalLayoutListener == null) {
-            mGlobalLayoutListener = new InnerGlobalLayoutListener();
-            treeObserver.addOnGlobalLayoutListener(mGlobalLayoutListener);
-        }
-        if (mScrollChangedListener == null) {
-            mScrollChangedListener = new InnerScrollChangedListener();
-            treeObserver.addOnScrollChangedListener(mScrollChangedListener);
-        }
 
         addAccessibilityApisToJavaScript();
 
@@ -5426,16 +5389,6 @@
         mZoomManager.dismissZoomPicker();
         if (mWebView.hasWindowFocus()) setActive(false);
 
-        final ViewTreeObserver treeObserver = mWebView.getViewTreeObserver();
-        if (mGlobalLayoutListener != null) {
-            treeObserver.removeGlobalOnLayoutListener(mGlobalLayoutListener);
-            mGlobalLayoutListener = null;
-        }
-        if (mScrollChangedListener != null) {
-            treeObserver.removeOnScrollChangedListener(mScrollChangedListener);
-            mScrollChangedListener = null;
-        }
-
         removeAccessibilityApisFromJavaScript();
         updateHwAccelerated();
 
@@ -5547,11 +5500,18 @@
         }
     }
 
-    void setInvScreenRect() {
+    // updateRectsForGL() happens almost every draw call, in order to avoid creating
+    // any object in this code path, we move the local variable out to be a private
+    // final member, and we marked them as mTemp*.
+    private final Point mTempVisibleRectOffset = new Point();
+    private final Rect mTempVisibleRect = new Rect();
+
+    void updateRectsForGL() {
         // Use the getGlobalVisibleRect() to get the intersection among the parents
         // visible == false means we're clipped - send a null rect down to indicate that
         // we should not draw
-        boolean visible = mWebView.getGlobalVisibleRect(mInvScreenRect);
+        boolean visible = mWebView.getGlobalVisibleRect(mTempVisibleRect, mTempVisibleRectOffset);
+        mInvScreenRect.set(mTempVisibleRect);
         if (visible) {
             // Then need to invert the Y axis, just for GL
             View rootView = mWebView.getRootView();
@@ -5560,16 +5520,33 @@
             int savedWebViewBottom = mInvScreenRect.bottom;
             mInvScreenRect.bottom = rootViewHeight - mInvScreenRect.top - getVisibleTitleHeightImpl();
             mInvScreenRect.top = rootViewHeight - savedWebViewBottom;
-            mGLViewportEmpty = false;
+            mIsWebViewVisible = true;
         } else {
-            mGLViewportEmpty = true;
+            mIsWebViewVisible = false;
         }
-        calcOurContentVisibleRectF(mVisibleContentRect);
-        nativeUpdateDrawGLFunction(mNativeClass, mGLViewportEmpty ? null : mInvScreenRect,
-                mGLViewportEmpty ? null : mScreenRect,
+
+        mTempVisibleRect.offset(-mTempVisibleRectOffset.x, -mTempVisibleRectOffset.y);
+        viewToContentVisibleRect(mVisibleContentRect, mTempVisibleRect);
+
+        nativeUpdateDrawGLFunction(mNativeClass, mIsWebViewVisible ? mInvScreenRect : null,
+                mIsWebViewVisible ? mScreenRect : null,
                 mVisibleContentRect, getScale());
     }
 
+    // Input : viewRect, rect in view/screen coordinate.
+    // Output: contentRect, rect in content/document coordinate.
+    private void viewToContentVisibleRect(RectF contentRect, Rect viewRect) {
+        contentRect.left = viewToContentXf(viewRect.left) / mWebView.getScaleX();
+        // viewToContentY will remove the total height of the title bar.  Add
+        // the visible height back in to account for the fact that if the title
+        // bar is partially visible, the part of the visible rect which is
+        // displaying our content is displaced by that amount.
+        contentRect.top = viewToContentYf(viewRect.top + getVisibleTitleHeightImpl())
+                / mWebView.getScaleY();
+        contentRect.right = viewToContentXf(viewRect.right) / mWebView.getScaleX();
+        contentRect.bottom = viewToContentYf(viewRect.bottom) / mWebView.getScaleY();
+    }
+
     @Override
     public boolean setFrame(int left, int top, int right, int bottom) {
         boolean changed = mWebViewPrivate.super_setFrame(left, top, right, bottom);
@@ -5582,7 +5559,7 @@
             // notify the WebKit about the new dimensions.
             sendViewSizeZoom(false);
         }
-        setInvScreenRect();
+        updateRectsForGL();
         return changed;
     }
 
diff --git a/core/java/android/widget/ActivityChooserModel.java b/core/java/android/widget/ActivityChooserModel.java
index 1578154..c6104bc 100644
--- a/core/java/android/widget/ActivityChooserModel.java
+++ b/core/java/android/widget/ActivityChooserModel.java
@@ -21,6 +21,7 @@
 import android.content.Intent;
 import android.content.pm.ResolveInfo;
 import android.database.DataSetObservable;
+import android.database.DataSetObserver;
 import android.os.AsyncTask;
 import android.text.TextUtils;
 import android.util.Log;
diff --git a/core/java/android/widget/ShareActionProvider.java b/core/java/android/widget/ShareActionProvider.java
index 367561e..21840ca 100644
--- a/core/java/android/widget/ShareActionProvider.java
+++ b/core/java/android/widget/ShareActionProvider.java
@@ -240,12 +240,25 @@
      * <p>
      * <strong>Note:</strong> The history file name can be set any time, however
      * only the action views created by {@link #onCreateActionView()} after setting
-     * the file name will be backed by the provided file. Hence, if you are using
-     * a share action provider on a menu item and want to change the history file
-     * based on the type of the currently selected item, you need to call
-     * {@link android.app.Activity#invalidateOptionsMenu()} to force the system
-     * to recreate the menu UI.
+     * the file name will be backed by the provided file. Therefore, if you want to
+     * use different history files for sharing specific types of content, every time
+     * you change the history file {@link #setShareHistoryFileName(String)} you must
+     * call {@link android.app.Activity#invalidateOptionsMenu()} to recreate the
+     * action view. You should <strong>not</strong> call
+     * {@link android.app.Activity#invalidateOptionsMenu()} from
+     * {@link android.app.Activity#onCreateOptionsMenu(Menu)}.
      * <p>
+     * <code>
+     * private void doShare(Intent intent) {
+     *     if (IMAGE.equals(intent.getMimeType())) {
+     *         mShareActionProvider.setHistoryFileName(SHARE_IMAGE_HISTORY_FILE_NAME);
+     *     } else if (TEXT.equals(intent.getMimeType())) {
+     *         mShareActionProvider.setHistoryFileName(SHARE_TEXT_HISTORY_FILE_NAME);
+     *     }
+     *     mShareActionProvider.setIntent(intent);
+     *     invalidateOptionsMenu();
+     * }
+     * <code>
      *
      * @param shareHistoryFile The share history file name.
      */
diff --git a/core/java/com/android/internal/app/IMediaContainerService.aidl b/core/java/com/android/internal/app/IMediaContainerService.aidl
index 727c094..c9f7a58 100755
--- a/core/java/com/android/internal/app/IMediaContainerService.aidl
+++ b/core/java/com/android/internal/app/IMediaContainerService.aidl
@@ -18,6 +18,7 @@
 
 import android.net.Uri;
 import android.os.ParcelFileDescriptor;
+import android.content.pm.ContainerEncryptionParams;
 import android.content.pm.PackageInfoLite;
 import android.content.res.ObbInfo;
 
@@ -25,9 +26,9 @@
     String copyResourceToContainer(in Uri packageURI, String containerId, String key,
             String resFileName, String publicResFileName, boolean isExternal,
             boolean isForwardLocked);
-    int copyResource(in Uri packageURI,
-                in ParcelFileDescriptor outStream);
-    PackageInfoLite getMinimalPackageInfo(in Uri fileUri, in int flags, in long threshold);
+    int copyResource(in Uri packageURI, in ContainerEncryptionParams encryptionParams,
+            in ParcelFileDescriptor outStream);
+    PackageInfoLite getMinimalPackageInfo(in String packagePath, in int flags, in long threshold);
     boolean checkInternalFreeStorage(in Uri fileUri, boolean isForwardLocked, in long threshold);
     boolean checkExternalFreeStorage(in Uri fileUri, boolean isForwardLocked);
     ObbInfo getObbInfo(in String filename);
diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index 4f2afa7..614f73f 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -210,12 +210,29 @@
     }
 
     @Override
+    protected void onRestoreInstanceState(Bundle savedInstanceState) {
+        super.onRestoreInstanceState(savedInstanceState);
+        if (mAlwaysUseOption) {
+            final int checkedPos = mGrid.getCheckedItemPosition();
+            final boolean enabled = checkedPos != GridView.INVALID_POSITION;
+            mAlwaysButton.setEnabled(enabled);
+            mOnceButton.setEnabled(enabled);
+            if (enabled) {
+                mGrid.setSelection(checkedPos);
+            }
+        }
+    }
+
+    @Override
     public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
         if (mAlwaysUseOption) {
             final int checkedPos = mGrid.getCheckedItemPosition();
             final boolean enabled = checkedPos != GridView.INVALID_POSITION;
             mAlwaysButton.setEnabled(enabled);
             mOnceButton.setEnabled(enabled);
+            if (enabled) {
+                mGrid.smoothScrollToPosition(checkedPos);
+            }
         } else {
             startSelected(position, false);
         }
diff --git a/core/jni/android/graphics/Canvas.cpp b/core/jni/android/graphics/Canvas.cpp
index ef6af74..6b74705 100644
--- a/core/jni/android/graphics/Canvas.cpp
+++ b/core/jni/android/graphics/Canvas.cpp
@@ -69,7 +69,11 @@
         SkImageRef_GlobalPool::SetRAMUsed(0);
         SkGraphics::PurgeFontCache();
     }
-    
+
+    static void freeTextLayoutCaches(JNIEnv* env, jobject) {
+        TextLayoutEngine::getInstance().purgeCaches();
+    }
+
     static jboolean isOpaque(JNIEnv* env, jobject jcanvas) {
         NPE_CHECK_RETURN_ZERO(env, jcanvas);
         SkCanvas* canvas = GraphicsJNI::getNativeCanvas(env, jcanvas);
@@ -986,7 +990,9 @@
         (void*) SkCanvasGlue::drawTextOnPath__StringPathFFPaint},
     {"native_drawPicture", "(II)V", (void*) SkCanvasGlue::drawPicture},
 
-    {"freeCaches", "()V", (void*) SkCanvasGlue::freeCaches}
+    {"freeCaches", "()V", (void*) SkCanvasGlue::freeCaches},
+
+    {"freeTextLayoutCaches", "()V", (void*) SkCanvasGlue::freeTextLayoutCaches}
 };
 
 ///////////////////////////////////////////////////////////////////////////////
diff --git a/core/jni/android/graphics/TextLayoutCache.cpp b/core/jni/android/graphics/TextLayoutCache.cpp
index 16f377d..673c38d 100644
--- a/core/jni/android/graphics/TextLayoutCache.cpp
+++ b/core/jni/android/graphics/TextLayoutCache.cpp
@@ -1015,4 +1015,11 @@
     return value;
 }
 
+void TextLayoutEngine::purgeCaches() {
+#if USE_TEXT_LAYOUT_CACHE
+    mTextLayoutCache->clear();
+#endif
+}
+
+
 } // namespace android
diff --git a/core/jni/android/graphics/TextLayoutCache.h b/core/jni/android/graphics/TextLayoutCache.h
index 0be61c65..027e888 100644
--- a/core/jni/android/graphics/TextLayoutCache.h
+++ b/core/jni/android/graphics/TextLayoutCache.h
@@ -310,6 +310,9 @@
 
     sp<TextLayoutValue> getValue(const SkPaint* paint, const jchar* text, jint start,
             jint count, jint contextCount, jint dirFlags);
+
+    void purgeCaches();
+
 private:
     TextLayoutCache* mTextLayoutCache;
     TextLayoutShaper* mShaper;
diff --git a/core/jni/android_hardware_SensorManager.cpp b/core/jni/android_hardware_SensorManager.cpp
index eddd838..3c1b9c8 100644
--- a/core/jni/android_hardware_SensorManager.cpp
+++ b/core/jni/android_hardware_SensorManager.cpp
@@ -130,10 +130,13 @@
         res = queue->waitForEvent();
         if (res != NO_ERROR)
             return -1;
+        // here we're guaranteed to have an event
         res = queue->read(&event, 1);
+        ALOGE_IF(res==0, "sensors_data_poll: nothing to read after waitForEvent()");
     }
-    if (res < 0)
+    if (res <= 0) {
         return -1;
+    }
 
     jint accuracy = event.vector.status;
     env->SetFloatArrayRegion(values, 0, 3, event.vector.v);
diff --git a/core/jni/android_os_Power.cpp b/core/jni/android_os_Power.cpp
index a201d8b..373abd4 100644
--- a/core/jni/android_os_Power.cpp
+++ b/core/jni/android_os_Power.cpp
@@ -72,11 +72,15 @@
 setScreenState(JNIEnv *env, jobject clazz, jboolean on)
 {
     if (on) {
-	autosuspend_disable();
-	sPowerModule->setInteractive(sPowerModule, true);
+        autosuspend_disable();
+        if (sPowerModule) {
+            sPowerModule->setInteractive(sPowerModule, true);
+        }
     } else {
-	sPowerModule->setInteractive(sPowerModule, false);
-	autosuspend_enable();
+        if (sPowerModule) {
+            sPowerModule->setInteractive(sPowerModule, false);
+        }
+        autosuspend_enable();
     }
 
     return 0;
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index e16e49a..dbc60f9 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -1594,7 +1594,8 @@
         android:protectionLevel="signature" />
 
     <!-- Allows low-level access to setting the keyboard layout.
-         Not for use by normal applications. -->
+         Not for use by normal applications.
+         @hide -->
     <permission android:name="android.permission.SET_KEYBOARD_LAYOUT"
         android:label="@string/permlab_setKeyboardLayout"
         android:description="@string/permdesc_setKeyboardLayout"
diff --git a/core/res/res/layout/notification_template_big_base.xml b/core/res/res/layout/notification_template_big_base.xml
index 097d15d..f8b24e2 100644
--- a/core/res/res/layout/notification_template_big_base.xml
+++ b/core/res/res/layout/notification_template_big_base.xml
@@ -43,99 +43,106 @@
         android:gravity="center_vertical"
         >
         <LinearLayout
-            android:id="@+id/line1"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
-            android:orientation="horizontal"
+            android:minHeight="@dimen/notification_large_icon_height"
+            android:orientation="vertical"
             >
-            <TextView android:id="@+id/title"
-                android:textAppearance="@style/TextAppearance.StatusBar.EventContent.Title"
+            <LinearLayout
+                android:id="@+id/line1"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
+                android:orientation="horizontal"
+                >
+                <TextView android:id="@+id/title"
+                    android:textAppearance="@style/TextAppearance.StatusBar.EventContent.Title"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:singleLine="true"
+                    android:ellipsize="marquee"
+                    android:fadingEdge="horizontal"
+                    android:layout_weight="1"
+                    />
+                <ViewStub android:id="@+id/time"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_gravity="center"
+                    android:layout_weight="0"
+                    android:visibility="gone"
+                    android:layout="@layout/notification_template_part_time"
+                    />
+                <ViewStub android:id="@+id/chronometer"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_gravity="center"
+                    android:layout_weight="0"
+                    android:visibility="gone"
+                    android:layout="@layout/notification_template_part_chronometer"
+                    />
+            </LinearLayout>
+            <TextView android:id="@+id/text2"
+                android:textAppearance="@style/TextAppearance.StatusBar.EventContent.Line2"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_marginTop="-2dp"
+                android:layout_marginBottom="-2dp"
                 android:singleLine="true"
-                android:ellipsize="marquee"
                 android:fadingEdge="horizontal"
-                android:layout_weight="1"
-                />
-            <ViewStub android:id="@+id/time"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:layout_gravity="center"
-                android:layout_weight="0"
+                android:ellipsize="marquee"
                 android:visibility="gone"
-                android:layout="@layout/notification_template_part_time"
                 />
-            <ViewStub android:id="@+id/chronometer"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:layout_gravity="center"
-                android:layout_weight="0"
-                android:visibility="gone"
-                android:layout="@layout/notification_template_part_chronometer"
-                />
-        </LinearLayout>
-        <TextView android:id="@+id/text2"
-            android:textAppearance="@style/TextAppearance.StatusBar.EventContent.Line2"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:layout_marginTop="-2dp"
-            android:layout_marginBottom="-2dp"
-            android:singleLine="true"
-            android:fadingEdge="horizontal"
-            android:ellipsize="marquee"
-            android:visibility="gone"
-            />
-        <TextView android:id="@+id/big_text"
-            android:textAppearance="@style/TextAppearance.StatusBar.EventContent"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:singleLine="false"
-            android:visibility="gone"
-            />
-        <LinearLayout
-            android:id="@+id/line3"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:orientation="horizontal"
-            >
-            <TextView android:id="@+id/text"
+            <TextView android:id="@+id/big_text"
                 android:textAppearance="@style/TextAppearance.StatusBar.EventContent"
-                android:layout_width="0dp"
+                android:layout_width="match_parent"
                 android:layout_height="wrap_content"
-                android:layout_weight="1"
-                android:layout_gravity="center"
-                android:singleLine="true"
-                android:ellipsize="marquee"
-                android:fadingEdge="horizontal"
-                />
-            <TextView android:id="@+id/info"
-                android:textAppearance="@style/TextAppearance.StatusBar.EventContent.Info"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:layout_gravity="center"
-                android:layout_weight="0"
-                android:singleLine="true"
-                android:gravity="center"
-                android:paddingLeft="8dp"
-                />
-            <ImageView android:id="@+id/right_icon"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:layout_gravity="center"
-                android:layout_weight="0"
-                android:scaleType="center"
-                android:paddingLeft="8dp"
+                android:singleLine="false"
                 android:visibility="gone"
-                android:drawableAlpha="180"
+                />
+            <LinearLayout
+                android:id="@+id/line3"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:orientation="horizontal"
+                >
+                <TextView android:id="@+id/text"
+                    android:textAppearance="@style/TextAppearance.StatusBar.EventContent"
+                    android:layout_width="0dp"
+                    android:layout_height="wrap_content"
+                    android:layout_weight="1"
+                    android:layout_gravity="center"
+                    android:singleLine="true"
+                    android:ellipsize="marquee"
+                    android:fadingEdge="horizontal"
+                    />
+                <TextView android:id="@+id/info"
+                    android:textAppearance="@style/TextAppearance.StatusBar.EventContent.Info"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_gravity="center"
+                    android:layout_weight="0"
+                    android:singleLine="true"
+                    android:gravity="center"
+                    android:paddingLeft="8dp"
+                    />
+                <ImageView android:id="@+id/right_icon"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_gravity="center"
+                    android:layout_weight="0"
+                    android:scaleType="center"
+                    android:paddingLeft="8dp"
+                    android:visibility="gone"
+                    android:drawableAlpha="180"
+                    />
+            </LinearLayout>
+            <ProgressBar
+                android:id="@android:id/progress"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:visibility="gone"
+                style="?android:attr/progressBarStyleHorizontal"
                 />
         </LinearLayout>
-        <ProgressBar
-            android:id="@android:id/progress"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:visibility="gone"
-            style="?android:attr/progressBarStyleHorizontal"
-            />
         <LinearLayout
             android:id="@+id/actions"
             android:layout_width="match_parent"
diff --git a/core/res/res/layout/resolver_grid.xml b/core/res/res/layout/resolver_grid.xml
index f10a59f0..4a0e84a 100644
--- a/core/res/res/layout/resolver_grid.xml
+++ b/core/res/res/layout/resolver_grid.xml
@@ -23,15 +23,20 @@
               android:divider="?android:attr/dividerHorizontal"
               android:showDividers="middle"
               android:dividerPadding="0dip">
-    <GridView
-        android:layout_gravity="center"
-        android:layout_height="wrap_content"
-        android:layout_width="wrap_content"
-        android:id="@+id/resolver_grid"
-        android:numColumns="4"
-        android:columnWidth="128dp"
-        android:padding="16dp"
-        android:clipToPadding="false" />
+    <FrameLayout android:layout_width="match_parent"
+                 android:layout_height="wrap_content"
+                 android:layout_weight="1">
+        <GridView
+            android:layout_gravity="center"
+            android:layout_width="wrap_content"
+            android:layout_height="match_parent"
+            android:id="@+id/resolver_grid"
+            android:numColumns="4"
+            android:columnWidth="128dp"
+            android:padding="16dp"
+            android:clipToPadding="false"
+            android:scrollbarStyle="outsideOverlay" />
+    </FrameLayout>
     <LinearLayout
         android:id="@+id/button_bar"
         android:visibility="gone"
diff --git a/core/res/res/values-h720dp/dimens.xml b/core/res/res/values-h720dp/dimens.xml
index 5a9c777..f726a98 100644
--- a/core/res/res/values-h720dp/dimens.xml
+++ b/core/res/res/values-h720dp/dimens.xml
@@ -19,12 +19,4 @@
 <resources>
     <!-- Dialog button bar height -->
     <dimen name="alert_dialog_button_bar_height">54dip</dimen>
-    <!-- Preference fragment padding, bottom -->
-    <dimen name="preference_fragment_padding_bottom">16dp</dimen>
-
-    <dimen name="preference_screen_header_padding_side">0dip</dimen>
-
-    <integer name="preference_screen_header_scrollbarStyle">0x0</integer> <!-- insideOverlay -->
-    <integer name="preference_fragment_scrollbarStyle">0x02000000</integer> <!-- outsideOverlay -->
-
 </resources>
diff --git a/core/res/res/values-sw600dp-w1024dp/dimens.xml b/core/res/res/values-sw600dp-w1024dp/dimens.xml
deleted file mode 100644
index 4d6a4da..0000000
--- a/core/res/res/values-sw600dp-w1024dp/dimens.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2011 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<resources>
-    <!-- Increase size (used to be 0 for dual pane -->
-    <!-- Preference activity side margins -->
-    <dimen name="preference_screen_side_margin">48dp</dimen>
-    <!-- Preference activity side margins negative-->
-    <dimen name="preference_screen_side_margin_negative">-52dp</dimen>
-</resources>
diff --git a/tools/localize/testdata/res/values-zz-rZZ/strings.xml b/core/res/res/values-sw600dp-w960dp/dimens.xml
similarity index 71%
rename from tools/localize/testdata/res/values-zz-rZZ/strings.xml
rename to core/res/res/values-sw600dp-w960dp/dimens.xml
index c2a783d..724904e 100644
--- a/tools/localize/testdata/res/values-zz-rZZ/strings.xml
+++ b/core/res/res/values-sw600dp-w960dp/dimens.xml
@@ -1,12 +1,12 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2007 The Android Open Source Project
+<!-- 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.
@@ -14,9 +14,8 @@
      limitations under the License.
 -->
 
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="changed_in_xx">AAAA</string>
-    <string name="previously_translated">CCC</string>
+<resources>
+    <dimen name="preference_screen_header_padding_side">48dp</dimen>
+    <!-- Preference fragment padding, sides -->
+    <dimen name="preference_fragment_padding_side">48dp</dimen>
 </resources>
-
-
diff --git a/core/res/res/values-sw600dp/bools.xml b/core/res/res/values-sw600dp/bools.xml
index 92b6171..b8db31f 100644
--- a/core/res/res/values-sw600dp/bools.xml
+++ b/core/res/res/values-sw600dp/bools.xml
@@ -15,6 +15,5 @@
 -->
 
 <resources>
-    <bool name="preferences_prefer_dual_pane">true</bool>
     <bool name="target_honeycomb_needs_options_menu">false</bool>
 </resources>
diff --git a/core/res/res/values-sw600dp/dimens.xml b/core/res/res/values-sw600dp/dimens.xml
index f8f865e..61136e3 100644
--- a/core/res/res/values-sw600dp/dimens.xml
+++ b/core/res/res/values-sw600dp/dimens.xml
@@ -47,12 +47,6 @@
     <!-- Size of status line font in LockScreen. -->
     <dimen name="keyguard_pattern_unlock_status_line_font_size">14sp</dimen>
 
-    <!-- Preference activity, vertical padding for the header list -->
-    <dimen name="preference_screen_header_vertical_padding">32dp</dimen>
-    <dimen name="preference_screen_side_margin">0dp</dimen>
-    <!-- Compensate for double margin : preference_screen_side_margin + 4 (frame background shadow) = -preference_screen_side_margin_negative -->
-    <dimen name="preference_screen_side_margin_negative">-4dp</dimen>
-
     <!-- Default padding to apply to AppWidgetHostViews containing widgets targeting API level 14 and up. -->
     <dimen name="default_app_widget_padding_left">12dp</dimen>
     <dimen name="default_app_widget_padding_top">4dp</dimen>
@@ -78,5 +72,9 @@
     <!-- Height of the bottom navigation bar in portrait; on sw600dp devices
          this is a bit taller -->
     <dimen name="navigation_bar_height_portrait">56dp</dimen>
+
+    <!-- Preference fragment padding, sides -->
+    <dimen name="preference_fragment_padding_side">24dp</dimen>
+    <dimen name="preference_screen_header_padding_side">24dip</dimen>
 </resources>
 
diff --git a/core/res/res/values-sw600dp/styles.xml b/core/res/res/values-sw600dp/styles.xml
index f9e95b7..7dea9b8 100644
--- a/core/res/res/values-sw600dp/styles.xml
+++ b/core/res/res/values-sw600dp/styles.xml
@@ -25,12 +25,4 @@
         <item name="android:measureWithLargestChild">true</item>
         <item name="android:tabLayout">@android:layout/tab_indicator_holo</item>
     </style>
-
-    <style name="PreferencePanel">
-        <item name="android:layout_marginLeft">@dimen/preference_screen_side_margin</item>
-        <item name="android:layout_marginRight">@dimen/preference_screen_side_margin</item>
-        <item name="android:layout_marginTop">@dimen/preference_screen_top_margin</item>
-        <item name="android:layout_marginBottom">@dimen/preference_screen_bottom_margin</item>
-        <item name="android:background">?attr/detailsElementBackground</item>
-    </style>
 </resources>
diff --git a/core/res/res/values-sw600dp-w1280dp/dimens.xml b/core/res/res/values-sw720dp-w1280dp/dimens.xml
similarity index 100%
rename from core/res/res/values-sw600dp-w1280dp/dimens.xml
rename to core/res/res/values-sw720dp-w1280dp/dimens.xml
diff --git a/tools/localize/testdata/merge_xx_old.xml b/core/res/res/values-sw720dp/bools.xml
similarity index 72%
rename from tools/localize/testdata/merge_xx_old.xml
rename to core/res/res/values-sw720dp/bools.xml
index 9d3a7d8..7d5813f 100644
--- a/tools/localize/testdata/merge_xx_old.xml
+++ b/core/res/res/values-sw720dp/bools.xml
@@ -1,12 +1,12 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2007 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
-  
+
      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.
@@ -14,8 +14,6 @@
      limitations under the License.
 -->
 
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="changed_in_xx">aaa</string>
-    <string name="previously_translated">CCC</string>
+<resources>
+    <bool name="preferences_prefer_dual_pane">true</bool>
 </resources>
-
diff --git a/core/res/res/values-sw720dp/dimens.xml b/core/res/res/values-sw720dp/dimens.xml
index 7b1bc4c5..34c7ea3 100644
--- a/core/res/res/values-sw720dp/dimens.xml
+++ b/core/res/res/values-sw720dp/dimens.xml
@@ -38,6 +38,32 @@
     <dimen name="thumbnail_width">230dp</dimen>
     <!-- The height that is used when creating thumbnails of applications. -->
     <dimen name="thumbnail_height">135dp</dimen>
+
+    <!-- Preference activity, vertical padding for the header list -->
+    <dimen name="preference_screen_header_vertical_padding">32dp</dimen>
+    <dimen name="preference_screen_side_margin">0dp</dimen>
+    <!-- Compensate for double margin : preference_screen_side_margin + 4 (frame background shadow) = -preference_screen_side_margin_negative -->
+    <dimen name="preference_screen_side_margin_negative">-4dp</dimen>
+
+    <!-- Preference fragment padding, bottom -->
+    <dimen name="preference_fragment_padding_bottom">16dp</dimen>
+    <dimen name="preference_screen_header_padding_side">0dip</dimen>
+    <integer name="preference_screen_header_scrollbarStyle">0x0</integer> <!-- insideOverlay -->
+
+    <!-- Preference fragment padding, sides -->
+    <dimen name="preference_fragment_padding_side">32dp</dimen>
+    <!-- Padding to the left of the preference panel breadcrumb -->
+    <dimen name="preference_breadcrumb_paddingLeft">32dp</dimen>
+    <!-- Padding to the right of the preference panel breadcrumb -->
+    <dimen name="preference_breadcrumb_paddingRight">32dp</dimen>
+    <!-- Weight of the left pane in a multi-pane preference layout. -->
+    <integer name="preferences_left_pane_weight">1</integer>
+    <!-- Weight of the right pane in a multi-pane preference layout. So the split is 1:2 -->
+    <integer name="preferences_right_pane_weight">2</integer>
+    <!-- Minimum space to allocate to the left of a preference item for an icon.
+        This helps in aligning titles when some items have icons and some don't. When space is
+        at a premium, we don't pre-allocate any space. -->
+    <dimen name="preference_icon_minWidth">56dp</dimen>
 </resources>
 
 
diff --git a/core/res/res/values-sw720dp/styles.xml b/core/res/res/values-sw720dp/styles.xml
new file mode 100644
index 0000000..640e898
--- /dev/null
+++ b/core/res/res/values-sw720dp/styles.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2012 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<resources>
+    <style name="PreferencePanel">
+        <item name="android:layout_marginLeft">@dimen/preference_screen_side_margin</item>
+        <item name="android:layout_marginRight">@dimen/preference_screen_side_margin</item>
+        <item name="android:layout_marginTop">@dimen/preference_screen_top_margin</item>
+        <item name="android:layout_marginBottom">@dimen/preference_screen_bottom_margin</item>
+        <item name="android:background">?attr/detailsElementBackground</item>
+    </style>
+</resources>
diff --git a/core/res/res/values-w720dp/dimens.xml b/core/res/res/values-w720dp/dimens.xml
deleted file mode 100644
index a37f588..0000000
--- a/core/res/res/values-w720dp/dimens.xml
+++ /dev/null
@@ -1,37 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2011 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<resources>
-    <!-- Preference fragment padding, sides -->
-    <dimen name="preference_fragment_padding_side">32dp</dimen>
-    <!-- Padding to the left of the preference panel breadcrumb -->
-    <dimen name="preference_breadcrumb_paddingLeft">32dp</dimen>
-    <!-- Padding to the right of the preference panel breadcrumb -->
-    <dimen name="preference_breadcrumb_paddingRight">32dp</dimen>
-    <!-- Weight of the left pane in a multi-pane preference layout. -->
-    <integer name="preferences_left_pane_weight">1</integer>
-    <!-- Weight of the right pane in a multi-pane preference layout. So the split is 1:2 -->
-    <integer name="preferences_right_pane_weight">2</integer>
-    <!-- Minimum space to allocate to the left of a preference item for an icon.
-        This helps in aligning titles when some items have icons and some don't. When space is
-        at a premium, we don't pre-allocate any space. -->
-    <dimen name="preference_icon_minWidth">56dp</dimen>
-
-    <dimen name="preference_screen_header_padding_side">0dip</dimen>
-
-    <integer name="preference_screen_header_scrollbarStyle">0x0</integer> <!-- insideOverlay -->
-    <integer name="preference_fragment_scrollbarStyle">0x02000000</integer> <!-- outsideOverlay -->
-</resources>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index e7ad4c2..687a00b 100755
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -3562,7 +3562,7 @@
 
     <!-- Title for a button to choose the currently selected activity
          as the default in the activity resolver. [CHAR LIMIT=25] -->
-    <string name="activity_resolver_use_always">Use Always</string>
+    <string name="activity_resolver_use_always">Always</string>
 
     <!-- Title for a button to choose the currently selected activity
          from the activity resolver to use just this once. [CHAR LIMIT=25] -->
diff --git a/core/tests/coretests/src/android/content/pm/ContainerEncryptionParamsTest.java b/core/tests/coretests/src/android/content/pm/ContainerEncryptionParamsTest.java
new file mode 100644
index 0000000..7deaa9a
--- /dev/null
+++ b/core/tests/coretests/src/android/content/pm/ContainerEncryptionParamsTest.java
@@ -0,0 +1,370 @@
+/*
+ * 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.content.pm;
+
+import android.os.Parcel;
+import android.test.AndroidTestCase;
+
+import java.util.Arrays;
+
+import javax.crypto.SecretKey;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+
+public class ContainerEncryptionParamsTest extends AndroidTestCase {
+    private static final String ENC_ALGORITHM = "AES/CBC/PKCS7Padding";
+
+    private static final byte[] IV_BYTES = "FOOBAR".getBytes();
+
+    private static final IvParameterSpec ENC_PARAMS = new IvParameterSpec(IV_BYTES);
+
+    private static final byte[] ENC_KEY_BYTES = "abcd1234wxyz7890".getBytes();
+
+    private static final SecretKey ENC_KEY = new SecretKeySpec(ENC_KEY_BYTES, "RAW");
+
+    private static final String MAC_ALGORITHM = "HMAC-SHA1";
+
+    private static final byte[] MAC_KEY_BYTES = "4wxyzabcd1237890".getBytes();
+
+    private static final SecretKey MAC_KEY = new SecretKeySpec(MAC_KEY_BYTES, "RAW");
+
+    private static final byte[] MAC_TAG = "faketag".getBytes();
+
+    private static final int AUTHENTICATED_START = 5;
+
+    private static final int ENCRYPTED_START = 11;
+
+    private static final int DATA_END = 19;
+
+    public void testParcel() throws Exception {
+        ContainerEncryptionParams expected = new ContainerEncryptionParams(ENC_ALGORITHM,
+                ENC_PARAMS, ENC_KEY, MAC_ALGORITHM, null, MAC_KEY, MAC_TAG, AUTHENTICATED_START,
+                ENCRYPTED_START, DATA_END);
+
+        Parcel parcel = Parcel.obtain();
+        expected.writeToParcel(parcel, 0);
+        parcel.setDataPosition(0);
+
+        ContainerEncryptionParams actual = ContainerEncryptionParams.CREATOR
+                .createFromParcel(parcel);
+
+        assertEquals(ENC_ALGORITHM, actual.getEncryptionAlgorithm());
+
+        if (!(actual.getEncryptionSpec() instanceof IvParameterSpec)) {
+            fail("encryption parameters should be IvParameterSpec");
+        } else {
+            IvParameterSpec actualParams = (IvParameterSpec) actual.getEncryptionSpec();
+            assertTrue(Arrays.equals(IV_BYTES, actualParams.getIV()));
+        }
+
+        assertEquals(ENC_KEY, actual.getEncryptionKey());
+
+        assertEquals(MAC_ALGORITHM, actual.getMacAlgorithm());
+
+        assertNull(actual.getMacSpec());
+
+        assertEquals(MAC_KEY, actual.getMacKey());
+
+        assertTrue(Arrays.equals(MAC_TAG, actual.getMacTag()));
+
+        assertEquals(AUTHENTICATED_START, actual.getAuthenticatedDataStart());
+
+        assertEquals(ENCRYPTED_START, actual.getEncryptedDataStart());
+
+        assertEquals(DATA_END, actual.getDataEnd());
+    }
+
+    public void testEquals_Success() throws Exception {
+        ContainerEncryptionParams params1 = new ContainerEncryptionParams(ENC_ALGORITHM,
+                ENC_PARAMS, ENC_KEY, MAC_ALGORITHM, null, MAC_KEY, MAC_TAG, AUTHENTICATED_START,
+                ENCRYPTED_START, DATA_END);
+
+        ContainerEncryptionParams params2 = new ContainerEncryptionParams(
+                new String(ENC_ALGORITHM), new IvParameterSpec(IV_BYTES.clone()),
+                new SecretKeySpec(ENC_KEY_BYTES.clone(), "RAW"), new String(MAC_ALGORITHM), null,
+                new SecretKeySpec(MAC_KEY_BYTES.clone(), "RAW"), MAC_TAG, AUTHENTICATED_START,
+                ENCRYPTED_START, DATA_END);
+
+        assertEquals(params1, params2);
+    }
+
+    public void testEquals_EncAlgo_Failure() throws Exception {
+        ContainerEncryptionParams params1 = new ContainerEncryptionParams(ENC_ALGORITHM,
+                ENC_PARAMS, ENC_KEY, MAC_ALGORITHM, null, MAC_KEY, MAC_TAG, AUTHENTICATED_START,
+                ENCRYPTED_START, DATA_END);
+
+        ContainerEncryptionParams params2 = new ContainerEncryptionParams(new String(
+                "AES-256/CBC/PKCS7Padding"), new IvParameterSpec(IV_BYTES.clone()),
+                new SecretKeySpec(ENC_KEY_BYTES.clone(), "RAW"), new String(MAC_ALGORITHM), null,
+                new SecretKeySpec(MAC_KEY_BYTES.clone(), "RAW"), MAC_TAG, AUTHENTICATED_START,
+                ENCRYPTED_START, DATA_END);
+
+        assertFalse(params1.equals(params2));
+    }
+
+    public void testEquals_EncParams_Failure() throws Exception {
+        ContainerEncryptionParams params1 = new ContainerEncryptionParams(ENC_ALGORITHM,
+                ENC_PARAMS, ENC_KEY, MAC_ALGORITHM, null, MAC_KEY, MAC_TAG, AUTHENTICATED_START,
+                ENCRYPTED_START, DATA_END);
+
+        ContainerEncryptionParams params2 = new ContainerEncryptionParams(
+                new String(ENC_ALGORITHM), new IvParameterSpec("BLAHBLAH".getBytes()),
+                new SecretKeySpec(ENC_KEY_BYTES.clone(), "RAW"), new String(MAC_ALGORITHM), null,
+                new SecretKeySpec(MAC_KEY_BYTES.clone(), "RAW"), MAC_TAG, AUTHENTICATED_START,
+                ENCRYPTED_START, DATA_END);
+
+        assertFalse(params1.equals(params2));
+    }
+
+    public void testEquals_EncKey_Failure() throws Exception {
+        ContainerEncryptionParams params1 = new ContainerEncryptionParams(ENC_ALGORITHM,
+                ENC_PARAMS, ENC_KEY, MAC_ALGORITHM, null, MAC_KEY, MAC_TAG, AUTHENTICATED_START,
+                ENCRYPTED_START, DATA_END);
+
+        ContainerEncryptionParams params2 = new ContainerEncryptionParams(
+                new String(ENC_ALGORITHM), new IvParameterSpec(IV_BYTES.clone()),
+                new SecretKeySpec("BLAHBLAH".getBytes(), "RAW"), new String(MAC_ALGORITHM), null,
+                new SecretKeySpec(MAC_KEY_BYTES.clone(), "RAW"), MAC_TAG, AUTHENTICATED_START,
+                ENCRYPTED_START, DATA_END);
+
+        assertFalse(params1.equals(params2));
+    }
+
+    public void testEquals_MacAlgo_Failure() throws Exception {
+        ContainerEncryptionParams params1 = new ContainerEncryptionParams(ENC_ALGORITHM,
+                ENC_PARAMS, ENC_KEY, MAC_ALGORITHM, null, MAC_KEY, MAC_TAG, AUTHENTICATED_START,
+                ENCRYPTED_START, DATA_END);
+
+        ContainerEncryptionParams params2 = new ContainerEncryptionParams(
+                new String(ENC_ALGORITHM), new IvParameterSpec(IV_BYTES.clone()),
+                new SecretKeySpec(ENC_KEY_BYTES.clone(), "RAW"), "BLAHBLAH", null,
+                new SecretKeySpec(MAC_KEY_BYTES.clone(), "RAW"), MAC_TAG, AUTHENTICATED_START,
+                ENCRYPTED_START, DATA_END);
+
+        assertFalse(params1.equals(params2));
+    }
+
+    public void testEquals_MacKey_Failure() throws Exception {
+        ContainerEncryptionParams params1 = new ContainerEncryptionParams(ENC_ALGORITHM,
+                ENC_PARAMS, ENC_KEY, MAC_ALGORITHM, null, MAC_KEY, MAC_TAG, AUTHENTICATED_START,
+                ENCRYPTED_START, DATA_END);
+
+        ContainerEncryptionParams params2 = new ContainerEncryptionParams(
+                new String(ENC_ALGORITHM), new IvParameterSpec(IV_BYTES.clone()),
+                new SecretKeySpec(ENC_KEY_BYTES.clone(), "RAW"), new String(MAC_ALGORITHM), null,
+                new SecretKeySpec("FAKE_MAC_KEY".getBytes(), "RAW"), MAC_TAG, AUTHENTICATED_START,
+                ENCRYPTED_START, DATA_END);
+
+        assertFalse(params1.equals(params2));
+    }
+
+    public void testEquals_MacTag_Failure() throws Exception {
+        ContainerEncryptionParams params1 = new ContainerEncryptionParams(ENC_ALGORITHM,
+                ENC_PARAMS, ENC_KEY, MAC_ALGORITHM, null, MAC_KEY, MAC_TAG, AUTHENTICATED_START,
+                ENCRYPTED_START, DATA_END);
+
+        ContainerEncryptionParams params2 = new ContainerEncryptionParams(
+                new String(ENC_ALGORITHM), new IvParameterSpec(IV_BYTES.clone()),
+                new SecretKeySpec(ENC_KEY_BYTES.clone(), "RAW"), new String(MAC_ALGORITHM), null,
+                new SecretKeySpec(MAC_KEY_BYTES.clone(), "RAW"), "broken".getBytes(),
+                AUTHENTICATED_START, ENCRYPTED_START, DATA_END);
+
+        assertFalse(params1.equals(params2));
+    }
+
+    public void testEquals_AuthenticatedStart_Failure() throws Exception {
+        ContainerEncryptionParams params1 = new ContainerEncryptionParams(ENC_ALGORITHM,
+                ENC_PARAMS, ENC_KEY, MAC_ALGORITHM, null, MAC_KEY, MAC_TAG, AUTHENTICATED_START,
+                ENCRYPTED_START, DATA_END);
+
+        ContainerEncryptionParams params2 = new ContainerEncryptionParams(
+                new String(ENC_ALGORITHM), new IvParameterSpec(IV_BYTES.clone()),
+                new SecretKeySpec(ENC_KEY_BYTES.clone(), "RAW"), new String(MAC_ALGORITHM), null,
+                new SecretKeySpec(MAC_KEY_BYTES.clone(), "RAW"), MAC_TAG, AUTHENTICATED_START - 1,
+                ENCRYPTED_START, DATA_END);
+
+        assertFalse(params1.equals(params2));
+    }
+
+    public void testEquals_EncryptedStart_Failure() throws Exception {
+        ContainerEncryptionParams params1 = new ContainerEncryptionParams(ENC_ALGORITHM,
+                ENC_PARAMS, ENC_KEY, MAC_ALGORITHM, null, MAC_KEY, MAC_TAG, AUTHENTICATED_START,
+                ENCRYPTED_START, DATA_END);
+
+        ContainerEncryptionParams params2 = new ContainerEncryptionParams(
+                new String(ENC_ALGORITHM), new IvParameterSpec(IV_BYTES.clone()),
+                new SecretKeySpec(ENC_KEY_BYTES.clone(), "RAW"), new String(MAC_ALGORITHM), null,
+                new SecretKeySpec(MAC_KEY_BYTES.clone(), "RAW"), MAC_TAG, AUTHENTICATED_START,
+                ENCRYPTED_START - 1, DATA_END);
+
+        assertFalse(params1.equals(params2));
+    }
+
+    public void testEquals_DataEnd_Failure() throws Exception {
+        ContainerEncryptionParams params1 = new ContainerEncryptionParams(ENC_ALGORITHM,
+                ENC_PARAMS, ENC_KEY, MAC_ALGORITHM, null, MAC_KEY, MAC_TAG, AUTHENTICATED_START,
+                ENCRYPTED_START, DATA_END);
+
+        ContainerEncryptionParams params2 = new ContainerEncryptionParams(
+                new String(ENC_ALGORITHM), new IvParameterSpec(IV_BYTES.clone()),
+                new SecretKeySpec(ENC_KEY_BYTES.clone(), "RAW"), new String(MAC_ALGORITHM), null,
+                new SecretKeySpec(MAC_KEY_BYTES.clone(), "RAW"), MAC_TAG, AUTHENTICATED_START,
+                ENCRYPTED_START, DATA_END + 1);
+
+        assertFalse(params1.equals(params2));
+    }
+
+    public void testHashCode_Success() throws Exception {
+        ContainerEncryptionParams params1 = new ContainerEncryptionParams(ENC_ALGORITHM,
+                ENC_PARAMS, ENC_KEY, MAC_ALGORITHM, null, MAC_KEY, MAC_TAG, AUTHENTICATED_START,
+                ENCRYPTED_START, DATA_END);
+
+        ContainerEncryptionParams params2 = new ContainerEncryptionParams(
+                new String(ENC_ALGORITHM), new IvParameterSpec(IV_BYTES.clone()),
+                new SecretKeySpec(ENC_KEY_BYTES.clone(), "RAW"), new String(MAC_ALGORITHM), null,
+                new SecretKeySpec(MAC_KEY_BYTES.clone(), "RAW"), MAC_TAG, AUTHENTICATED_START,
+                ENCRYPTED_START, DATA_END);
+
+        assertEquals(params1.hashCode(), params2.hashCode());
+    }
+
+    public void testHashCode_EncAlgo_Failure() throws Exception {
+        ContainerEncryptionParams params1 = new ContainerEncryptionParams(ENC_ALGORITHM,
+                ENC_PARAMS, ENC_KEY, MAC_ALGORITHM, null, MAC_KEY, MAC_TAG, AUTHENTICATED_START,
+                ENCRYPTED_START, DATA_END);
+
+        ContainerEncryptionParams params2 = new ContainerEncryptionParams(new String(
+                "AES-256/CBC/PKCS7Padding"), new IvParameterSpec(IV_BYTES.clone()),
+                new SecretKeySpec(ENC_KEY_BYTES.clone(), "RAW"), new String(MAC_ALGORITHM), null,
+                new SecretKeySpec(MAC_KEY_BYTES.clone(), "RAW"), MAC_TAG, AUTHENTICATED_START,
+                ENCRYPTED_START, DATA_END);
+
+        assertFalse(params1.hashCode() == params2.hashCode());
+    }
+
+    public void testHashCode_EncParams_Failure() throws Exception {
+        ContainerEncryptionParams params1 = new ContainerEncryptionParams(ENC_ALGORITHM,
+                ENC_PARAMS, ENC_KEY, MAC_ALGORITHM, null, MAC_KEY, MAC_TAG, AUTHENTICATED_START,
+                ENCRYPTED_START, DATA_END);
+
+        ContainerEncryptionParams params2 = new ContainerEncryptionParams(
+                new String(ENC_ALGORITHM), new IvParameterSpec("BLAHBLAH".getBytes()),
+                new SecretKeySpec(ENC_KEY_BYTES.clone(), "RAW"), new String(MAC_ALGORITHM), null,
+                new SecretKeySpec(MAC_KEY_BYTES.clone(), "RAW"), MAC_TAG, AUTHENTICATED_START,
+                ENCRYPTED_START, DATA_END);
+
+        assertFalse(params1.hashCode() == params2.hashCode());
+    }
+
+    public void testHashCode_EncKey_Failure() throws Exception {
+        ContainerEncryptionParams params1 = new ContainerEncryptionParams(ENC_ALGORITHM,
+                ENC_PARAMS, ENC_KEY, MAC_ALGORITHM, null, MAC_KEY, MAC_TAG, AUTHENTICATED_START,
+                ENCRYPTED_START, DATA_END);
+
+        ContainerEncryptionParams params2 = new ContainerEncryptionParams(
+                new String(ENC_ALGORITHM), new IvParameterSpec(IV_BYTES.clone()),
+                new SecretKeySpec("BLAHBLAH".getBytes(), "RAW"), new String(MAC_ALGORITHM), null,
+                new SecretKeySpec(MAC_KEY_BYTES.clone(), "RAW"), MAC_TAG, AUTHENTICATED_START,
+                ENCRYPTED_START, DATA_END);
+
+        assertFalse(params1.hashCode() == params2.hashCode());
+    }
+
+    public void testHashCode_MacAlgo_Failure() throws Exception {
+        ContainerEncryptionParams params1 = new ContainerEncryptionParams(ENC_ALGORITHM,
+                ENC_PARAMS, ENC_KEY, MAC_ALGORITHM, null, MAC_KEY, MAC_TAG, AUTHENTICATED_START,
+                ENCRYPTED_START, DATA_END);
+
+        ContainerEncryptionParams params2 = new ContainerEncryptionParams(
+                new String(ENC_ALGORITHM), new IvParameterSpec(IV_BYTES.clone()),
+                new SecretKeySpec(ENC_KEY_BYTES.clone(), "RAW"), "BLAHBLAH", null,
+                new SecretKeySpec(MAC_KEY_BYTES.clone(), "RAW"), MAC_TAG, AUTHENTICATED_START,
+                ENCRYPTED_START, DATA_END);
+
+        assertFalse(params1.hashCode() == params2.hashCode());
+    }
+
+    public void testHashCode_MacKey_Failure() throws Exception {
+        ContainerEncryptionParams params1 = new ContainerEncryptionParams(ENC_ALGORITHM,
+                ENC_PARAMS, ENC_KEY, MAC_ALGORITHM, null, MAC_KEY, MAC_TAG, AUTHENTICATED_START,
+                ENCRYPTED_START, DATA_END);
+
+        ContainerEncryptionParams params2 = new ContainerEncryptionParams(
+                new String(ENC_ALGORITHM), new IvParameterSpec(IV_BYTES.clone()),
+                new SecretKeySpec(ENC_KEY_BYTES.clone(), "RAW"), new String(MAC_ALGORITHM), null,
+                new SecretKeySpec("FAKE_MAC_KEY".getBytes(), "RAW"), MAC_TAG, AUTHENTICATED_START,
+                ENCRYPTED_START, DATA_END);
+
+        assertFalse(params1.hashCode() == params2.hashCode());
+    }
+
+    public void testHashCode_MacTag_Failure() throws Exception {
+        ContainerEncryptionParams params1 = new ContainerEncryptionParams(ENC_ALGORITHM,
+                ENC_PARAMS, ENC_KEY, MAC_ALGORITHM, null, MAC_KEY, MAC_TAG, AUTHENTICATED_START,
+                ENCRYPTED_START, DATA_END);
+
+        ContainerEncryptionParams params2 = new ContainerEncryptionParams(
+                new String(ENC_ALGORITHM), new IvParameterSpec(IV_BYTES.clone()),
+                new SecretKeySpec(ENC_KEY_BYTES.clone(), "RAW"), new String(MAC_ALGORITHM), null,
+                new SecretKeySpec(MAC_KEY_BYTES.clone(), "RAW"), "broken".getBytes(),
+                AUTHENTICATED_START, ENCRYPTED_START, DATA_END);
+
+        assertFalse(params1.hashCode() == params2.hashCode());
+    }
+
+    public void testHashCode_AuthenticatedStart_Failure() throws Exception {
+        ContainerEncryptionParams params1 = new ContainerEncryptionParams(ENC_ALGORITHM,
+                ENC_PARAMS, ENC_KEY, MAC_ALGORITHM, null, MAC_KEY, MAC_TAG, AUTHENTICATED_START,
+                ENCRYPTED_START, DATA_END);
+
+        ContainerEncryptionParams params2 = new ContainerEncryptionParams(
+                new String(ENC_ALGORITHM), new IvParameterSpec(IV_BYTES.clone()),
+                new SecretKeySpec(ENC_KEY_BYTES.clone(), "RAW"), new String(MAC_ALGORITHM), null,
+                new SecretKeySpec(MAC_KEY_BYTES.clone(), "RAW"), MAC_TAG, AUTHENTICATED_START - 1,
+                ENCRYPTED_START, DATA_END);
+
+        assertFalse(params1.hashCode() == params2.hashCode());
+    }
+
+    public void testHashCode_EncryptedStart_Failure() throws Exception {
+        ContainerEncryptionParams params1 = new ContainerEncryptionParams(ENC_ALGORITHM,
+                ENC_PARAMS, ENC_KEY, MAC_ALGORITHM, null, MAC_KEY, MAC_TAG, AUTHENTICATED_START,
+                ENCRYPTED_START, DATA_END);
+
+        ContainerEncryptionParams params2 = new ContainerEncryptionParams(
+                new String(ENC_ALGORITHM), new IvParameterSpec(IV_BYTES.clone()),
+                new SecretKeySpec(ENC_KEY_BYTES.clone(), "RAW"), new String(MAC_ALGORITHM), null,
+                new SecretKeySpec(MAC_KEY_BYTES.clone(), "RAW"), MAC_TAG, AUTHENTICATED_START,
+                ENCRYPTED_START - 1, DATA_END);
+
+        assertFalse(params1.hashCode() == params2.hashCode());
+    }
+
+    public void testHashCode_DataEnd_Failure() throws Exception {
+        ContainerEncryptionParams params1 = new ContainerEncryptionParams(ENC_ALGORITHM,
+                ENC_PARAMS, ENC_KEY, MAC_ALGORITHM, null, MAC_KEY, MAC_TAG, AUTHENTICATED_START,
+                ENCRYPTED_START, DATA_END);
+
+        ContainerEncryptionParams params2 = new ContainerEncryptionParams(
+                new String(ENC_ALGORITHM), new IvParameterSpec(IV_BYTES.clone()),
+                new SecretKeySpec(ENC_KEY_BYTES.clone(), "RAW"), new String(MAC_ALGORITHM), null,
+                new SecretKeySpec(MAC_KEY_BYTES.clone(), "RAW"), MAC_TAG, AUTHENTICATED_START,
+                ENCRYPTED_START, DATA_END + 1);
+
+        assertFalse(params1.hashCode() == params2.hashCode());
+    }
+}
diff --git a/core/tests/coretests/src/android/content/pm/LimitedLengthInputStreamTest.java b/core/tests/coretests/src/android/content/pm/LimitedLengthInputStreamTest.java
new file mode 100644
index 0000000..0a0152b
--- /dev/null
+++ b/core/tests/coretests/src/android/content/pm/LimitedLengthInputStreamTest.java
@@ -0,0 +1,186 @@
+/*
+ * 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.content.pm;
+
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.MediumTest;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Arrays;
+
+public class LimitedLengthInputStreamTest extends AndroidTestCase {
+    private final byte[] TEST_STRING1 = "This is a test".getBytes();
+
+    private InputStream mTestStream1;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        mTestStream1 = new ByteArrayInputStream(TEST_STRING1);
+    }
+
+    @MediumTest
+    public void testConstructor_NegativeOffset_Failure() throws Exception {
+        try {
+            InputStream is = new LimitedLengthInputStream(mTestStream1, -1, TEST_STRING1.length);
+            fail("Should throw IOException on negative index");
+        } catch (IOException e) {
+            // success
+        }
+    }
+
+    @MediumTest
+    public void testConstructor_NegativeLength_Failure() throws Exception {
+        try {
+            InputStream is = new LimitedLengthInputStream(mTestStream1, 0, -1);
+            fail("Should throw IOException on negative length");
+        } catch (IOException e) {
+            // success
+        }
+    }
+
+    @MediumTest
+    public void testConstructor_NullInputStream_Failure() throws Exception {
+        try {
+            InputStream is = new LimitedLengthInputStream(null, 0, 1);
+            fail("Should throw IOException on null input stream");
+        } catch (IOException e) {
+            // success
+        }
+    }
+
+    private void checkReadBytesWithOffsetAndLength_WithString1(int offset, int length)
+            throws Exception {
+        byte[] temp = new byte[TEST_STRING1.length];
+        byte[] expected = new byte[length];
+        byte[] actual = new byte[length];
+
+        System.arraycopy(TEST_STRING1, offset, expected, 0, length);
+
+        InputStream is = new LimitedLengthInputStream(mTestStream1, offset, length);
+        assertEquals(length, is.read(temp, 0, temp.length));
+
+        System.arraycopy(temp, 0, actual, 0, length);
+        assertTrue(Arrays.equals(expected, actual));
+
+        assertEquals(-1, is.read(temp, 0, temp.length));
+    }
+
+    @MediumTest
+    public void testReadBytesWithOffsetAndLength_ZeroOffset_PartialLength_Success()
+            throws Exception {
+        checkReadBytesWithOffsetAndLength_WithString1(0, 2);
+    }
+
+    @MediumTest
+    public void testReadBytesWithOffsetAndLength_NonZeroOffset_PartialLength_Success()
+            throws Exception {
+        checkReadBytesWithOffsetAndLength_WithString1(3, 2);
+    }
+
+    @MediumTest
+    public void testReadBytesWithOffsetAndLength_ZeroOffset_FullLength_Success() throws Exception {
+        checkReadBytesWithOffsetAndLength_WithString1(0, TEST_STRING1.length);
+    }
+
+    @MediumTest
+    public void testReadBytesWithOffsetAndLength_NonZeroOffset_FullLength_Success()
+            throws Exception {
+        checkReadBytesWithOffsetAndLength_WithString1(3, TEST_STRING1.length - 3);
+    }
+
+    @MediumTest
+    public void testReadBytesWithOffsetAndLength_ZeroOffset_PastEnd_Success() throws Exception {
+        byte[] temp = new byte[TEST_STRING1.length + 10];
+        InputStream is = new LimitedLengthInputStream(mTestStream1, 0, TEST_STRING1.length + 10);
+        assertEquals(TEST_STRING1.length, is.read(temp, 0, TEST_STRING1.length + 10));
+
+        byte[] actual = new byte[TEST_STRING1.length];
+        System.arraycopy(temp, 0, actual, 0, actual.length);
+        assertTrue(Arrays.equals(TEST_STRING1, actual));
+    }
+
+    private void checkReadBytes_WithString1(int offset, int length) throws Exception {
+        byte[] temp = new byte[TEST_STRING1.length];
+        byte[] expected = new byte[length];
+        byte[] actual = new byte[length];
+
+        System.arraycopy(TEST_STRING1, offset, expected, 0, length);
+
+        InputStream is = new LimitedLengthInputStream(mTestStream1, offset, length);
+        assertEquals(length, is.read(temp));
+
+        System.arraycopy(temp, 0, actual, 0, length);
+        assertTrue(Arrays.equals(expected, actual));
+
+        assertEquals(-1, is.read(temp));
+    }
+
+    @MediumTest
+    public void testReadBytes_ZeroOffset_PartialLength_Success() throws Exception {
+        checkReadBytesWithOffsetAndLength_WithString1(0, 2);
+    }
+
+    @MediumTest
+    public void testReadBytes_NonZeroOffset_PartialLength_Success() throws Exception {
+        checkReadBytesWithOffsetAndLength_WithString1(3, 2);
+    }
+
+    @MediumTest
+    public void testReadBytes_ZeroOffset_FullLength_Success() throws Exception {
+        checkReadBytesWithOffsetAndLength_WithString1(0, TEST_STRING1.length);
+    }
+
+    @MediumTest
+    public void testReadBytes_NonZeroOffset_FullLength_Success() throws Exception {
+        checkReadBytesWithOffsetAndLength_WithString1(3, TEST_STRING1.length - 3);
+    }
+
+    private void checkSingleByteRead_WithString1(int offset, int length) throws Exception {
+        InputStream is = new LimitedLengthInputStream(mTestStream1, offset, length);
+
+        for (int i = 0; i < length; i++) {
+            assertEquals(TEST_STRING1[offset + i], is.read());
+        }
+
+        assertEquals(-1, is.read());
+    }
+
+    @MediumTest
+    public void testSingleByteRead_ZeroOffset_PartialLength_Success() throws Exception {
+        checkSingleByteRead_WithString1(0, 2);
+    }
+
+    @MediumTest
+    public void testSingleByteRead_NonZeroOffset_PartialLength_Success() throws Exception {
+        checkSingleByteRead_WithString1(3, 2);
+    }
+
+    @MediumTest
+    public void testSingleByteRead_ZeroOffset_FullLength_Success() throws Exception {
+        checkSingleByteRead_WithString1(0, TEST_STRING1.length);
+    }
+
+    @MediumTest
+    public void testSingleByteRead_NonZeroOffset_FullLength_Success() throws Exception {
+        checkSingleByteRead_WithString1(3, TEST_STRING1.length - 3);
+    }
+
+}
diff --git a/core/tests/coretests/src/android/content/pm/MacAuthenticatedInputStreamTest.java b/core/tests/coretests/src/android/content/pm/MacAuthenticatedInputStreamTest.java
new file mode 100644
index 0000000..948e722
--- /dev/null
+++ b/core/tests/coretests/src/android/content/pm/MacAuthenticatedInputStreamTest.java
@@ -0,0 +1,120 @@
+/*
+ * 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.content.pm;
+
+import android.test.AndroidTestCase;
+
+import java.io.ByteArrayInputStream;
+import java.util.Arrays;
+
+import javax.crypto.Mac;
+import javax.crypto.SecretKey;
+import javax.crypto.spec.SecretKeySpec;
+
+import libcore.io.Streams;
+
+public class MacAuthenticatedInputStreamTest extends AndroidTestCase {
+
+    private static final SecretKey HMAC_KEY_1 = new SecretKeySpec("test_key_1".getBytes(), "HMAC");
+
+    private static final byte[] TEST_STRING_1 = "Hello, World!".getBytes();
+
+    /**
+     * Generated with:
+     *
+     * echo -n 'Hello, World!' | openssl dgst -hmac 'test_key_1' -binary -sha1 | recode ..//x1 |
+     *   sed 's/0x/(byte) 0x/g'
+     */
+    private static final byte[] TEST_STRING_1_MAC = {
+            (byte) 0x29, (byte) 0xB1, (byte) 0x87, (byte) 0x6B, (byte) 0xFE, (byte) 0x83,
+            (byte) 0x96, (byte) 0x51, (byte) 0x61, (byte) 0x02, (byte) 0xAF, (byte) 0x7B,
+            (byte) 0xBA, (byte) 0x05, (byte) 0xE6, (byte) 0xA4, (byte) 0xAB, (byte) 0x36,
+            (byte) 0x18, (byte) 0x02
+    };
+
+    /**
+     * Same as TEST_STRING_1_MAC but with the first byte as 0x28 instead of
+     * 0x29.
+     */
+    private static final byte[] TEST_STRING_1_MAC_BROKEN = {
+            (byte) 0x28, (byte) 0xB1, (byte) 0x87, (byte) 0x6B, (byte) 0xFE, (byte) 0x83,
+            (byte) 0x96, (byte) 0x51, (byte) 0x61, (byte) 0x02, (byte) 0xAF, (byte) 0x7B,
+            (byte) 0xBA, (byte) 0x05, (byte) 0xE6, (byte) 0xA4, (byte) 0xAB, (byte) 0x36,
+            (byte) 0x18, (byte) 0x02
+    };
+
+    private ByteArrayInputStream mTestStream1;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        mTestStream1 = new ByteArrayInputStream(TEST_STRING_1);
+    }
+
+    public void testString1Authenticate_Success() throws Exception {
+        Mac mac = Mac.getInstance("HMAC-SHA1");
+        mac.init(HMAC_KEY_1);
+
+        MacAuthenticatedInputStream is = new MacAuthenticatedInputStream(mTestStream1, mac);
+
+        assertTrue(Arrays.equals(TEST_STRING_1, Streams.readFully(is)));
+
+        assertTrue(is.isTagEqual(TEST_STRING_1_MAC));
+    }
+
+    public void testString1Authenticate_WrongTag_Failure() throws Exception {
+        Mac mac = Mac.getInstance("HMAC-SHA1");
+        mac.init(HMAC_KEY_1);
+
+        MacAuthenticatedInputStream is = new MacAuthenticatedInputStream(mTestStream1, mac);
+
+        assertTrue(Arrays.equals(TEST_STRING_1, Streams.readFully(is)));
+
+        assertFalse(is.isTagEqual(TEST_STRING_1_MAC_BROKEN));
+    }
+
+    public void testString1Authenticate_NullTag_Failure() throws Exception {
+        Mac mac = Mac.getInstance("HMAC-SHA1");
+        mac.init(HMAC_KEY_1);
+
+        MacAuthenticatedInputStream is = new MacAuthenticatedInputStream(mTestStream1, mac);
+
+        assertTrue(Arrays.equals(TEST_STRING_1, Streams.readFully(is)));
+
+        assertFalse(is.isTagEqual(null));
+    }
+
+    public void testString1Authenticate_ReadSingleByte_Success() throws Exception {
+        Mac mac = Mac.getInstance("HMAC-SHA1");
+        mac.init(HMAC_KEY_1);
+
+        MacAuthenticatedInputStream is = new MacAuthenticatedInputStream(mTestStream1, mac);
+
+        int numRead = 0;
+        while (is.read() != -1) {
+            numRead++;
+
+            if (numRead > TEST_STRING_1.length) {
+                fail("read too many bytes");
+            }
+        }
+        assertEquals(TEST_STRING_1.length, numRead);
+
+        assertTrue(is.isTagEqual(TEST_STRING_1_MAC));
+    }
+}
diff --git a/drm/java/android/drm/DrmManagerClient.java b/drm/java/android/drm/DrmManagerClient.java
index 482ab0a..4b51994 100755
--- a/drm/java/android/drm/DrmManagerClient.java
+++ b/drm/java/android/drm/DrmManagerClient.java
@@ -242,6 +242,7 @@
     public DrmManagerClient(Context context) {
         mContext = context;
         mReleased = false;
+        createEventThreads();
 
         // save the unique id
         mUniqueId = _initialize();
@@ -283,21 +284,6 @@
         _release(mUniqueId);
     }
 
-
-    private void createListeners() {
-        if (mEventHandler == null && mInfoHandler == null) {
-            mInfoThread = new HandlerThread("DrmManagerClient.InfoHandler");
-            mInfoThread.start();
-            mInfoHandler = new InfoHandler(mInfoThread.getLooper());
-
-            mEventThread = new HandlerThread("DrmManagerClient.EventHandler");
-            mEventThread.start();
-            mEventHandler = new EventHandler(mEventThread.getLooper());
-            _setListeners(mUniqueId, new WeakReference<DrmManagerClient>(this));
-        }
-    }
-
-
     /**
      * Registers an {@link DrmManagerClient.OnInfoListener} callback, which is invoked when the 
      * DRM framework sends status or warning information during registration or rights acquisition.
@@ -878,5 +864,21 @@
     private native DrmConvertedStatus _closeConvertSession(int uniqueId, int convertId);
 
     private native DrmSupportInfo[] _getAllSupportInfo(int uniqueId);
+
+    private void createEventThreads() {
+        if (mEventHandler == null && mInfoHandler == null) {
+            mInfoThread = new HandlerThread("DrmManagerClient.InfoHandler");
+            mInfoThread.start();
+            mInfoHandler = new InfoHandler(mInfoThread.getLooper());
+
+            mEventThread = new HandlerThread("DrmManagerClient.EventHandler");
+            mEventThread.start();
+            mEventHandler = new EventHandler(mEventThread.getLooper());
+        }
+    }
+
+    private void createListeners() {
+        _setListeners(mUniqueId, new WeakReference<DrmManagerClient>(this));
+    }
 }
 
diff --git a/graphics/java/android/graphics/Canvas.java b/graphics/java/android/graphics/Canvas.java
index 7e92973..3949afd 100644
--- a/graphics/java/android/graphics/Canvas.java
+++ b/graphics/java/android/graphics/Canvas.java
@@ -1617,6 +1617,13 @@
      */
     public static native void freeCaches();
 
+    /**
+     * Free up text layout caches
+     *
+     * @hide
+     */
+    public static native void freeTextLayoutCaches();
+
     private static native int initRaster(int nativeBitmapOrZero);
     private static native void native_setBitmap(int nativeCanvas, int bitmap);
     private static native int native_saveLayer(int nativeCanvas, RectF bounds,
diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java
index 1dbd48e..2debd57 100644
--- a/media/java/android/media/MediaCodec.java
+++ b/media/java/android/media/MediaCodec.java
@@ -94,6 +94,11 @@
  * be codec specific data marked as such using the flag {@link #BUFFER_FLAG_CODEC_CONFIG}
  * in a call to {@link #queueInputBuffer}.
  *
+ * Codec specific data included in the format passed to {@link #configure}
+ * (in ByteBuffer entries with keys "csd-0", "csd-1", ...) is automatically
+ * submitted to the codec, this data MUST NOT be submitted explicitly by the
+ * client.
+ *
  * Once the client reaches the end of the input data it signals the end of
  * the input stream by specifying a flag of {@link #BUFFER_FLAG_END_OF_STREAM} in the call to
  * {@link #queueInputBuffer}. The codec will continue to return output buffers
diff --git a/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java b/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
index c709e40..17e5f4e 100644
--- a/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
+++ b/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
@@ -22,7 +22,10 @@
 
 import android.app.IntentService;
 import android.content.Intent;
+import android.content.pm.MacAuthenticatedInputStream;
+import android.content.pm.ContainerEncryptionParams;
 import android.content.pm.IPackageManager;
+import android.content.pm.LimitedLengthInputStream;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageInfoLite;
 import android.content.pm.PackageManager;
@@ -49,9 +52,21 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
+import java.security.DigestException;
+import java.security.GeneralSecurityException;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+
+import javax.crypto.Cipher;
+import javax.crypto.CipherInputStream;
+import javax.crypto.Mac;
+import javax.crypto.NoSuchPaddingException;
 
 import libcore.io.ErrnoException;
+import libcore.io.IoUtils;
 import libcore.io.Libcore;
+import libcore.io.Streams;
 import libcore.io.StructStatFs;
 
 /*
@@ -68,7 +83,7 @@
     private static final String LIB_DIR_NAME = "lib";
 
     private IMediaContainerService.Stub mBinder = new IMediaContainerService.Stub() {
-        /*
+        /**
          * Creates a new container and copies resource there.
          * @param paackageURI the uri of resource to be copied. Can be either
          * a content uri or a file uri
@@ -92,15 +107,19 @@
                     isExternal, isForwardLocked);
         }
 
-        /*
+        /**
          * Copy specified resource to output stream
+         *
          * @param packageURI the uri of resource to be copied. Should be a file
-         * uri
+         *            uri
+         * @param encryptionParams parameters describing the encryption used for
+         *            this file
          * @param outStream Remote file descriptor to be used for copying
-         * @return returns status code according to those in {@link
-         * PackageManager}
+         * @return returns status code according to those in
+         *         {@link PackageManager}
          */
-        public int copyResource(final Uri packageURI, ParcelFileDescriptor outStream) {
+        public int copyResource(final Uri packageURI, ContainerEncryptionParams encryptionParams,
+                ParcelFileDescriptor outStream) {
             if (packageURI == null || outStream == null) {
                 return PackageManager.INSTALL_FAILED_INVALID_URI;
             }
@@ -109,7 +128,7 @@
                     = new ParcelFileDescriptor.AutoCloseOutputStream(outStream);
 
             try {
-                copyFile(packageURI, autoOut);
+                copyFile(packageURI, autoOut, encryptionParams);
                 return PackageManager.INSTALL_SUCCEEDED;
             } catch (FileNotFoundException e) {
                 Slog.e(TAG, "Could not copy URI " + packageURI.toString() + " FNF: "
@@ -119,10 +138,14 @@
                 Slog.e(TAG, "Could not copy URI " + packageURI.toString() + " IO: "
                         + e.getMessage());
                 return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
+            } catch (DigestException e) {
+                Slog.e(TAG, "Could not copy URI " + packageURI.toString() + " Security: "
+                                + e.getMessage());
+                return PackageManager.INSTALL_FAILED_INVALID_APK;
             }
         }
 
-        /*
+        /**
          * Determine the recommended install location for package
          * specified by file uri location.
          * @param fileUri the uri of resource to be copied. Should be a
@@ -130,28 +153,24 @@
          * @return Returns PackageInfoLite object containing
          * the package info and recommended app location.
          */
-        public PackageInfoLite getMinimalPackageInfo(final Uri fileUri, int flags, long threshold) {
+        public PackageInfoLite getMinimalPackageInfo(final String packagePath, int flags,
+                long threshold) {
             PackageInfoLite ret = new PackageInfoLite();
-            if (fileUri == null) {
-                Slog.i(TAG, "Invalid package uri " + fileUri);
+
+            if (packagePath == null) {
+                Slog.i(TAG, "Invalid package file " + packagePath);
                 ret.recommendedInstallLocation = PackageHelper.RECOMMEND_FAILED_INVALID_APK;
                 return ret;
             }
-            String scheme = fileUri.getScheme();
-            if (scheme != null && !scheme.equals("file")) {
-                Slog.w(TAG, "Falling back to installing on internal storage only");
-                ret.recommendedInstallLocation = PackageHelper.RECOMMEND_INSTALL_INTERNAL;
-                return ret;
-            }
-            String archiveFilePath = fileUri.getPath();
+
             DisplayMetrics metrics = new DisplayMetrics();
             metrics.setToDefaults();
 
-            PackageParser.PackageLite pkg = PackageParser.parsePackageLite(archiveFilePath, 0);
+            PackageParser.PackageLite pkg = PackageParser.parsePackageLite(packagePath, 0);
             if (pkg == null) {
                 Slog.w(TAG, "Failed to parse package");
 
-                final File apkFile = new File(archiveFilePath);
+                final File apkFile = new File(packagePath);
                 if (!apkFile.exists()) {
                     ret.recommendedInstallLocation = PackageHelper.RECOMMEND_FAILED_INVALID_URI;
                 } else {
@@ -160,12 +179,13 @@
 
                 return ret;
             }
+
             ret.packageName = pkg.packageName;
             ret.installLocation = pkg.installLocation;
             ret.verifiers = pkg.verifiers;
 
             ret.recommendedInstallLocation = recommendAppInstallLocation(pkg.installLocation,
-                    archiveFilePath, flags, threshold);
+                    packagePath, flags, threshold);
 
             return ret;
         }
@@ -392,55 +412,195 @@
         }
     }
 
-    private static void copyToFile(File srcFile, OutputStream out)
-            throws FileNotFoundException, IOException {
-        InputStream inputStream = new BufferedInputStream(new FileInputStream(srcFile));
+    private void copyFile(Uri pPackageURI, OutputStream outStream,
+            ContainerEncryptionParams encryptionParams) throws FileNotFoundException, IOException,
+            DigestException {
+        String scheme = pPackageURI.getScheme();
+        InputStream inStream = null;
         try {
-            copyToFile(inputStream, out);
+            if (scheme == null || scheme.equals("file")) {
+                final InputStream is = new FileInputStream(new File(pPackageURI.getPath()));
+                inStream = new BufferedInputStream(is);
+            } else if (scheme.equals("content")) {
+                final ParcelFileDescriptor fd;
+                try {
+                    fd = getContentResolver().openFileDescriptor(pPackageURI, "r");
+                } catch (FileNotFoundException e) {
+                    Slog.e(TAG, "Couldn't open file descriptor from download service. "
+                            + "Failed with exception " + e);
+                    throw e;
+                }
+
+                if (fd == null) {
+                    Slog.e(TAG, "Provider returned no file descriptor for " +
+                            pPackageURI.toString());
+                    throw new FileNotFoundException("provider returned no file descriptor");
+                } else {
+                    if (localLOGV) {
+                        Slog.i(TAG, "Opened file descriptor from download service.");
+                    }
+                    inStream = new ParcelFileDescriptor.AutoCloseInputStream(fd);
+                }
+            } else {
+                Slog.e(TAG, "Package URI is not 'file:' or 'content:' - " + pPackageURI);
+                throw new FileNotFoundException("Package URI is not 'file:' or 'content:'");
+            }
+
+            /*
+             * If this resource is encrypted, get the decrypted stream version
+             * of it.
+             */
+            ApkContainer container = new ApkContainer(inStream, encryptionParams);
+
+            try {
+                /*
+                 * We copy the source package file to a temp file and then
+                 * rename it to the destination file in order to eliminate a
+                 * window where the package directory scanner notices the new
+                 * package file but it's not completely copied yet.
+                 */
+                copyToFile(container.getInputStream(), outStream);
+
+                if (!container.isAuthenticated()) {
+                    throw new DigestException();
+                }
+            } catch (GeneralSecurityException e) {
+                throw new DigestException("A problem occured copying the file.");
+            }
         } finally {
-            try { inputStream.close(); } catch (IOException e) {}
+            IoUtils.closeQuietly(inStream);
         }
     }
 
-    private void copyFile(Uri pPackageURI, OutputStream outStream) throws FileNotFoundException,
-            IOException {
-        String scheme = pPackageURI.getScheme();
-        if (scheme == null || scheme.equals("file")) {
-            final File srcPackageFile = new File(pPackageURI.getPath());
-            // We copy the source package file to a temp file and then rename it to the
-            // destination file in order to eliminate a window where the package directory
-            // scanner notices the new package file but it's not completely copied yet.
-            copyToFile(srcPackageFile, outStream);
-        } else if (scheme.equals("content")) {
-            ParcelFileDescriptor fd = null;
-            try {
-                fd = getContentResolver().openFileDescriptor(pPackageURI, "r");
-            } catch (FileNotFoundException e) {
-                Slog.e(TAG, "Couldn't open file descriptor from download service. "
-                        + "Failed with exception " + e);
-                throw e;
-            }
+    private static class ApkContainer {
+        private final InputStream mInStream;
 
-            if (fd == null) {
-                Slog.e(TAG, "Provider returned no file descriptor for " + pPackageURI.toString());
-                throw new FileNotFoundException("provider returned no file descriptor");
+        private MacAuthenticatedInputStream mAuthenticatedStream;
+
+        private byte[] mTag;
+
+        public ApkContainer(InputStream inStream, ContainerEncryptionParams encryptionParams)
+                throws IOException {
+            if (encryptionParams == null) {
+                mInStream = inStream;
             } else {
-                if (localLOGV) {
-                    Slog.i(TAG, "Opened file descriptor from download service.");
-                }
-                ParcelFileDescriptor.AutoCloseInputStream dlStream
-                        = new ParcelFileDescriptor.AutoCloseInputStream(fd);
-
-                // We copy the source package file to a temp file and then rename it to the
-                // destination file in order to eliminate a window where the package directory
-                // scanner notices the new package file but it's not completely
-                // copied
-                copyToFile(dlStream, outStream);
+                mInStream = getDecryptedStream(inStream, encryptionParams);
+                mTag = encryptionParams.getMacTag();
             }
-        } else {
-            Slog.e(TAG, "Package URI is not 'file:' or 'content:' - " + pPackageURI);
-            throw new FileNotFoundException("Package URI is not 'file:' or 'content:'");
         }
+
+        public boolean isAuthenticated() {
+            if (mAuthenticatedStream == null) {
+                return true;
+            }
+
+            return mAuthenticatedStream.isTagEqual(mTag);
+        }
+
+        private Mac getMacInstance(ContainerEncryptionParams encryptionParams) throws IOException {
+            final Mac m;
+            try {
+                final String macAlgo = encryptionParams.getMacAlgorithm();
+
+                if (macAlgo != null) {
+                    m = Mac.getInstance(macAlgo);
+                    m.init(encryptionParams.getMacKey(), encryptionParams.getMacSpec());
+                } else {
+                    m = null;
+                }
+
+                return m;
+            } catch (NoSuchAlgorithmException e) {
+                throw new IOException(e);
+            } catch (InvalidKeyException e) {
+                throw new IOException(e);
+            } catch (InvalidAlgorithmParameterException e) {
+                throw new IOException(e);
+            }
+        }
+
+        public InputStream getInputStream() {
+            return mInStream;
+        }
+
+        private InputStream getDecryptedStream(InputStream inStream,
+                ContainerEncryptionParams encryptionParams) throws IOException {
+            final Cipher c;
+            try {
+                c = Cipher.getInstance(encryptionParams.getEncryptionAlgorithm());
+                c.init(Cipher.DECRYPT_MODE, encryptionParams.getEncryptionKey(),
+                        encryptionParams.getEncryptionSpec());
+            } catch (NoSuchAlgorithmException e) {
+                throw new IOException(e);
+            } catch (NoSuchPaddingException e) {
+                throw new IOException(e);
+            } catch (InvalidKeyException e) {
+                throw new IOException(e);
+            } catch (InvalidAlgorithmParameterException e) {
+                throw new IOException(e);
+            }
+
+            final int encStart = encryptionParams.getEncryptedDataStart();
+            final int end = encryptionParams.getDataEnd();
+            if (end < encStart) {
+                throw new IOException("end <= encStart");
+            }
+
+            final Mac mac = getMacInstance(encryptionParams);
+            if (mac != null) {
+                final int macStart = encryptionParams.getAuthenticatedDataStart();
+
+                final int furtherOffset;
+                if (macStart >= 0 && encStart >= 0 && macStart < encStart) {
+                    /*
+                     * If there is authenticated data at the beginning, read
+                     * that into our MAC first.
+                     */
+                    final int authenticatedLength = encStart - macStart;
+                    final byte[] authenticatedData = new byte[authenticatedLength];
+
+                    Streams.readFully(inStream, authenticatedData, macStart, authenticatedLength);
+                    mac.update(authenticatedData, 0, authenticatedLength);
+
+                    furtherOffset = 0;
+                } else {
+                    /*
+                     * No authenticated data at the beginning. Just skip the
+                     * required number of bytes to the beginning of the stream.
+                     */
+                    if (encStart > 0) {
+                        furtherOffset = encStart;
+                    } else {
+                        furtherOffset = 0;
+                    }
+                }
+
+                /*
+                 * If there is data at the end of the stream we want to ignore,
+                 * wrap this in a LimitedLengthInputStream.
+                 */
+                if (furtherOffset >= 0 && end > furtherOffset) {
+                    inStream = new LimitedLengthInputStream(inStream, furtherOffset, end - encStart);
+                } else if (furtherOffset > 0) {
+                    inStream.skip(furtherOffset);
+                }
+
+                mAuthenticatedStream = new MacAuthenticatedInputStream(inStream, mac);
+
+                inStream = mAuthenticatedStream;
+            } else {
+                if (encStart >= 0) {
+                    if (end > encStart) {
+                        inStream = new LimitedLengthInputStream(inStream, encStart, end - encStart);
+                    } else {
+                        inStream.skip(encStart);
+                    }
+                }
+            }
+
+            return new CipherInputStream(inStream, c);
+        }
+
     }
 
     private static final int PREFER_INTERNAL = 1;
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_notify_clear_normal.png b/packages/SystemUI/res/drawable-hdpi/ic_notify_clear_normal.png
index babddb1..a54761f 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_notify_clear_normal.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_notify_clear_normal.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_notify_clear_pressed.png b/packages/SystemUI/res/drawable-hdpi/ic_notify_clear_pressed.png
index 56cd6f9..f3f336c 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_notify_clear_pressed.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_notify_clear_pressed.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_notify_quicksettings_normal.png b/packages/SystemUI/res/drawable-hdpi/ic_notify_quicksettings_normal.png
index 23ce001..3ed7418 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_notify_quicksettings_normal.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_notify_quicksettings_normal.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_notify_quicksettings_pressed.png b/packages/SystemUI/res/drawable-hdpi/ic_notify_quicksettings_pressed.png
index d0754a39..5e20eea 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_notify_quicksettings_pressed.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_notify_quicksettings_pressed.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_notify_rotation_off_normal.png b/packages/SystemUI/res/drawable-hdpi/ic_notify_rotation_off_normal.png
new file mode 100644
index 0000000..4ca1ab8
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_notify_rotation_off_normal.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_notify_rotation_off_pressed.png b/packages/SystemUI/res/drawable-hdpi/ic_notify_rotation_off_pressed.png
new file mode 100644
index 0000000..85a4cd2
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_notify_rotation_off_pressed.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_notify_rotation_on_normal.png b/packages/SystemUI/res/drawable-hdpi/ic_notify_rotation_on_normal.png
new file mode 100644
index 0000000..d0cb087
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_notify_rotation_on_normal.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_notify_rotation_on_pressed.png b/packages/SystemUI/res/drawable-hdpi/ic_notify_rotation_on_pressed.png
new file mode 100644
index 0000000..c1c9e16
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_notify_rotation_on_pressed.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_notify_clear_normal.png b/packages/SystemUI/res/drawable-mdpi/ic_notify_clear_normal.png
index bf1bad5..b44b527 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_notify_clear_normal.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_notify_clear_normal.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_notify_clear_pressed.png b/packages/SystemUI/res/drawable-mdpi/ic_notify_clear_pressed.png
index 320d92d..94c8165 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_notify_clear_pressed.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_notify_clear_pressed.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_notify_quicksettings_normal.png b/packages/SystemUI/res/drawable-mdpi/ic_notify_quicksettings_normal.png
index b58e4dc..44cfc5b 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_notify_quicksettings_normal.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_notify_quicksettings_normal.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_notify_quicksettings_pressed.png b/packages/SystemUI/res/drawable-mdpi/ic_notify_quicksettings_pressed.png
index 604eb75..0c3fdcd 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_notify_quicksettings_pressed.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_notify_quicksettings_pressed.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_notify_rotation_off_normal.png b/packages/SystemUI/res/drawable-mdpi/ic_notify_rotation_off_normal.png
new file mode 100644
index 0000000..77da014
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_notify_rotation_off_normal.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_notify_rotation_off_pressed.png b/packages/SystemUI/res/drawable-mdpi/ic_notify_rotation_off_pressed.png
new file mode 100644
index 0000000..f132d5c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_notify_rotation_off_pressed.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_notify_rotation_on_normal.png b/packages/SystemUI/res/drawable-mdpi/ic_notify_rotation_on_normal.png
new file mode 100644
index 0000000..1637209
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_notify_rotation_on_normal.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_notify_rotation_on_pressed.png b/packages/SystemUI/res/drawable-mdpi/ic_notify_rotation_on_pressed.png
new file mode 100644
index 0000000..4d8fbde
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_notify_rotation_on_pressed.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_notify_clear_normal.png b/packages/SystemUI/res/drawable-xhdpi/ic_notify_clear_normal.png
index cf9bd8e..870beb4 100644
--- a/packages/SystemUI/res/drawable-xhdpi/ic_notify_clear_normal.png
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_notify_clear_normal.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_notify_clear_pressed.png b/packages/SystemUI/res/drawable-xhdpi/ic_notify_clear_pressed.png
index 8eee4d9..94a4646 100644
--- a/packages/SystemUI/res/drawable-xhdpi/ic_notify_clear_pressed.png
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_notify_clear_pressed.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_notify_quicksettings_normal.png b/packages/SystemUI/res/drawable-xhdpi/ic_notify_quicksettings_normal.png
index 5e67545..80fdb79 100644
--- a/packages/SystemUI/res/drawable-xhdpi/ic_notify_quicksettings_normal.png
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_notify_quicksettings_normal.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_notify_quicksettings_pressed.png b/packages/SystemUI/res/drawable-xhdpi/ic_notify_quicksettings_pressed.png
index e56aeda..ac7c1a7 100644
--- a/packages/SystemUI/res/drawable-xhdpi/ic_notify_quicksettings_pressed.png
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_notify_quicksettings_pressed.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_notify_rotation_off_normal.png b/packages/SystemUI/res/drawable-xhdpi/ic_notify_rotation_off_normal.png
new file mode 100644
index 0000000..cebd6d8
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_notify_rotation_off_normal.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_notify_rotation_off_pressed.png b/packages/SystemUI/res/drawable-xhdpi/ic_notify_rotation_off_pressed.png
new file mode 100644
index 0000000..ef4d9a1
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_notify_rotation_off_pressed.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_notify_rotation_on_normal.png b/packages/SystemUI/res/drawable-xhdpi/ic_notify_rotation_on_normal.png
new file mode 100644
index 0000000..01146aa
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_notify_rotation_on_normal.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_notify_rotation_on_pressed.png b/packages/SystemUI/res/drawable-xhdpi/ic_notify_rotation_on_pressed.png
new file mode 100644
index 0000000..e8f01c5
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_notify_rotation_on_pressed.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable/ic_notify_quicksettings.xml b/packages/SystemUI/res/drawable/ic_notify_quicksettings.xml
index b37dc39..d8ea524 100644
--- a/packages/SystemUI/res/drawable/ic_notify_quicksettings.xml
+++ b/packages/SystemUI/res/drawable/ic_notify_quicksettings.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- 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.
@@ -16,6 +16,8 @@
 
 <selector xmlns:android="http://schemas.android.com/apk/res/android">
     <item android:state_pressed="true"
-        android:drawable="@drawable/ic_notify_quicksettings_pressed" />
-    <item android:drawable="@drawable/ic_notify_quicksettings_normal" />
+         android:drawable="@drawable/ic_notify_quicksettings_pressed" />
+    <item
+         android:drawable="@drawable/ic_notify_quicksettings_normal" />
 </selector>
+
diff --git a/packages/SystemUI/res/drawable/ic_notify_rotation.xml b/packages/SystemUI/res/drawable/ic_notify_rotation.xml
new file mode 100644
index 0000000..213af80
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_notify_rotation.xml
@@ -0,0 +1,27 @@
+<?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.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_checked="true"
+         android:drawable="@drawable/ic_notify_rotation_on_normal" />
+    <item android:state_checked="true" android:state_pressed="true"
+         android:drawable="@drawable/ic_notify_rotation_on_pressed" />
+    <item android:state_pressed="true"
+         android:drawable="@drawable/ic_notify_rotation_off_pressed" />
+    <item
+         android:drawable="@drawable/ic_notify_rotation_off_normal" />
+</selector>
+
diff --git a/packages/SystemUI/res/layout/status_bar_expanded.xml b/packages/SystemUI/res/layout/status_bar_expanded.xml
index 1de4ab8..8715a99 100644
--- a/packages/SystemUI/res/layout/status_bar_expanded.xml
+++ b/packages/SystemUI/res/layout/status_bar_expanded.xml
@@ -38,14 +38,25 @@
         android:paddingRight="3dp"
         android:background="@drawable/notification_header_bg"
         >
-        <com.android.systemui.statusbar.policy.DateView android:id="@+id/date"
-            android:textAppearance="@style/TextAppearance.StatusBar.Date"
+        <com.android.systemui.statusbar.policy.Clock
+            android:id="@+id/clock"
             android:layout_width="wrap_content"
-            android:layout_height="match_parent"
+            android:layout_height="wrap_content"
             android:layout_alignParentLeft="true"
+            android:layout_centerVertical="true"
+            android:layout_marginLeft="8dp"
             android:singleLine="true"
-            android:gravity="center_vertical|left"
-            android:paddingLeft="16dp"
+            android:textAppearance="@style/TextAppearance.StatusBar.Expanded.Clock"
+            />
+
+        <com.android.systemui.statusbar.policy.DateView android:id="@+id/date"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_centerVertical="true"
+            android:layout_toRightOf="@id/clock"
+            android:layout_marginLeft="8dp"
+            android:paddingLeft="8dp"
+            android:textAppearance="@style/TextAppearance.StatusBar.Expanded.Date"
             />
         <!--
         <com.android.systemui.statusbar.phone.CarrierLabel
@@ -62,22 +73,32 @@
             />
         -->
 
-        <ImageView android:id="@+id/settings_button"
-            android:layout_width="wrap_content"
-            android:layout_height="match_parent"
+        <com.android.systemui.statusbar.RotationToggle android:id="@+id/rotation_lock_button"
+            android:layout_width="32dp"
+            android:layout_height="32dp"
+            android:layout_centerVertical="true"
             android:layout_toRightOf="@id/date"
-            android:paddingLeft="8dp"
-            android:paddingRight="8dp"
+            android:layout_marginLeft="12dp"
+            android:button="@drawable/ic_notify_rotation"
+            android:contentDescription="@string/accessibility_rotation_lock_off"
+            />
+
+        <ImageView android:id="@+id/settings_button"
+            android:layout_width="32dp"
+            android:layout_height="32dp"
+            android:layout_marginLeft="8dp"
+            android:layout_centerVertical="true"
+            android:layout_toRightOf="@id/rotation_lock_button"
             android:src="@drawable/ic_notify_quicksettings"
             android:contentDescription="@string/accessibility_settings_button"
             />
 
         <ImageView android:id="@+id/clear_all_button"
-            android:layout_width="wrap_content"
-            android:layout_height="match_parent"
+            android:layout_width="32dp"
+            android:layout_height="32dp"
+            android:layout_marginLeft="8dp"
+            android:layout_centerVertical="true"
             android:layout_alignParentRight="true"
-            android:paddingLeft="8dp"
-            android:paddingRight="8dp"
             android:src="@drawable/ic_notify_clear"
             android:contentDescription="@string/accessibility_clear_all"
             />            
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 1f22507..5548445 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -53,5 +53,8 @@
 
     <!-- When true, show 1/2G networks as 3G. -->
     <bool name="config_showMin3G">false</bool>
+
+    <!-- Show rotation lock button in phone-style notification panel. -->
+    <bool name="config_showRotationLock">true</bool>
 </resources>
 
diff --git a/packages/SystemUI/res/values/donottranslate.xml b/packages/SystemUI/res/values/donottranslate.xml
index 4ca2116..089a54d 100644
--- a/packages/SystemUI/res/values/donottranslate.xml
+++ b/packages/SystemUI/res/values/donottranslate.xml
@@ -21,6 +21,6 @@
          We show both (DOW on one line, then the date) but this can be overridden for locales as
          necessary.
          -->
-    <string name="status_bar_date_formatter">%2$s</string>
+    <string name="status_bar_date_formatter">%1$s\n%2$s</string>
 
 </resources>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index d79ba42..1eb353f 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -377,4 +377,12 @@
     <!-- Content text for do-not-disturb mode notification -->
     <string name="notifications_off_text">Tap here to turn notifications back on.</string>
 
+    <!-- Description of the button in the phone-style notification panel that controls auto-rotation, when auto-rotation is on. [CHAR LIMIT=NONE] -->
+    <string name="accessibility_rotation_lock_off">Screen will rotate automatically.</string>
+
+    <!-- Description of the button in the phone-style notification panel that controls auto-rotation, when auto-rotation is off. [CHAR LIMIT=NONE] -->
+    <string name="accessibility_rotation_lock_on_landscape">Screen is locked in landscape orientation.</string>
+
+    <!-- Description of the button in the phone-style notification panel that controls auto-rotation, when auto-rotation is off. [CHAR LIMIT=NONE] -->
+    <string name="accessibility_rotation_lock_on_portrait">Screen is locked in portrait orientation.</string>
 </resources>
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index 02411d4..144760e 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -53,6 +53,21 @@
         <item name="android:textColor">@android:color/holo_blue_light</item>
     </style>
 
+    <style name="TextAppearance.StatusBar.Expanded" parent="@*android:style/TextAppearance.StatusBar" />
+
+    <style name="TextAppearance.StatusBar.Expanded.Clock">
+        <item name="android:textSize">32dp</item>
+        <item name="android:textStyle">normal</item>
+        <item name="android:textColor">#ffffff</item>
+    </style>
+
+    <style name="TextAppearance.StatusBar.Expanded.Date">
+        <item name="android:textSize">12dp</item>
+        <item name="android:textStyle">normal</item>
+        <item name="android:textColor">#666666</item>
+        <item name="android:textAllCaps">true</item>
+    </style>
+
     <style name="Animation" />
 
     <style name="Animation.ShirtPocketPanel">
diff --git a/packages/SystemUI/src/com/android/systemui/ExpandHelper.java b/packages/SystemUI/src/com/android/systemui/ExpandHelper.java
index 5387bf5..c5928f1 100644
--- a/packages/SystemUI/src/com/android/systemui/ExpandHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/ExpandHelper.java
@@ -41,6 +41,13 @@
     private static final long EXPAND_DURATION = 250;
     private static final long GLOW_DURATION = 150;
 
+    // Set to false to disable focus-based gestures (two-finger pull).
+    private static final boolean USE_DRAG = true;
+    // Set to false to disable scale-based gestures (both horizontal and vertical).
+    private static final boolean USE_SPAN = true;
+    // Both gestures types may be active at the same time.
+    // At least one gesture type should be active.
+    // A variant of the screwdriver gesture will emerge from either gesture type.
 
     // amount of overstretch for maximum brightness expressed in U
     // 2f: maximum brightness is stretching a 1U to 3U, or a 4U to 6U
@@ -59,6 +66,7 @@
     private View mCurrViewBottomGlow;
     private float mOldHeight;
     private float mNaturalHeight;
+    private float mInitialTouchFocusY;
     private float mInitialTouchSpan;
     private Callback mCallback;
     private ScaleGestureDetector mDetector;
@@ -83,7 +91,7 @@
             ViewGroup.LayoutParams lp = mView.getLayoutParams();
             lp.height = (int)h;
             mView.setLayoutParams(lp);
-	    mView.requestLayout();
+            mView.requestLayout();
         }
         public float getHeight() {
             int height = mView.getLayoutParams().height;
@@ -94,15 +102,15 @@
         }
         public int getNaturalHeight(int maximum) {
             ViewGroup.LayoutParams lp = mView.getLayoutParams();
-	    if (DEBUG) Log.v(TAG, "Inspecting a child of type: " + mView.getClass().getName());
+            if (DEBUG) Log.v(TAG, "Inspecting a child of type: " + mView.getClass().getName());
             int oldHeight = lp.height;
             lp.height = ViewGroup.LayoutParams.WRAP_CONTENT;
             mView.setLayoutParams(lp);
             mView.measure(
                     View.MeasureSpec.makeMeasureSpec(mView.getMeasuredWidth(),
-						     View.MeasureSpec.EXACTLY),
+                                                     View.MeasureSpec.EXACTLY),
                     View.MeasureSpec.makeMeasureSpec(maximum,
-						     View.MeasureSpec.AT_MOST));
+                                                     View.MeasureSpec.AT_MOST));
             lp.height = oldHeight;
             mView.setLayoutParams(lp);
             return mView.getMeasuredHeight();
@@ -135,8 +143,9 @@
                 View v = mCallback.getChildAtPosition(detector.getFocusX(), detector.getFocusY());
 
                 // your fingers have to be somewhat close to the bounds of the view in question
-                mInitialTouchSpan = Math.abs(detector.getCurrentSpanY());
-                if (DEBUG) Log.d(TAG, "got mInitialTouchSpan: " + mInitialTouchSpan);
+                mInitialTouchFocusY = detector.getFocusY();
+                mInitialTouchSpan = Math.abs(detector.getCurrentSpan());
+                if (DEBUG) Log.d(TAG, "got mInitialTouchSpan: (" + mInitialTouchSpan + ")");
 
                 mStretching = initScale(v);
                 return mStretching;
@@ -145,16 +154,25 @@
             @Override
             public boolean onScale(ScaleGestureDetector detector) {
                 if (DEBUG) Log.v(TAG, "onscale() on " + mCurrView);
-                float h = Math.abs(detector.getCurrentSpanY());
-                if (DEBUG) Log.d(TAG, "current span is: " + h);
-                h = h + mOldHeight - mInitialTouchSpan;
-                float target = h;
+
+                // are we scaling or dragging?
+                float span = Math.abs(detector.getCurrentSpan()) - mInitialTouchSpan;
+                span *= USE_SPAN ? 1f : 0f;
+                float drag = detector.getFocusY() - mInitialTouchFocusY;
+                drag *= USE_DRAG ? 1f : 0f;
+                float pull = Math.abs(drag) + Math.abs(span) + 1f;
+                float hand = drag * Math.abs(drag) / pull + span * Math.abs(span) / pull;
+                if (DEBUG) Log.d(TAG, "current span handle is: " + hand);
+                hand = hand + mOldHeight;
+                float target = hand;
                 if (DEBUG) Log.d(TAG, "target is: " + target);
-                h = h<mSmallSize?mSmallSize:(h>mLargeSize?mLargeSize:h);
-                h = h>mNaturalHeight?mNaturalHeight:h;
-                if (DEBUG) Log.d(TAG, "scale continues: h=" + h);
-                mScaler.setHeight(h);
-                float stretch = (float) Math.abs((target - h) / mMaximumStretch);
+                hand = hand < mSmallSize ? mSmallSize : (hand > mLargeSize ? mLargeSize : hand);
+                hand = hand > mNaturalHeight ? mNaturalHeight : hand;
+                if (DEBUG) Log.d(TAG, "scale continues: hand =" + hand);
+                mScaler.setHeight(hand);
+
+                // glow if overscale
+                float stretch = (float) Math.abs((target - hand) / mMaximumStretch);
                 float strength = 1f / (1f + (float) Math.pow(Math.E, -1 * ((8f * stretch) - 5f)));
                 if (DEBUG) Log.d(TAG, "stretch: " + stretch + " strength: " + strength);
                 setGlow(GLOW_BASE + strength * (1f - GLOW_BASE));
@@ -171,7 +189,10 @@
         });
     }
     public void setGlow(float glow) {
-        if (!mGlowAnimationSet.isRunning()) {
+        if (!mGlowAnimationSet.isRunning() || glow == 0f) {
+            if (mGlowAnimationSet.isRunning()) {
+                mGlowAnimationSet.cancel();
+            }
             if (mCurrViewTopGlow != null && mCurrViewBottomGlow != null) {
                 if (glow == 0f || mCurrViewTopGlow.getAlpha() == 0f) { 
                     // animate glow in and out
@@ -251,6 +272,7 @@
         mScaleAnimation.start();
         mStretching = false;
         setGlow(0f);
+        if (DEBUG) Log.d(TAG, "scale was finished on view: " + mCurrView);
         clearView();
     }
 
@@ -261,12 +283,12 @@
     }
 
     private void setView(View v) {
-        mCurrView = null;
+        mCurrView = v;
         if (v instanceof ViewGroup) {
             ViewGroup g = (ViewGroup) v;
             mCurrViewTopGlow = g.findViewById(R.id.top_glow);
             mCurrViewBottomGlow = g.findViewById(R.id.bottom_glow);
-	    if (DEBUG) {
+            if (DEBUG) {
                 String debugLog = "Looking for glows: " + 
                         (mCurrViewTopGlow != null ? "found top " : "didn't find top") +
                         (mCurrViewBottomGlow != null ? "found bottom " : "didn't find bottom");
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/RotationToggle.java b/packages/SystemUI/src/com/android/systemui/statusbar/RotationToggle.java
new file mode 100644
index 0000000..c5a7354
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/RotationToggle.java
@@ -0,0 +1,30 @@
+package com.android.systemui.statusbar;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.widget.CompoundButton;
+
+import com.android.systemui.statusbar.policy.AutoRotateController;
+
+public class RotationToggle extends CompoundButton {
+    AutoRotateController mRotater;
+
+    public RotationToggle(Context context) {
+        super(context);
+        mRotater = new AutoRotateController(context, this);
+        setClickable(true);
+    }
+
+    public RotationToggle(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        mRotater = new AutoRotateController(context, this);
+        setClickable(true);
+    }
+
+    public RotationToggle(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+        mRotater = new AutoRotateController(context, this);
+        setClickable(true);
+    }
+
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index 1561e27..f6f41b8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -63,6 +63,7 @@
 import android.view.animation.AccelerateInterpolator;
 import android.view.animation.Animation;
 import android.view.animation.AnimationUtils;
+import android.widget.CompoundButton;
 import android.widget.FrameLayout;
 import android.widget.ImageView;
 import android.widget.LinearLayout;
@@ -77,8 +78,10 @@
 import com.android.systemui.statusbar.BaseStatusBar;
 import com.android.systemui.statusbar.NotificationData;
 import com.android.systemui.statusbar.NotificationData.Entry;
+import com.android.systemui.statusbar.RotationToggle;
 import com.android.systemui.statusbar.SignalClusterView;
 import com.android.systemui.statusbar.StatusBarIconView;
+import com.android.systemui.statusbar.policy.AutoRotateController;
 import com.android.systemui.statusbar.policy.BatteryController;
 import com.android.systemui.statusbar.policy.DateView;
 import com.android.systemui.statusbar.policy.IntruderAlertView;
@@ -169,6 +172,7 @@
     // top bar
     View mClearButton;
     View mSettingsButton;
+    RotationToggle mRotationButton;
 
     // drag bar
     CloseDragHandle mCloseView;
@@ -299,6 +303,13 @@
 
         mStatusBarView = (PhoneStatusBarView) mStatusBarWindow.findViewById(R.id.status_bar);
         mNotificationPanel = mStatusBarWindow.findViewById(R.id.notification_panel);
+        // don't allow clicks on the panel to pass through to the background where they will cause the panel to close
+        mNotificationPanel.setOnTouchListener(new View.OnTouchListener() {
+            @Override
+            public boolean onTouch(View v, MotionEvent event) {
+                return true;
+            }
+        });
 
         if (ENABLE_INTRUDERS) {
             mIntruderAlertView = (IntruderAlertView) View.inflate(context, R.layout.intruder_alert, null);
@@ -344,6 +355,8 @@
         mDateView = (DateView)mStatusBarWindow.findViewById(R.id.date);
         mSettingsButton = mStatusBarWindow.findViewById(R.id.settings_button);
         mSettingsButton.setOnClickListener(mSettingsButtonListener);
+        mRotationButton = (RotationToggle) mStatusBarWindow.findViewById(R.id.rotation_lock_button);
+
         mScrollView = (ScrollView)mStatusBarWindow.findViewById(R.id.scroll);
         mScrollView.setVerticalScrollBarEnabled(false); // less drawing during pulldowns
 
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index b3ca171..6348d37 100755
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -553,8 +553,6 @@
             resolver.registerContentObserver(Settings.System.getUriFor(
                     Settings.System.SCREEN_OFF_TIMEOUT), false, this);
             resolver.registerContentObserver(Settings.System.getUriFor(
-                    Settings.System.WINDOW_ORIENTATION_LISTENER_LOG), false, this);
-            resolver.registerContentObserver(Settings.System.getUriFor(
                     Settings.System.POINTER_LOCATION), false, this);
             resolver.registerContentObserver(Settings.Secure.getUriFor(
                     Settings.Secure.DEFAULT_INPUT_METHOD), false, this);
@@ -1098,10 +1096,6 @@
                 updateOrientationListenerLp();
             }
 
-            mOrientationListener.setLogEnabled(
-                    Settings.System.getInt(resolver,
-                            Settings.System.WINDOW_ORIENTATION_LISTENER_LOG, 0) != 0);
-
             if (mSystemReady) {
                 int pointerLocation = Settings.System.getInt(resolver,
                         Settings.System.POINTER_LOCATION, 0);
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 1f7aeb0..0f8d151 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -13484,7 +13484,7 @@
                         parentLaunchMode == ActivityInfo.LAUNCH_SINGLE_TASK ||
                         parentLaunchMode == ActivityInfo.LAUNCH_SINGLE_TOP ||
                         (destIntentFlags & Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0) {
-                    parent.deliverNewIntentLocked(srec.app.uid, destIntent);
+                    parent.deliverNewIntentLocked(srec.info.applicationInfo.uid, destIntent);
                 } else {
                     try {
                         ActivityInfo aInfo = AppGlobals.getPackageManager().getActivityInfo(
diff --git a/services/java/com/android/server/location/GpsLocationProvider.java b/services/java/com/android/server/location/GpsLocationProvider.java
index 65b9627..ce53499 100755
--- a/services/java/com/android/server/location/GpsLocationProvider.java
+++ b/services/java/com/android/server/location/GpsLocationProvider.java
@@ -192,6 +192,11 @@
     // stop trying if we do not receive a fix within 60 seconds
     private static final int NO_FIX_TIMEOUT = 60 * 1000;
 
+    // if the fix interval is below this we leave GPS on,
+    // if above then we cycle the GPS driver.
+    // Typical hot TTTF is ~5 seconds, so 10 seconds seems sane.
+    private static final int GPS_POLLING_THRESHOLD_INTERVAL = 10 * 1000;
+
     // true if we are enabled
     private volatile boolean mEnabled;
     
@@ -842,7 +847,18 @@
     }
 
     public String getInternalState() {
-        return native_get_internal_state();
+        StringBuilder s = new StringBuilder();
+        s.append("  mFixInterval=").append(mFixInterval).append("\n");
+        s.append("  mEngineCapabilities=0x").append(Integer.toHexString(mEngineCapabilities)).append(" (");
+        if (hasCapability(GPS_CAPABILITY_SCHEDULING)) s.append("SCHED ");
+        if (hasCapability(GPS_CAPABILITY_MSB)) s.append("MSB ");
+        if (hasCapability(GPS_CAPABILITY_MSA)) s.append("MSA ");
+        if (hasCapability(GPS_CAPABILITY_SINGLE_SHOT)) s.append("SINGLE_SHOT ");
+        if (hasCapability(GPS_CAPABILITY_ON_DEMAND_TIME)) s.append("ON_DEMAND_TIME ");
+        s.append(")\n");
+
+        s.append(native_get_internal_state());
+        return s.toString();
     }
 
     private final class Listener implements IBinder.DeathRecipient {
@@ -1131,7 +1147,8 @@
             updateStatus(LocationProvider.AVAILABLE, mSvCount);
         }
 
-       if (!hasCapability(GPS_CAPABILITY_SCHEDULING) && mStarted && mFixInterval > 1000) {
+       if (!hasCapability(GPS_CAPABILITY_SCHEDULING) && mStarted &&
+               mFixInterval > GPS_POLLING_THRESHOLD_INTERVAL) {
             if (DEBUG) Log.d(TAG, "got fix, hibernating");
             hibernate();
         }
diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java
index b5d0b60..4ae3c57 100644
--- a/services/java/com/android/server/pm/PackageManagerService.java
+++ b/services/java/com/android/server/pm/PackageManagerService.java
@@ -53,6 +53,7 @@
 import android.content.IntentSender.SendIntentException;
 import android.content.pm.ActivityInfo;
 import android.content.pm.ApplicationInfo;
+import android.content.pm.ContainerEncryptionParams;
 import android.content.pm.FeatureInfo;
 import android.content.pm.IPackageDataObserver;
 import android.content.pm.IPackageDeleteObserver;
@@ -116,7 +117,6 @@
 import java.io.FileReader;
 import java.io.FilenameFilter;
 import java.io.IOException;
-import java.io.InputStream;
 import java.io.PrintWriter;
 import java.security.NoSuchAlgorithmException;
 import java.security.PublicKey;
@@ -128,7 +128,6 @@
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.Date;
-import java.util.Enumeration;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
@@ -136,9 +135,6 @@
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Set;
-import java.util.zip.ZipEntry;
-import java.util.zip.ZipFile;
-import java.util.zip.ZipOutputStream;
 
 import libcore.io.ErrnoException;
 import libcore.io.IoUtils;
@@ -1067,23 +1063,29 @@
             mInstaller.moveFiles();
 
             // Prune any system packages that no longer exist.
+            final List<String> possiblyDeletedSystemApps = new ArrayList<String>();
             if (!mOnlyCore) {
                 Iterator<PackageSetting> psit = mSettings.mPackages.values().iterator();
                 while (psit.hasNext()) {
                     PackageSetting ps = psit.next();
-                    if ((ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) != 0
-                            && !mPackages.containsKey(ps.name)
-                            && !mSettings.mDisabledSysPackages.containsKey(ps.name)) {
+                    if ((ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0
+                            || mPackages.containsKey(ps.name)) {
+                        continue;
+                    }
+
+                    if (!mSettings.isDisabledSystemPackageLPr(ps.name)) {
                         psit.remove();
                         String msg = "System package " + ps.name
                                 + " no longer exists; wiping its data";
                         reportSettingsProblem(Log.WARN, msg);
                         mInstaller.remove(ps.name, 0);
                         sUserManager.removePackageForAllUsers(ps.name);
+                    } else {
+                        possiblyDeletedSystemApps.add(ps.name);
                     }
                 }
             }
-            
+
             mAppInstallDir = new File(dataDir, "app");
             //look for any incomplete package installations
             ArrayList<PackageSetting> deletePkgsList = mSettings.getListOfIncompleteInstallPackagesLPr();
@@ -1108,6 +1110,21 @@
                 mDrmAppInstallObserver.startWatching();
                 scanDirLI(mDrmAppPrivateInstallDir, PackageParser.PARSE_FORWARD_LOCK,
                         scanMode, 0);
+
+                /**
+                 * Remove disable package settings for any system apps
+                 * that were removed via an OTA.
+                 */
+                for (String deletedAppName : possiblyDeletedSystemApps) {
+                    PackageParser.Package deletedPkg = mPackages.get(deletedAppName);
+                    if (deletedPkg != null) {
+                        mSettings.removeDisabledSystemPackageLPw(deletedAppName);
+                        deletedPkg.applicationInfo.flags &= ~ApplicationInfo.FLAG_SYSTEM;
+
+                        PackageSetting deletedPs = mSettings.mPackages.get(deletedAppName);
+                        deletedPs.pkgFlags &= ~ApplicationInfo.FLAG_SYSTEM;
+                    }
+                }
             } else {
                 mAppInstallObserver = null;
                 mDrmAppInstallObserver = null;
@@ -3047,8 +3064,7 @@
             // Check to see if this package could be hiding/updating a system
             // package.  Must look for it either under the original or real
             // package name depending on our state.
-            updatedPkg = mSettings.mDisabledSysPackages.get(
-                    ps != null ? ps.name : pkg.packageName);
+            updatedPkg = mSettings.getDisabledSystemPkgLPr(ps != null ? ps.name : pkg.packageName);
         }
         // First check if this is a system package that may involve an update
         if (updatedPkg != null && (parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
@@ -3527,7 +3543,7 @@
                 mTransferedPackages.add(pkg.packageName);
             }
             
-            if (mSettings.mDisabledSysPackages.get(pkg.packageName) != null) {
+            if (mSettings.isDisabledSystemPackageLPr(pkg.packageName)) {
                 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
             }
 
@@ -5133,13 +5149,13 @@
             final Uri packageURI, final IPackageInstallObserver observer, final int flags,
             final String installerPackageName) {
         installPackageWithVerification(packageURI, observer, flags, installerPackageName, null,
-                null);
+                null, null);
     }
 
     @Override
     public void installPackageWithVerification(Uri packageURI, IPackageInstallObserver observer,
             int flags, String installerPackageName, Uri verificationURI,
-            ManifestDigest manifestDigest) {
+            ManifestDigest manifestDigest, ContainerEncryptionParams encryptionParams) {
         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.INSTALL_PACKAGES, null);
 
         final int uid = Binder.getCallingUid();
@@ -5157,7 +5173,7 @@
 
         final Message msg = mHandler.obtainMessage(INIT_COPY);
         msg.obj = new InstallParams(packageURI, observer, filteredFlags, installerPackageName,
-                verificationURI, manifestDigest);
+                verificationURI, manifestDigest, encryptionParams);
         mHandler.sendMessage(msg);
     }
 
@@ -5560,22 +5576,27 @@
     class InstallParams extends HandlerParams {
         final IPackageInstallObserver observer;
         int flags;
-        final Uri packageURI;
+
+        private final Uri mPackageURI;
         final String installerPackageName;
         final Uri verificationURI;
         final ManifestDigest manifestDigest;
         private InstallArgs mArgs;
         private int mRet;
+        private File mTempPackage;
+        final ContainerEncryptionParams encryptionParams;
 
         InstallParams(Uri packageURI,
                 IPackageInstallObserver observer, int flags,
-                String installerPackageName, Uri verificationURI, ManifestDigest manifestDigest) {
-            this.packageURI = packageURI;
+                String installerPackageName, Uri verificationURI, ManifestDigest manifestDigest,
+                ContainerEncryptionParams encryptionParams) {
+            this.mPackageURI = packageURI;
             this.flags = flags;
             this.observer = observer;
             this.installerPackageName = installerPackageName;
             this.verificationURI = verificationURI;
             this.manifestDigest = manifestDigest;
+            this.encryptionParams = encryptionParams;
         }
 
         private int installLocationPolicy(PackageInfoLite pkgLite, int flags) {
@@ -5655,16 +5676,51 @@
                     lowThreshold = dsm.getMemoryLowThreshold();
                 }
 
-                // Remote call to find out default install location
                 try {
-                    mContext.grantUriPermission(DEFAULT_CONTAINER_PACKAGE, packageURI,
+                    mContext.grantUriPermission(DEFAULT_CONTAINER_PACKAGE, mPackageURI,
                             Intent.FLAG_GRANT_READ_URI_PERMISSION);
-                    pkgLite = mContainerService.getMinimalPackageInfo(packageURI, flags,
-                            lowThreshold);
-                } finally {
-                    mContext.revokeUriPermission(packageURI, Intent.FLAG_GRANT_READ_URI_PERMISSION);
-                }
 
+                    final File packageFile;
+                    if (encryptionParams != null || !"file".equals(mPackageURI.getScheme())) {
+                        ParcelFileDescriptor out = null;
+
+                        mTempPackage = createTempPackageFile(mDrmAppPrivateInstallDir);
+                        if (mTempPackage != null) {
+                            try {
+                                out = ParcelFileDescriptor.open(mTempPackage,
+                                        ParcelFileDescriptor.MODE_READ_WRITE);
+                            } catch (FileNotFoundException e) {
+                                Slog.e(TAG, "Failed to create temporary file for : " + mPackageURI);
+                            }
+
+                            // Make a temporary file for decryption.
+                            ret = mContainerService
+                                    .copyResource(mPackageURI, encryptionParams, out);
+
+                            packageFile = mTempPackage;
+
+                            FileUtils.setPermissions(packageFile.getAbsolutePath(),
+                                    FileUtils.S_IRUSR | FileUtils.S_IWUSR | FileUtils.S_IROTH,
+                                    -1, -1);
+                        } else {
+                            packageFile = null;
+                        }
+                    } else {
+                        packageFile = new File(mPackageURI.getPath());
+                    }
+
+                    if (packageFile != null) {
+                        // Remote call to find out default install location
+                        pkgLite = mContainerService.getMinimalPackageInfo(
+                                packageFile.getAbsolutePath(), flags, lowThreshold);
+                    }
+                } finally {
+                    mContext.revokeUriPermission(mPackageURI,
+                            Intent.FLAG_GRANT_READ_URI_PERMISSION);
+                }
+            }
+
+            if (ret == PackageManager.INSTALL_SUCCEEDED) {
                 int loc = pkgLite.recommendedInstallLocation;
                 if (loc == PackageHelper.RECOMMEND_FAILED_INVALID_LOCATION) {
                     ret = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
@@ -5708,8 +5764,9 @@
                 final int requiredUid = mRequiredVerifierPackage == null ? -1
                         : getPackageUid(mRequiredVerifierPackage, 0);
                 if (requiredUid != -1 && isVerificationEnabled()) {
-                    final Intent verification = new Intent(Intent.ACTION_PACKAGE_NEEDS_VERIFICATION);
-                    verification.setDataAndType(packageURI, PACKAGE_MIME_TYPE);
+                    final Intent verification = new Intent(
+                            Intent.ACTION_PACKAGE_NEEDS_VERIFICATION);
+                    verification.setDataAndType(getPackageUri(), PACKAGE_MIME_TYPE);
                     verification.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
 
                     final List<ResolveInfo> receivers = queryIntentReceivers(verification, null,
@@ -5812,6 +5869,13 @@
             if (mArgs != null) {
                 processPendingInstall(mArgs, mRet);
             }
+
+            if (mTempPackage != null) {
+                if (!mTempPackage.delete()) {
+                    Slog.w(TAG, "Couldn't delete temporary file: "
+                            + mTempPackage.getAbsolutePath());
+                }
+            }
         }
 
         @Override
@@ -5823,6 +5887,14 @@
         public boolean isForwardLocked() {
             return (flags & PackageManager.INSTALL_FORWARD_LOCK) != 0;
         }
+
+        public Uri getPackageUri() {
+            if (mTempPackage != null) {
+                return Uri.fromFile(mTempPackage);
+            } else {
+                return mPackageURI;
+            }
+        }
     }
 
     /*
@@ -6037,8 +6109,8 @@
         boolean created = false;
 
         FileInstallArgs(InstallParams params) {
-            super(params.packageURI, params.observer, params.flags, params.installerPackageName,
-                    params.manifestDigest);
+            super(params.getPackageUri(), params.observer, params.flags,
+                    params.installerPackageName, params.manifestDigest);
         }
 
         FileInstallArgs(String fullCodePath, String fullResourcePath, String nativeLibraryPath) {
@@ -6128,7 +6200,7 @@
             try {
                 mContext.grantUriPermission(DEFAULT_CONTAINER_PACKAGE, packageURI,
                         Intent.FLAG_GRANT_READ_URI_PERMISSION);
-                ret = imcs.copyResource(packageURI, out);
+                ret = imcs.copyResource(packageURI, null, out);
             } finally {
                 IoUtils.closeQuietly(out);
                 mContext.revokeUriPermission(packageURI, Intent.FLAG_GRANT_READ_URI_PERMISSION);
@@ -6315,8 +6387,8 @@
         String libraryPath;
 
         AsecInstallArgs(InstallParams params) {
-            super(params.packageURI, params.observer, params.flags, params.installerPackageName,
-                    params.manifestDigest);
+            super(params.getPackageUri(), params.observer, params.flags,
+                    params.installerPackageName, params.manifestDigest);
         }
 
         AsecInstallArgs(String fullCodePath, String fullResourcePath, String nativeLibraryPath,
diff --git a/services/java/com/android/server/pm/Settings.java b/services/java/com/android/server/pm/Settings.java
index d015278..d0eda2d 100644
--- a/services/java/com/android/server/pm/Settings.java
+++ b/services/java/com/android/server/pm/Settings.java
@@ -102,7 +102,7 @@
     final HashMap<String, PackageSetting> mPackages =
             new HashMap<String, PackageSetting>();
     // List of replaced system applications
-    final HashMap<String, PackageSetting> mDisabledSysPackages =
+    private final HashMap<String, PackageSetting> mDisabledSysPackages =
         new HashMap<String, PackageSetting>();
 
     // These are the last platform API version we were using for
@@ -280,6 +280,14 @@
         return ret;
     }
 
+    boolean isDisabledSystemPackageLPr(String name) {
+        return mDisabledSysPackages.containsKey(name);
+    }
+
+    void removeDisabledSystemPackageLPw(String name) {
+        mDisabledSysPackages.remove(name);
+    }
+
     PackageSetting addPackageLPw(String name, String realName, File codePath, File resourcePath,
             String nativeLibraryPathString, int uid, int vc, int pkgFlags) {
         PackageSetting p = mPackages.get(name);
diff --git a/test-runner/src/android/test/mock/MockContentProvider.java b/test-runner/src/android/test/mock/MockContentProvider.java
index a8c388e..1e41416 100644
--- a/test-runner/src/android/test/mock/MockContentProvider.java
+++ b/test-runner/src/android/test/mock/MockContentProvider.java
@@ -21,7 +21,6 @@
 import android.content.ContentProviderResult;
 import android.content.ContentValues;
 import android.content.Context;
-import android.content.ICancellationSignal;
 import android.content.IContentProvider;
 import android.content.OperationApplicationException;
 import android.content.pm.PathPermission;
@@ -31,6 +30,7 @@
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.IBinder;
+import android.os.ICancellationSignal;
 import android.os.ParcelFileDescriptor;
 import android.os.RemoteException;
 
diff --git a/test-runner/src/android/test/mock/MockIContentProvider.java b/test-runner/src/android/test/mock/MockIContentProvider.java
index 1aa0448..9fcfc22 100644
--- a/test-runner/src/android/test/mock/MockIContentProvider.java
+++ b/test-runner/src/android/test/mock/MockIContentProvider.java
@@ -21,12 +21,12 @@
 import android.content.ContentValues;
 import android.content.EntityIterator;
 import android.content.IContentProvider;
-import android.content.ICancellationSignal;
 import android.content.res.AssetFileDescriptor;
 import android.database.Cursor;
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.IBinder;
+import android.os.ICancellationSignal;
 import android.os.ParcelFileDescriptor;
 import android.os.RemoteException;
 
diff --git a/test-runner/src/android/test/mock/MockPackageManager.java b/test-runner/src/android/test/mock/MockPackageManager.java
index 5610134..86689f3 100644
--- a/test-runner/src/android/test/mock/MockPackageManager.java
+++ b/test-runner/src/android/test/mock/MockPackageManager.java
@@ -22,6 +22,7 @@
 import android.content.IntentSender;
 import android.content.pm.ActivityInfo;
 import android.content.pm.ApplicationInfo;
+import android.content.pm.ContainerEncryptionParams;
 import android.content.pm.FeatureInfo;
 import android.content.pm.IPackageDataObserver;
 import android.content.pm.IPackageDeleteObserver;
@@ -29,6 +30,7 @@
 import android.content.pm.IPackageMoveObserver;
 import android.content.pm.IPackageStatsObserver;
 import android.content.pm.InstrumentationInfo;
+import android.content.pm.ManifestDigest;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.PermissionGroupInfo;
@@ -36,16 +38,12 @@
 import android.content.pm.ProviderInfo;
 import android.content.pm.ResolveInfo;
 import android.content.pm.ServiceInfo;
-import android.content.pm.Signature;
 import android.content.pm.UserInfo;
-import android.content.pm.ManifestDigest;
 import android.content.pm.VerifierDeviceIdentity;
-import android.content.pm.VerifierInfo;
 import android.content.res.Resources;
 import android.content.res.XmlResourceParser;
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
-import android.os.RemoteException;
 
 import java.util.List;
 
@@ -565,7 +563,7 @@
     @Override
     public void installPackageWithVerification(Uri packageURI, IPackageInstallObserver observer,
             int flags, String installerPackageName, Uri verificationURI,
-            ManifestDigest manifestDigest) {
+            ManifestDigest manifestDigest, ContainerEncryptionParams encryptionParams) {
         throw new UnsupportedOperationException();
     }
 
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContentProvider.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContentProvider.java
index e28866e..f770ccc 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContentProvider.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContentProvider.java
@@ -19,7 +19,6 @@
 import android.content.ContentProviderOperation;
 import android.content.ContentProviderResult;
 import android.content.ContentValues;
-import android.content.ICancellationSignal;
 import android.content.IContentProvider;
 import android.content.OperationApplicationException;
 import android.content.res.AssetFileDescriptor;
@@ -27,6 +26,7 @@
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.IBinder;
+import android.os.ICancellationSignal;
 import android.os.ParcelFileDescriptor;
 import android.os.RemoteException;
 
diff --git a/tools/localize/Android.mk b/tools/localize/Android.mk
deleted file mode 100644
index 5ec9feb..0000000
--- a/tools/localize/Android.mk
+++ /dev/null
@@ -1,55 +0,0 @@
-# 
-# Copyright 2006 The Android Open Source Project
-#
-# Android Asset Packaging Tool
-#
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := \
-    file_utils.cpp \
-    localize.cpp \
-    merge_res_and_xliff.cpp \
-    res_check.cpp \
-    xmb.cpp \
-    Configuration.cpp \
-    Perforce.cpp \
-    SourcePos.cpp \
-    Values.cpp \
-    ValuesFile.cpp \
-    XLIFFFile.cpp \
-    XMLHandler.cpp
-
-LOCAL_C_INCLUDES := \
-    external/expat/lib \
-    build/libs/host/include
-
-LOCAL_CFLAGS += -g -O0
-
-LOCAL_STATIC_LIBRARIES := \
-    libexpat \
-    libhost \
-    libutils \
-	libcutils
-    
-ifeq ($(HOST_OS),linux)
-LOCAL_LDLIBS += -lrt -ldl -lpthread
-endif
-
-
-LOCAL_MODULE := localize
-
-ifeq (a,a)
-    LOCAL_CFLAGS += -DLOCALIZE_WITH_TESTS
-    LOCAL_SRC_FILES += \
-        test.cpp \
-        localize_test.cpp \
-        merge_res_and_xliff_test.cpp \
-        Perforce_test.cpp \
-        ValuesFile_test.cpp \
-        XLIFFFile_test.cpp \
-        XMLHandler_test.cpp
-endif
-
-include $(BUILD_HOST_EXECUTABLE)
diff --git a/tools/localize/Configuration.cpp b/tools/localize/Configuration.cpp
deleted file mode 100644
index 56addbd..0000000
--- a/tools/localize/Configuration.cpp
+++ /dev/null
@@ -1,76 +0,0 @@
-#include "Configuration.h"
-#include <string.h>
-
-int
-Configuration::Compare(const Configuration& that) const
-{
-    int n;
-
-    n = locale.compare(that.locale);
-    if (n != 0) return n;
-
-    n = vendor.compare(that.vendor);
-    if (n != 0) return n;
-
-    n = orientation.compare(that.orientation);
-    if (n != 0) return n;
-
-    n = density.compare(that.density);
-    if (n != 0) return n;
-
-    n = touchscreen.compare(that.touchscreen);
-    if (n != 0) return n;
-
-    n = keyboard.compare(that.keyboard);
-    if (n != 0) return n;
-
-    n = navigation.compare(that.navigation);
-    if (n != 0) return n;
-
-    n = screenSize.compare(that.screenSize);
-    if (n != 0) return n;
-
-    return 0;
-}
-
-string
-Configuration::ToString() const
-{
-    string s;
-    if (locale.length() > 0) {
-        if (s.length() > 0) {
-            s += "-";
-        }
-        s += locale;
-    }
-    return s;
-}
-
-bool
-split_locale(const string& in, string* language, string* region)
-{
-    const int len = in.length();
-    if (len == 2) {
-        if (isalpha(in[0]) && isalpha(in[1])) {
-            *language = in;
-            region->clear();
-            return true;
-        } else {
-            return false;
-        }
-    }
-    else if (len == 5) {
-        if (isalpha(in[0]) && isalpha(in[1]) && (in[2] == '_' || in[2] == '-')
-                && isalpha(in[3]) && isalpha(in[4])) {
-            language->assign(in.c_str(), 2);
-            region->assign(in.c_str()+3, 2);
-            return true;
-        } else {
-            return false;
-        }
-    }
-    else {
-        return false;
-    }
-}
-
diff --git a/tools/localize/Configuration.h b/tools/localize/Configuration.h
deleted file mode 100644
index f91bf04..0000000
--- a/tools/localize/Configuration.h
+++ /dev/null
@@ -1,38 +0,0 @@
-#ifndef CONFIGURATION_H
-#define CONFIGURATION_H
-
-#include <string>
-
-using namespace std;
-
-struct Configuration
-{
-    string locale;
-    string vendor;
-    string orientation;
-    string density;
-    string touchscreen;
-    string keyboard;
-    string navigation;
-    string screenSize;
-
-    // Compare two configurations
-    int Compare(const Configuration& that) const;
-
-    inline bool operator<(const Configuration& that) const { return Compare(that) < 0; }
-    inline bool operator<=(const Configuration& that) const { return Compare(that) <= 0; }
-    inline bool operator==(const Configuration& that) const { return Compare(that) == 0; }
-    inline bool operator!=(const Configuration& that) const { return Compare(that) != 0; }
-    inline bool operator>=(const Configuration& that) const { return Compare(that) >= 0; }
-    inline bool operator>(const Configuration& that) const { return Compare(that) > 0; }
-
-    // Parse a directory name, like "values-en-rUS".  Return the first segment in resType.
-    bool ParseDiectoryName(const string& dir, string* resType);
-
-    string ToString() const;
-};
-
-bool split_locale(const string& in, string* language, string* region);
-
-
-#endif // CONFIGURATION_H
diff --git a/tools/localize/Perforce.cpp b/tools/localize/Perforce.cpp
deleted file mode 100644
index ae11231..0000000
--- a/tools/localize/Perforce.cpp
+++ /dev/null
@@ -1,234 +0,0 @@
-#include "Perforce.h"
-#include "log.h"
-#include <string.h>
-#include <cstdio>
-#include <stdlib.h>
-#include <sstream>
-#include <sys/types.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/wait.h>
-#include <cstdio>
-
-using namespace std;
-
-extern char** environ;
-
-int
-Perforce::RunCommand(const string& cmd, string* result, bool printOnFailure)
-{
-    int err;
-    int outPipe[2];
-    int errPipe[2];
-    pid_t pid;
-
-    log_printf("Perforce::RunCommand: %s\n", cmd.c_str());
-
-    err = pipe(outPipe);
-    err |= pipe(errPipe);
-    if (err == -1) {
-        printf("couldn't create pipe. exiting.\n");
-        exit(1);
-        return -1;
-    }
-
-    pid = fork();
-    if (pid == -1) {
-        printf("couldn't fork. eixiting\n");
-        exit(1);
-        return -1;
-    }
-    else if (pid == 0) {
-        char const* args[] = {
-            "/bin/sh",
-            "-c",
-            cmd.c_str(),
-            NULL
-        };
-        close(outPipe[0]);
-        close(errPipe[0]);
-        dup2(outPipe[1], 1);
-        dup2(errPipe[1], 2);
-        execve(args[0], (char* const*)args, environ);
-        // done
-    }
-
-    close(outPipe[1]);
-    close(errPipe[1]);
-
-    result->clear();
-
-    char buf[1024];
-
-    // stdout
-    while (true) {
-        size_t amt = read(outPipe[0], buf, sizeof(buf));
-        result->append(buf, amt);
-        if (amt <= 0) {
-            break;
-        }
-    }
-
-    // stderr -- the messages are short so it ought to just fit in the buffer
-    string error;
-    while (true) {
-        size_t amt = read(errPipe[0], buf, sizeof(buf));
-        error.append(buf, amt);
-        if (amt <= 0) {
-            break;
-        }
-    }
-
-    close(outPipe[0]);
-    close(errPipe[0]);
-
-    waitpid(pid, &err, 0);
-    if (WIFEXITED(err)) {
-        err = WEXITSTATUS(err);
-    } else {
-        err = -1;
-    }
-    if (err != 0 && printOnFailure) {
-        write(2, error.c_str(), error.length());
-    }
-    return err;
-}
-
-int
-Perforce::GetResourceFileNames(const string& version, const string& base,
-                                const vector<string>& apps, vector<string>* results,
-                                bool printOnFailure)
-{
-    int err;
-    string text;
-    stringstream cmd;
-
-    cmd << "p4 files";
-
-    const size_t I = apps.size();
-    for (size_t i=0; i<I; i++) {
-        cmd << " \"" << base << '/' << apps[i] << "/res/values/strings.xml@" << version << '"';
-    }
-
-    err = RunCommand(cmd.str(), &text, printOnFailure);
-
-    const char* str = text.c_str();
-    while (*str) {
-        const char* lineend = strchr(str, '\n');
-        if (lineend == str) {
-            str++;
-            continue;
-        }
-        if (lineend-str > 1023) {
-            fprintf(stderr, "line too long!\n");
-            return 1;
-        }
-
-        string s(str, lineend-str);
-
-        char filename[1024];
-        char edit[1024];
-        int count = sscanf(str, "%[^#]#%*d - %s change %*d %*[^\n]\n", filename, edit);
-
-        if (count == 2 && 0 != strcmp("delete", edit)) {
-            results->push_back(string(filename));
-        }
-
-        str = lineend + 1;
-    }
-
-    return err;
-}
-
-int
-Perforce::GetFile(const string& file, const string& version, string* result,
-        bool printOnFailure)
-{
-    stringstream cmd;
-    cmd << "p4 print -q \"" << file << '@' << version << '"';
-    return RunCommand(cmd.str(), result, printOnFailure);
-}
-
-string
-Perforce::GetCurrentChange(bool printOnFailure)
-{
-    int err;
-    string text;
-
-    err = RunCommand("p4 changes -m 1 \\#have", &text, printOnFailure);
-    if (err != 0) {
-        return "";
-    }
-
-    long long n;
-    int count = sscanf(text.c_str(), "Change %lld on", &n);
-    if (count != 1) {
-        return "";
-    }
-
-    char result[100];
-    sprintf(result, "%lld", n);
-
-    return string(result);
-}
-
-static int
-do_files(const string& op, const vector<string>& files, bool printOnFailure)
-{
-    string text;
-    stringstream cmd;
-
-    cmd << "p4 " << op;
-
-    const size_t I = files.size();
-    for (size_t i=0; i<I; i++) {
-        cmd << " \"" << files[i] << "\"";
-    }
-
-    return Perforce::RunCommand(cmd.str(), &text, printOnFailure);
-}
-
-int
-Perforce::EditFiles(const vector<string>& files, bool printOnFailure)
-{
-    return do_files("edit", files, printOnFailure);
-}
-
-int
-Perforce::AddFiles(const vector<string>& files, bool printOnFailure)
-{
-    return do_files("add", files, printOnFailure);
-}
-
-int
-Perforce::DeleteFiles(const vector<string>& files, bool printOnFailure)
-{
-    return do_files("delete", files, printOnFailure);
-}
-
-string
-Perforce::Where(const string& depotPath, bool printOnFailure)
-{
-    int err;
-    string text;
-    string cmd = "p4 where ";
-    cmd += depotPath;
-
-    err = RunCommand(cmd, &text, printOnFailure);
-    if (err != 0) {
-        return "";
-    }
-
-    size_t index = text.find(' ');
-    if (index == text.npos) {
-        return "";
-    }
-    index = text.find(' ', index+1)+1;
-    if (index == text.npos) {
-        return "";
-    }
-
-    return text.substr(index, text.length()-index-1);
-}
-
diff --git a/tools/localize/Perforce.h b/tools/localize/Perforce.h
deleted file mode 100644
index 522797d..0000000
--- a/tools/localize/Perforce.h
+++ /dev/null
@@ -1,25 +0,0 @@
-#ifndef PERFORCE_H
-#define PERFORCE_H
-
-#include <string>
-#include <vector>
-
-using namespace std;
-
-class Perforce
-{
-public:
-    static int RunCommand(const string& cmd, string* result, bool printOnFailure);
-    static int GetResourceFileNames(const string& version, const string& base,
-                                const vector<string>& apps, vector<string>* result,
-                                bool printOnFailure);
-    static int GetFile(const string& file, const string& version, string* result,
-                                bool printOnFailure);
-    static string GetCurrentChange(bool printOnFailure);
-    static int EditFiles(const vector<string>& filename, bool printOnFailure);
-    static int AddFiles(const vector<string>& files, bool printOnFailure);
-    static int DeleteFiles(const vector<string>& files, bool printOnFailure);
-    static string Where(const string& depotPath, bool printOnFailure);
-};
-
-#endif // PERFORCE_H
diff --git a/tools/localize/Perforce_test.cpp b/tools/localize/Perforce_test.cpp
deleted file mode 100644
index 142b20e..0000000
--- a/tools/localize/Perforce_test.cpp
+++ /dev/null
@@ -1,62 +0,0 @@
-#include "Perforce.h"
-#include <stdio.h>
-
-static int
-RunCommand_test()
-{
-    string result;
-    int err = Perforce::RunCommand("p4 help csommands", &result, true);
-    printf("err=%d result=[[%s]]\n", err, result.c_str());
-    return 0;
-}
-
-static int
-GetResourceFileNames_test()
-{
-    vector<string> results;
-    vector<string> apps;
-    apps.push_back("apps/common");
-    apps.push_back("apps/Contacts");
-    int err = Perforce::GetResourceFileNames("43019", "//device", apps, &results, true);
-    if (err != 0) {
-        return err;
-    }
-    if (results.size() != 2) {
-        return 1;
-    }
-    if (results[0] != "//device/apps/common/res/values/strings.xml") {
-        return 1;
-    }
-    if (results[1] != "//device/apps/Contacts/res/values/strings.xml") {
-        return 1;
-    }
-    if (false) {
-        for (size_t i=0; i<results.size(); i++) {
-            printf("[%zd] '%s'\n", i, results[i].c_str());
-        }
-    }
-    return 0;
-}
-
-static int
-GetFile_test()
-{
-    string result;
-    int err = Perforce::GetFile("//device/Makefile", "296", &result, true);
-    printf("err=%d result=[[%s]]\n", err, result.c_str());
-    return 0;
-}
-
-int
-Perforce_test()
-{
-    bool all = false;
-    int err = 0;
-
-    if (all) err |= RunCommand_test();
-    if (all) err |= GetResourceFileNames_test();
-    if (all) err |= GetFile_test();
-
-    return err;
-}
-
diff --git a/tools/localize/SourcePos.cpp b/tools/localize/SourcePos.cpp
deleted file mode 100644
index 184bfe0a..0000000
--- a/tools/localize/SourcePos.cpp
+++ /dev/null
@@ -1,168 +0,0 @@
-#include "SourcePos.h"
-
-#include <stdarg.h>
-#include <cstdio>
-#include <set>
-#include <cstdio>
-
-using namespace std;
-
-const SourcePos GENERATED_POS("<generated>", -1);
-
-// ErrorPos
-// =============================================================================
-struct ErrorPos
-{
-    string file;
-    int line;
-    string error;
-
-    ErrorPos();
-    ErrorPos(const ErrorPos& that);
-    ErrorPos(const string& file, int line, const string& error);
-    ~ErrorPos();
-    bool operator<(const ErrorPos& rhs) const;
-    bool operator==(const ErrorPos& rhs) const;
-    ErrorPos& operator=(const ErrorPos& rhs);
-
-    void Print(FILE* to) const;
-};
-
-static set<ErrorPos> g_errors;
-
-ErrorPos::ErrorPos()
-{
-}
-
-ErrorPos::ErrorPos(const ErrorPos& that)
-    :file(that.file),
-     line(that.line),
-     error(that.error)
-{
-}
-
-ErrorPos::ErrorPos(const string& f, int l, const string& e)
-    :file(f),
-     line(l),
-     error(e)
-{
-}
-
-ErrorPos::~ErrorPos()
-{
-}
-
-bool
-ErrorPos::operator<(const ErrorPos& rhs) const
-{
-    if (this->file < rhs.file) return true;
-    if (this->file == rhs.file) {
-        if (this->line < rhs.line) return true;
-        if (this->line == rhs.line) {
-            if (this->error < rhs.error) return true;
-        }
-    }
-    return false;
-}
-
-bool
-ErrorPos::operator==(const ErrorPos& rhs) const
-{
-    return this->file == rhs.file
-            && this->line == rhs.line
-            && this->error == rhs.error;
-}
-
-ErrorPos&
-ErrorPos::operator=(const ErrorPos& rhs)
-{
-    this->file = rhs.file;
-    this->line = rhs.line;
-    this->error = rhs.error;
-    return *this;
-}
-
-void
-ErrorPos::Print(FILE* to) const
-{
-    if (this->line >= 0) {
-        fprintf(to, "%s:%d: %s\n", this->file.c_str(), this->line, this->error.c_str());
-    } else {
-        fprintf(to, "%s: %s\n", this->file.c_str(), this->error.c_str());
-    }
-}
-
-// SourcePos
-// =============================================================================
-SourcePos::SourcePos(const string& f, int l)
-    : file(f), line(l)
-{
-}
-
-SourcePos::SourcePos(const SourcePos& that)
-    : file(that.file), line(that.line)
-{
-}
-
-SourcePos::SourcePos()
-    : file("???", 0)
-{
-}
-
-SourcePos::~SourcePos()
-{
-}
-
-string
-SourcePos::ToString() const
-{
-    char buf[1024];
-    if (this->line >= 0) {
-        snprintf(buf, sizeof(buf)-1, "%s:%d", this->file.c_str(), this->line);
-    } else {
-        snprintf(buf, sizeof(buf)-1, "%s:", this->file.c_str());
-    }
-    buf[sizeof(buf)-1] = '\0';
-    return string(buf);
-}
-
-int
-SourcePos::Error(const char* fmt, ...) const
-{
-    int retval=0;
-    char buf[1024];
-    va_list ap;
-    va_start(ap, fmt);
-    retval = vsnprintf(buf, sizeof(buf), fmt, ap);
-    va_end(ap);
-    char* p = buf + retval - 1;
-    while (p > buf && *p == '\n') {
-        *p = '\0';
-        p--;
-    }
-    ErrorPos err(this->file, this->line, string(buf));
-    if (g_errors.find(err) == g_errors.end()) {
-        err.Print(stderr);
-        g_errors.insert(err);
-    }
-    return retval;
-}
-
-bool
-SourcePos::HasErrors()
-{
-    return g_errors.size() > 0;
-}
-
-void
-SourcePos::PrintErrors(FILE* to)
-{
-    set<ErrorPos>::const_iterator it;
-    for (it=g_errors.begin(); it!=g_errors.end(); it++) {
-        it->Print(to);
-    }
-}
-
-
-
-
diff --git a/tools/localize/SourcePos.h b/tools/localize/SourcePos.h
deleted file mode 100644
index 5027129..0000000
--- a/tools/localize/SourcePos.h
+++ /dev/null
@@ -1,28 +0,0 @@
-#ifndef SOURCEPOS_H
-#define SOURCEPOS_H
-
-#include <string>
-
-using namespace std;
-
-class SourcePos
-{
-public:
-    string file;
-    int line;
-
-    SourcePos(const string& f, int l);
-    SourcePos(const SourcePos& that);
-    SourcePos();
-    ~SourcePos();
-
-    string ToString() const;
-    int Error(const char* fmt, ...) const;
-
-    static bool HasErrors();
-    static void PrintErrors(FILE* to);
-};
-
-extern const SourcePos GENERATED_POS;
-
-#endif // SOURCEPOS_H
diff --git a/tools/localize/Values.cpp b/tools/localize/Values.cpp
deleted file mode 100644
index 8623b97..0000000
--- a/tools/localize/Values.cpp
+++ /dev/null
@@ -1,135 +0,0 @@
-#include "Values.h"
-#include <stdlib.h>
-#include <cstdio>
-
-
-// =====================================================================================
-StringResource::StringResource(const SourcePos& p, const string& f, const Configuration& c, 
-                    const string& i, int ix, XMLNode* v, const int ve, const string& vs,
-                    const string& cmnt)
-    :pos(p),
-     file(f),
-     config(c),
-     id(i),
-     index(ix),
-     value(v),
-     version(ve),
-     versionString(vs),
-     comment(cmnt)
-{
-}
-
-StringResource::StringResource()
-    :pos(),
-     file(),
-     config(),
-     id(),
-     index(-1),
-     value(NULL),
-     version(),
-     versionString(),
-     comment()
-{
-}
-
-StringResource::StringResource(const StringResource& that)
-    :pos(that.pos),
-     file(that.file),
-     config(that.config),
-     id(that.id),
-     index(that.index),
-     value(that.value),
-     version(that.version),
-     versionString(that.versionString),
-     comment(that.comment)
-{
-}
-
-int
-StringResource::Compare(const StringResource& that) const
-{
-    if (file != that.file) {
-        return file < that.file ? -1 : 1;
-    }
-    if (id != that.id) {
-        return id < that.id ? -1 : 1;
-    }
-    if (index != that.index) {
-        return index - that.index;
-    }
-    if (config != that.config) {
-        return config < that.config ? -1 : 1;
-    }
-    if (version != that.version) {
-        return version < that.version ? -1 : 1;
-    }
-    return 0;
-}
-
-string
-StringResource::TypedID() const
-{
-    string result;
-    if (index < 0) {
-        result = "string:";
-    } else {
-        char n[20];
-        sprintf(n, "%d:", index);
-        result = "array:";
-        result += n;
-    }
-    result += id;
-    return result;
-}
-
-static void
-split(const string& raw, vector<string>*parts)
-{
-    size_t index = 0;
-    while (true) {
-        size_t next = raw.find(':', index);
-        if (next != raw.npos) {
-            parts->push_back(string(raw, index, next-index));
-            index = next + 1;
-        } else {
-            parts->push_back(string(raw, index));
-            break;
-        }
-    }
-}
-
-bool
-StringResource::ParseTypedID(const string& raw, string* id, int* index)
-{
-    vector<string> parts;
-    split(raw, &parts);
-
-    const size_t N = parts.size();
-
-    for (size_t i=0; i<N; i++) {
-        if (parts[i].length() == 0) {
-            return false;
-        }
-    }
-
-    if (N == 2 && parts[0] == "string") {
-        *id = parts[1];
-        *index = -1;
-        return true;
-    }
-    else if (N == 3 && parts[0] == "array") {
-        char* p;
-        int n = (int)strtol(parts[1].c_str(), &p, 0);
-        if (*p == '\0') {
-            *id = parts[2];
-            *index = n;
-            return true;
-        } else {
-            return false;
-        }
-    }
-    else {
-        return false;
-    }
-}
-
diff --git a/tools/localize/Values.h b/tools/localize/Values.h
deleted file mode 100644
index 0a60b6d..0000000
--- a/tools/localize/Values.h
+++ /dev/null
@@ -1,48 +0,0 @@
-#ifndef VALUES_H
-#define VALUES_H
-
-#include "Configuration.h"
-#include "XMLHandler.h"
-
-#include <string>
-
-using namespace std;
-
-enum {
-    CURRENT_VERSION,
-    OLD_VERSION
-};
-
-struct StringResource
-{
-    StringResource();
-    StringResource(const SourcePos& pos, const string& file, const Configuration& config, 
-                    const string& id, int index, XMLNode* value,
-                    int version, const string& versionString, const string& comment = "");
-    StringResource(const StringResource& that);
-
-    // Compare two configurations
-    int Compare(const StringResource& that) const;
-
-    inline bool operator<(const StringResource& that) const { return Compare(that) < 0; }
-    inline bool operator<=(const StringResource& that) const { return Compare(that) <= 0; }
-    inline bool operator==(const StringResource& that) const { return Compare(that) == 0; }
-    inline bool operator!=(const StringResource& that) const { return Compare(that) != 0; }
-    inline bool operator>=(const StringResource& that) const { return Compare(that) >= 0; }
-    inline bool operator>(const StringResource& that) const { return Compare(that) > 0; }
-
-    string TypedID() const;
-    static bool ParseTypedID(const string& typed, string* id, int* index);
-
-    SourcePos pos;
-    string file;
-    Configuration config;
-    string id;
-    int index;
-    XMLNode* value;
-    int version;
-    string versionString;
-    string comment;
-};
-
-#endif // VALUES_H
diff --git a/tools/localize/ValuesFile.cpp b/tools/localize/ValuesFile.cpp
deleted file mode 100644
index bd6f494..0000000
--- a/tools/localize/ValuesFile.cpp
+++ /dev/null
@@ -1,266 +0,0 @@
-#include "ValuesFile.h"
-
-#include "XMLHandler.h"
-
-#include <algorithm>
-#include <fcntl.h>
-#include <expat.h>
-#include <unistd.h>
-#include <errno.h>
-
-using namespace std;
-
-const char* const ANDROID_XMLNS = "http://schemas.android.com/apk/res/android";
-const char* const XLIFF_XMLNS = "urn:oasis:names:tc:xliff:document:1.2";
-
-const char *const NS_MAP[] = {
-    "android", ANDROID_XMLNS,
-    "xliff", XLIFF_XMLNS,
-    NULL, NULL
-};
-
-const XMLNamespaceMap ANDROID_NAMESPACES(NS_MAP);
-
-
-// =====================================================================================
-class ArrayHandler : public XMLHandler
-{
-public:
-    ArrayHandler(ValuesFile* vf, int version, const string& versionString, const string& id);
-
-    virtual int OnStartElement(const SourcePos& pos, const string& ns, const string& name,
-                                const vector<XMLAttribute>& attrs, XMLHandler** next);
-    virtual int OnText(const SourcePos& pos, const string& text);
-    virtual int OnComment(const SourcePos& pos, const string& text);
-
-private:
-    ValuesFile* m_vf;
-    int m_version;
-    int m_index;
-    string m_versionString;
-    string m_id;
-    string m_comment;
-};
-
-ArrayHandler::ArrayHandler(ValuesFile* vf, int version, const string& versionString,
-                            const string& id)
-    :m_vf(vf),
-     m_version(version),
-     m_index(0),
-     m_versionString(versionString),
-     m_id(id)
-{
-}
-
-int
-ArrayHandler::OnStartElement(const SourcePos& pos, const string& ns, const string& name,
-                                const vector<XMLAttribute>& attrs, XMLHandler** next)
-{
-    if (ns == "" && name == "item") {
-        XMLNode* node = XMLNode::NewElement(pos, ns, name, attrs, XMLNode::EXACT);
-        m_vf->AddString(StringResource(pos, pos.file, m_vf->GetConfiguration(),
-                                            m_id, m_index, node, m_version, m_versionString,
-                                            trim_string(m_comment)));
-        *next = new NodeHandler(node, XMLNode::EXACT);
-        m_index++;
-        m_comment = "";
-        return 0;
-    } else {
-        pos.Error("invalid <%s> element inside <array>\n", name.c_str());
-        return 1;
-    }
-}
-
-int
-ArrayHandler::OnText(const SourcePos& pos, const string& text)
-{
-    return 0;
-}
-
-int
-ArrayHandler::OnComment(const SourcePos& pos, const string& text)
-{
-    m_comment += text;
-    return 0;
-}
-
-// =====================================================================================
-class ValuesHandler : public XMLHandler
-{
-public:
-    ValuesHandler(ValuesFile* vf, int version, const string& versionString);
-
-    virtual int OnStartElement(const SourcePos& pos, const string& ns, const string& name,
-                                const vector<XMLAttribute>& attrs, XMLHandler** next);
-    virtual int OnText(const SourcePos& pos, const string& text);
-    virtual int OnComment(const SourcePos& pos, const string& text);
-
-private:
-    ValuesFile* m_vf;
-    int m_version;
-    string m_versionString;
-    string m_comment;
-};
-
-ValuesHandler::ValuesHandler(ValuesFile* vf, int version, const string& versionString)
-    :m_vf(vf),
-     m_version(version),
-     m_versionString(versionString)
-{
-}
-
-int
-ValuesHandler::OnStartElement(const SourcePos& pos, const string& ns, const string& name,
-                                const vector<XMLAttribute>& attrs, XMLHandler** next)
-{
-    if (ns == "" && name == "string") {
-        string id = XMLAttribute::Find(attrs, "", "name", "");
-        XMLNode* node = XMLNode::NewElement(pos, ns, name, attrs, XMLNode::EXACT);
-        m_vf->AddString(StringResource(pos, pos.file, m_vf->GetConfiguration(),
-                                            id, -1, node, m_version, m_versionString,
-                                            trim_string(m_comment)));
-        *next = new NodeHandler(node, XMLNode::EXACT);
-    }
-    else if (ns == "" && name == "array") {
-        string id = XMLAttribute::Find(attrs, "", "name", "");
-        *next = new ArrayHandler(m_vf, m_version, m_versionString, id);
-    }
-    m_comment = "";
-    return 0;
-}
-
-int
-ValuesHandler::OnText(const SourcePos& pos, const string& text)
-{
-    return 0;
-}
-
-int
-ValuesHandler::OnComment(const SourcePos& pos, const string& text)
-{
-    m_comment += text;
-    return 0;
-}
-
-// =====================================================================================
-ValuesFile::ValuesFile(const Configuration& config)
-    :m_config(config),
-     m_strings(),
-     m_arrays()
-{
-}
-
-ValuesFile::~ValuesFile()
-{
-}
-
-ValuesFile*
-ValuesFile::ParseFile(const string& filename, const Configuration& config,
-                    int version, const string& versionString)
-{
-    ValuesFile* result = new ValuesFile(config);
-
-    TopElementHandler top("", "resources", new ValuesHandler(result, version, versionString));
-    XMLHandler::ParseFile(filename, &top);
-
-    return result;
-}
-
-ValuesFile*
-ValuesFile::ParseString(const string& filename, const string& text, const Configuration& config,
-                    int version, const string& versionString)
-{
-    ValuesFile* result = new ValuesFile(config);
-
-    TopElementHandler top("", "resources", new ValuesHandler(result, version, versionString));
-    XMLHandler::ParseString(filename, text, &top);
-
-    return result;
-}
-
-const Configuration&
-ValuesFile::GetConfiguration() const
-{
-    return m_config;
-}
-
-void
-ValuesFile::AddString(const StringResource& str)
-{
-    if (str.index < 0) {
-        m_strings.insert(str);
-    } else {
-        m_arrays[str.id].insert(str);
-    }
-}
-
-set<StringResource>
-ValuesFile::GetStrings() const
-{
-    set<StringResource> result = m_strings;
-
-    for (map<string,set<StringResource> >::const_iterator it = m_arrays.begin();
-            it != m_arrays.end(); it++) {
-        result.insert(it->second.begin(), it->second.end());
-    }
-
-    return result;
-}
-
-XMLNode*
-ValuesFile::ToXMLNode() const
-{
-    XMLNode* root;
-
-    // <resources>
-    {
-        vector<XMLAttribute> attrs;
-        ANDROID_NAMESPACES.AddToAttributes(&attrs);
-        root = XMLNode::NewElement(GENERATED_POS, "", "resources", attrs, XMLNode::PRETTY);
-    }
-
-    // <array>
-    for (map<string,set<StringResource> >::const_iterator it = m_arrays.begin();
-            it != m_arrays.end(); it++) {
-        vector<XMLAttribute> arrayAttrs;
-        arrayAttrs.push_back(XMLAttribute("", "name", it->first));
-        const set<StringResource>& items = it->second;
-        XMLNode* arrayNode = XMLNode::NewElement(items.begin()->pos, "", "array", arrayAttrs,
-                XMLNode::PRETTY);
-        root->EditChildren().push_back(arrayNode);
-
-        // <item>
-        for (set<StringResource>::const_iterator item = items.begin();
-                item != items.end(); item++) {
-            XMLNode* itemNode = item->value->Clone();
-            itemNode->SetName("", "item");
-            itemNode->EditAttributes().clear();
-            arrayNode->EditChildren().push_back(itemNode);
-        }
-    }
-
-    // <string>
-    for (set<StringResource>::const_iterator it=m_strings.begin(); it!=m_strings.end(); it++) {
-        const StringResource& str = *it;
-        vector<XMLAttribute> attrs;
-        XMLNode* strNode = str.value->Clone();
-        strNode->SetName("", "string");
-        strNode->EditAttributes().clear();
-        strNode->EditAttributes().push_back(XMLAttribute("", "name", str.id));
-        root->EditChildren().push_back(strNode);
-    }
-
-    return root;
-}
-
-string
-ValuesFile::ToString() const
-{
-    XMLNode* xml = ToXMLNode();
-    string s = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n";
-    s += xml->ToString(ANDROID_NAMESPACES);
-    delete xml;
-    s += '\n';
-    return s;
-}
-
diff --git a/tools/localize/ValuesFile.h b/tools/localize/ValuesFile.h
deleted file mode 100644
index 752fd78..0000000
--- a/tools/localize/ValuesFile.h
+++ /dev/null
@@ -1,52 +0,0 @@
-#ifndef VALUES_FILE_H
-#define VALUES_FILE_H
-
-#include "SourcePos.h"
-#include "Configuration.h"
-#include "XMLHandler.h"
-#include "Values.h"
-
-#include <string>
-#include <set>
-
-using namespace std;
-
-extern const XMLNamespaceMap ANDROID_NAMESPACES;
-
-class ValuesFile
-{
-public:
-    ValuesFile(const Configuration& config);
-
-    static ValuesFile* ParseFile(const string& filename, const Configuration& config,
-                                     int version, const string& versionString);
-    static ValuesFile* ParseString(const string& filename, const string& text,
-                                     const Configuration& config,
-                                     int version, const string& versionString);
-    ~ValuesFile();
-
-    const Configuration& GetConfiguration() const;
-
-    void AddString(const StringResource& str);
-    set<StringResource> GetStrings() const;
-
-    // exports this file as a n XMLNode, you own this object
-    XMLNode* ToXMLNode() const;
-
-    // writes the ValuesFile out to a string in the canonical format (i.e. writes the contents of
-    // ToXMLNode()).
-    string ToString() const;
-
-private:
-    class ParseState;
-    friend class ValuesFile::ParseState;
-    friend class StringHandler;
-
-    ValuesFile();
-
-    Configuration m_config;
-    set<StringResource> m_strings;
-    map<string,set<StringResource> > m_arrays;
-};
-
-#endif // VALUES_FILE_H
diff --git a/tools/localize/ValuesFile_test.cpp b/tools/localize/ValuesFile_test.cpp
deleted file mode 100644
index 56d2ec2..0000000
--- a/tools/localize/ValuesFile_test.cpp
+++ /dev/null
@@ -1,54 +0,0 @@
-#include "ValuesFile.h"
-#include <stdio.h>
-
-int
-ValuesFile_test()
-{
-    int err = 0;
-    Configuration config;
-    config.locale = "zz_ZZ";
-    ValuesFile* vf = ValuesFile::ParseFile("testdata/values/strings.xml", config,
-                                        OLD_VERSION, "1");
-
-    const set<StringResource>& strings = vf->GetStrings();
-    string canonical = vf->ToString();
-
-    if (false) {
-        printf("Strings (%zd)\n", strings.size());
-            for (set<StringResource>::const_iterator it=strings.begin();
-                    it!=strings.end(); it++) {
-            const StringResource& str = *it;
-            printf("%s: '%s'[%d]='%s' (%s) <!-- %s -->\n", str.pos.ToString().c_str(),
-                    str.id.c_str(), str.index,
-                    str.value->ContentsToString(ANDROID_NAMESPACES).c_str(),
-                    str.config.ToString().c_str(), str.comment.c_str());
-        }
-
-        printf("XML:[[%s]]\n", canonical.c_str());
-    }
-
-    const char * const EXPECTED =
-        "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
-        "<resources xmlns:android=\"http://schemas.android.com/apk/res/android\"\n"
-        "    xmlns:xliff=\"urn:oasis:names:tc:xliff:document:1.2\">\n"
-        "  <array name=\"emailAddressTypes\">\n"
-        "    <item>Email</item>\n"
-        "    <item>Home</item>\n"
-        "    <item>Work</item>\n"
-        "    <item>Other\\u2026</item>\n"
-        "  </array>\n"
-        "  <string name=\"test1\">Discard</string>\n"
-        "  <string name=\"test2\">a<b>b<i>c</i></b>d</string>\n"
-        "  <string name=\"test3\">a<xliff:g a=\"b\" xliff:a=\"asdf\">bBb</xliff:g>C</string>\n"
-        "</resources>\n";
-
-    if (canonical != EXPECTED) {
-        fprintf(stderr, "ValuesFile_test failed\n");
-        fprintf(stderr, "canonical=[[%s]]\n", canonical.c_str());
-        fprintf(stderr, "EXPECTED=[[%s]]\n", EXPECTED);
-        err = 1;
-    }
-
-    delete vf;
-    return err;
-}
diff --git a/tools/localize/XLIFFFile.cpp b/tools/localize/XLIFFFile.cpp
deleted file mode 100644
index 4e217d9..0000000
--- a/tools/localize/XLIFFFile.cpp
+++ /dev/null
@@ -1,610 +0,0 @@
-#include "XLIFFFile.h"
-
-#include <algorithm>
-#include <sys/time.h>
-#include <time.h>
-#include <cstdio>
-
-const char* const XLIFF_XMLNS = "urn:oasis:names:tc:xliff:document:1.2";
-
-const char *const NS_MAP[] = {
-    "", XLIFF_XMLNS,
-    "xml", XMLNS_XMLNS,
-    NULL, NULL
-};
-
-const XMLNamespaceMap XLIFF_NAMESPACES(NS_MAP);
-
-int
-XLIFFFile::File::Compare(const XLIFFFile::File& that) const
-{
-    if (filename != that.filename) {
-        return filename < that.filename ? -1 : 1;
-    }
-    return 0;
-}
-
-// =====================================================================================
-XLIFFFile::XLIFFFile()
-{
-}
-
-XLIFFFile::~XLIFFFile()
-{
-}
-
-static XMLNode*
-get_unique_node(const XMLNode* parent, const string& ns, const string& name, bool required)
-{
-    size_t count = parent->CountElementsByName(ns, name);
-    if (count == 1) {
-        return parent->GetElementByNameAt(ns, name, 0);
-    } else {
-        if (required) {
-            SourcePos pos = count == 0
-                                ? parent->Position()
-                                : parent->GetElementByNameAt(XLIFF_XMLNS, name, 1)->Position();
-            pos.Error("<%s> elements must contain exactly one <%s> element",
-                                parent->Name().c_str(), name.c_str());
-        }
-        return NULL;
-    }
-}
-
-XLIFFFile*
-XLIFFFile::Parse(const string& filename)
-{
-    XLIFFFile* result = new XLIFFFile();
-
-    XMLNode* root = NodeHandler::ParseFile(filename, XMLNode::PRETTY);
-    if (root == NULL) {
-        return NULL;
-    }
-
-    // <file>
-    vector<XMLNode*> files = root->GetElementsByName(XLIFF_XMLNS, "file");
-    for (size_t i=0; i<files.size(); i++) {
-        XMLNode* file = files[i];
-
-        string datatype = file->GetAttribute("", "datatype", "");
-        string originalFile = file->GetAttribute("", "original", "");
-
-        Configuration sourceConfig;
-        sourceConfig.locale = file->GetAttribute("", "source-language", "");
-        result->m_sourceConfig = sourceConfig;
-
-        Configuration targetConfig;
-        targetConfig.locale = file->GetAttribute("", "target-language", "");
-        result->m_targetConfig = targetConfig;
-
-        result->m_currentVersion = file->GetAttribute("", "build-num", "");
-        result->m_oldVersion = "old";
-
-        // <body>
-        XMLNode* body = get_unique_node(file, XLIFF_XMLNS, "body", true);
-        if (body == NULL) continue;
-
-        // <trans-unit>
-        vector<XMLNode*> transUnits = body->GetElementsByName(XLIFF_XMLNS, "trans-unit");
-        for (size_t j=0; j<transUnits.size(); j++) {
-            XMLNode* transUnit = transUnits[j];
-
-            string rawID = transUnit->GetAttribute("", "id", "");
-            if (rawID == "") {
-                transUnit->Position().Error("<trans-unit> tag requires an id");
-                continue;
-            }
-            string id;
-            int index;
-
-            if (!StringResource::ParseTypedID(rawID, &id, &index)) {
-                transUnit->Position().Error("<trans-unit> has invalid id '%s'\n", rawID.c_str());
-                continue;
-            }
-
-            // <source>
-            XMLNode* source = get_unique_node(transUnit, XLIFF_XMLNS, "source", false);
-            if (source != NULL) {
-                XMLNode* node = source->Clone();
-                node->SetPrettyRecursive(XMLNode::EXACT);
-                result->AddStringResource(StringResource(source->Position(), originalFile,
-                            sourceConfig, id, index, node, CURRENT_VERSION,
-                            result->m_currentVersion));
-            }
-
-            // <target>
-            XMLNode* target = get_unique_node(transUnit, XLIFF_XMLNS, "target", false);
-            if (target != NULL) {
-                XMLNode* node = target->Clone();
-                node->SetPrettyRecursive(XMLNode::EXACT);
-                result->AddStringResource(StringResource(target->Position(), originalFile,
-                            targetConfig, id, index, node, CURRENT_VERSION,
-                            result->m_currentVersion));
-            }
-
-            // <alt-trans>
-            XMLNode* altTrans = get_unique_node(transUnit, XLIFF_XMLNS, "alt-trans", false);
-            if (altTrans != NULL) {
-                // <source>
-                XMLNode* altSource = get_unique_node(altTrans, XLIFF_XMLNS, "source", false);
-                if (altSource != NULL) {
-                    XMLNode* node = altSource->Clone();
-                    node->SetPrettyRecursive(XMLNode::EXACT);
-                    result->AddStringResource(StringResource(altSource->Position(),
-                                originalFile, sourceConfig, id, index, node, OLD_VERSION,
-                                result->m_oldVersion));
-                }
-
-                // <target>
-                XMLNode* altTarget = get_unique_node(altTrans, XLIFF_XMLNS, "target", false);
-                if (altTarget != NULL) {
-                    XMLNode* node = altTarget->Clone();
-                    node->SetPrettyRecursive(XMLNode::EXACT);
-                    result->AddStringResource(StringResource(altTarget->Position(),
-                                originalFile, targetConfig, id, index, node, OLD_VERSION,
-                                result->m_oldVersion));
-                }
-            }
-        }
-    }
-    delete root;
-    return result;
-}
-
-XLIFFFile*
-XLIFFFile::Create(const Configuration& sourceConfig, const Configuration& targetConfig,
-                                const string& currentVersion)
-{
-    XLIFFFile* result = new XLIFFFile();
-        result->m_sourceConfig = sourceConfig;
-        result->m_targetConfig = targetConfig;
-        result->m_currentVersion = currentVersion;
-    return result;
-}
-
-set<string>
-XLIFFFile::Files() const
-{
-    set<string> result;
-    for (vector<File>::const_iterator f = m_files.begin(); f != m_files.end(); f++) {
-        result.insert(f->filename);
-    }
-    return result;
-}
-
-void
-XLIFFFile::AddStringResource(const StringResource& str)
-{
-    string id = str.TypedID();
-
-    File* f = NULL;
-    const size_t I = m_files.size();
-    for (size_t i=0; i<I; i++) {
-        if (m_files[i].filename == str.file) {
-            f = &m_files[i];
-            break;
-        }
-    }
-    if (f == NULL) {
-        File file;
-        file.filename = str.file;
-        m_files.push_back(file);
-        f = &m_files[I];
-    }
-
-    const size_t J = f->transUnits.size();
-    TransUnit* g = NULL;
-    for (size_t j=0; j<J; j++) {
-        if (f->transUnits[j].id == id) {
-            g = &f->transUnits[j];
-        }
-    }
-    if (g == NULL) {
-        TransUnit group;
-        group.id = id;
-        f->transUnits.push_back(group);
-        g = &f->transUnits[J];
-    }
-
-    StringResource* res = find_string_res(*g, str);
-    if (res == NULL) {
-        return ;
-    }
-    if (res->id != "") {
-        str.pos.Error("Duplicate string resource: %s", res->id.c_str());
-        res->pos.Error("Previous definition here");
-        return ;
-    }
-    *res = str;
-
-    m_strings.insert(str);
-}
-
-void
-XLIFFFile::Filter(bool (*func)(const string&,const TransUnit&,void*), void* cookie)
-{
-    const size_t I = m_files.size();
-    for (size_t ix=0, i=I-1; ix<I; ix++, i--) {
-        File& file = m_files[i];
-
-        const size_t J = file.transUnits.size();
-        for (size_t jx=0, j=J-1; jx<J; jx++, j--) {
-            TransUnit& tu = file.transUnits[j];
-
-            bool keep = func(file.filename, tu, cookie);
-            if (!keep) {
-                if (tu.source.id != "") {
-                    m_strings.erase(tu.source);
-                }
-                if (tu.target.id != "") {
-                    m_strings.erase(tu.target);
-                }
-                if (tu.altSource.id != "") {
-                    m_strings.erase(tu.altSource);
-                }
-                if (tu.altTarget.id != "") {
-                    m_strings.erase(tu.altTarget);
-                }
-                file.transUnits.erase(file.transUnits.begin()+j);
-            }
-        }
-        if (file.transUnits.size() == 0) {
-            m_files.erase(m_files.begin()+i);
-        }
-    }
-}
-
-void
-XLIFFFile::Map(void (*func)(const string&,TransUnit*,void*), void* cookie)
-{
-    const size_t I = m_files.size();
-    for (size_t i=0; i<I; i++) {
-        File& file = m_files[i];
-
-        const size_t J = file.transUnits.size();
-        for (size_t j=0; j<J; j++) {
-            func(file.filename, &(file.transUnits[j]), cookie);
-        }
-    }
-}
-
-TransUnit*
-XLIFFFile::EditTransUnit(const string& filename, const string& id)
-{
-    const size_t I = m_files.size();
-    for (size_t ix=0, i=I-1; ix<I; ix++, i--) {
-        File& file = m_files[i];
-        if (file.filename == filename) {
-            const size_t J = file.transUnits.size();
-            for (size_t jx=0, j=J-1; jx<J; jx++, j--) {
-                TransUnit& tu = file.transUnits[j];
-                if (tu.id == id) {
-                    return &tu;
-                }
-            }
-        }
-    }
-    return NULL;
-}
-
-StringResource*
-XLIFFFile::find_string_res(TransUnit& g, const StringResource& str)
-{
-    int index;
-    if (str.version == CURRENT_VERSION) {
-        index = 0;
-    }
-    else if (str.version == OLD_VERSION) {
-        index = 2;
-    }
-    else {
-        str.pos.Error("Internal Error %s:%d\n", __FILE__, __LINE__);
-        return NULL;
-    }
-    if (str.config == m_sourceConfig) {
-        // index += 0;
-    }
-    else if (str.config == m_targetConfig) {
-        index += 1;
-    }
-    else {
-        str.pos.Error("unknown config for string %s: %s", str.id.c_str(),
-                            str.config.ToString().c_str());
-        return NULL;
-    }
-    switch (index) {
-        case 0:
-            return &g.source;
-        case 1:
-            return &g.target;
-        case 2:
-            return &g.altSource;
-        case 3:
-            return &g.altTarget;
-    }
-    str.pos.Error("Internal Error %s:%d\n", __FILE__, __LINE__);
-    return NULL;
-}
-
-int
-convert_html_to_xliff(const XMLNode* original, const string& name, XMLNode* addTo, int* phID)
-{
-    int err = 0;
-    if (original->Type() == XMLNode::TEXT) {
-        addTo->EditChildren().push_back(original->Clone());
-        return 0;
-    } else {
-        string ctype;
-        if (original->Namespace() == "") {
-            if (original->Name() == "b") {
-                ctype = "bold";
-            }
-            else if (original->Name() == "i") {
-                ctype = "italic";
-            }
-            else if (original->Name() == "u") {
-                ctype = "underline";
-            }
-        }
-        if (ctype != "") {
-            vector<XMLAttribute> attrs;
-            attrs.push_back(XMLAttribute(XLIFF_XMLNS, "ctype", ctype));
-            XMLNode* copy = XMLNode::NewElement(original->Position(), XLIFF_XMLNS, "g",
-                                                attrs, XMLNode::EXACT);
-
-            const vector<XMLNode*>& children = original->Children();
-            size_t I = children.size();
-            for (size_t i=0; i<I; i++) {
-                err |= convert_html_to_xliff(children[i], name, copy, phID);
-            }
-            return err;
-        }
-        else {
-            if (original->Namespace() == XLIFF_XMLNS) {
-                addTo->EditChildren().push_back(original->Clone());
-                return 0;
-            } else {
-                if (original->Namespace() == "") {
-                    // flatten out the tag into ph tags -- but only if there is no namespace
-                    // that's still unsupported because propagating the xmlns attribute is hard.
-                    vector<XMLAttribute> attrs;
-                    char idStr[30];
-                    (*phID)++;
-                    sprintf(idStr, "id-%d", *phID);
-                    attrs.push_back(XMLAttribute(XLIFF_XMLNS, "id", idStr));
-
-                    if (original->Children().size() == 0) {
-                        XMLNode* ph = XMLNode::NewElement(original->Position(), XLIFF_XMLNS,
-                                "ph", attrs, XMLNode::EXACT);
-                        ph->EditChildren().push_back(
-                                XMLNode::NewText(original->Position(),
-                                    original->ToString(XLIFF_NAMESPACES),
-                                    XMLNode::EXACT));
-                        addTo->EditChildren().push_back(ph);
-                    } else {
-                        XMLNode* begin = XMLNode::NewElement(original->Position(), XLIFF_XMLNS,
-                                "bpt", attrs, XMLNode::EXACT);
-                        begin->EditChildren().push_back(
-                                XMLNode::NewText(original->Position(),
-                                    original->OpenTagToString(XLIFF_NAMESPACES, XMLNode::EXACT),
-                                    XMLNode::EXACT));
-                        XMLNode* end = XMLNode::NewElement(original->Position(), XLIFF_XMLNS,
-                                "ept", attrs, XMLNode::EXACT);
-                        string endText = "</";
-                            endText += original->Name();
-                            endText += ">";
-                        end->EditChildren().push_back(XMLNode::NewText(original->Position(),
-                                endText, XMLNode::EXACT));
-
-                        addTo->EditChildren().push_back(begin);
-
-                        const vector<XMLNode*>& children = original->Children();
-                        size_t I = children.size();
-                        for (size_t i=0; i<I; i++) {
-                            err |= convert_html_to_xliff(children[i], name, addTo, phID);
-                        }
-
-                        addTo->EditChildren().push_back(end);
-                    }
-                    return err;
-                } else {
-                    original->Position().Error("invalid <%s> element in <%s> tag\n",
-                                                original->Name().c_str(), name.c_str());
-                    return 1;
-                }
-            }
-        }
-    }
-}
-
-XMLNode*
-create_string_node(const StringResource& str, const string& name)
-{
-    vector<XMLAttribute> attrs;
-    attrs.push_back(XMLAttribute(XMLNS_XMLNS, "space", "preserve"));
-    XMLNode* node = XMLNode::NewElement(str.pos, XLIFF_XMLNS, name, attrs, XMLNode::EXACT);
-
-    const vector<XMLNode*>& children = str.value->Children();
-    size_t I = children.size();
-    int err = 0;
-    for (size_t i=0; i<I; i++) {
-        int phID = 0;
-        err |= convert_html_to_xliff(children[i], name, node, &phID);
-    }
-
-    if (err != 0) {
-        delete node;
-    }
-    return node;
-}
-
-static bool
-compare_id(const TransUnit& lhs, const TransUnit& rhs)
-{
-    string lid, rid;
-    int lindex, rindex;
-    StringResource::ParseTypedID(lhs.id, &lid, &lindex);
-    StringResource::ParseTypedID(rhs.id, &rid, &rindex);
-    if (lid < rid) return true;
-    if (lid == rid && lindex < rindex) return true;
-    return false;
-}
-
-XMLNode*
-XLIFFFile::ToXMLNode() const
-{
-    XMLNode* root;
-    size_t N;
-
-    // <xliff>
-    {
-        vector<XMLAttribute> attrs;
-        XLIFF_NAMESPACES.AddToAttributes(&attrs);
-        attrs.push_back(XMLAttribute(XLIFF_XMLNS, "version", "1.2"));
-        root = XMLNode::NewElement(GENERATED_POS, XLIFF_XMLNS, "xliff", attrs, XMLNode::PRETTY);
-    }
-
-    vector<TransUnit> groups;
-
-    // <file>
-    vector<File> files = m_files;
-    sort(files.begin(), files.end());
-    const size_t I = files.size();
-    for (size_t i=0; i<I; i++) {
-        const File& file = files[i];
-
-        vector<XMLAttribute> fileAttrs;
-        fileAttrs.push_back(XMLAttribute(XLIFF_XMLNS, "datatype", "x-android-res"));
-        fileAttrs.push_back(XMLAttribute(XLIFF_XMLNS, "original", file.filename));
-
-        struct timeval tv;
-        struct timezone tz;
-        gettimeofday(&tv, &tz);
-        fileAttrs.push_back(XMLAttribute(XLIFF_XMLNS, "date", trim_string(ctime(&tv.tv_sec))));
-
-        fileAttrs.push_back(XMLAttribute(XLIFF_XMLNS, "source-language", m_sourceConfig.locale));
-        fileAttrs.push_back(XMLAttribute(XLIFF_XMLNS, "target-language", m_targetConfig.locale));
-        fileAttrs.push_back(XMLAttribute(XLIFF_XMLNS, "build-num", m_currentVersion));
-
-        XMLNode* fileNode = XMLNode::NewElement(GENERATED_POS, XLIFF_XMLNS, "file", fileAttrs,
-                                                XMLNode::PRETTY);
-        root->EditChildren().push_back(fileNode);
-
-        // <body>
-        XMLNode* bodyNode = XMLNode::NewElement(GENERATED_POS, XLIFF_XMLNS, "body",
-                                                vector<XMLAttribute>(), XMLNode::PRETTY);
-        fileNode->EditChildren().push_back(bodyNode);
-
-        // <trans-unit>
-        vector<TransUnit> transUnits = file.transUnits;
-        sort(transUnits.begin(), transUnits.end(), compare_id);
-        const size_t J = transUnits.size();
-        for (size_t j=0; j<J; j++) {
-            const TransUnit& transUnit = transUnits[j];
-
-            vector<XMLAttribute> tuAttrs;
-
-            // strings start with string:
-            tuAttrs.push_back(XMLAttribute(XLIFF_XMLNS, "id", transUnit.id));
-            XMLNode* transUnitNode = XMLNode::NewElement(GENERATED_POS, XLIFF_XMLNS, "trans-unit",
-                                                         tuAttrs, XMLNode::PRETTY);
-            bodyNode->EditChildren().push_back(transUnitNode);
-
-            // <extradata>
-            if (transUnit.source.comment != "") {
-                vector<XMLAttribute> extradataAttrs;
-                XMLNode* extraNode = XMLNode::NewElement(GENERATED_POS, XLIFF_XMLNS, "extradata",
-                                                            extradataAttrs, XMLNode::EXACT);
-                transUnitNode->EditChildren().push_back(extraNode);
-                extraNode->EditChildren().push_back(
-                        XMLNode::NewText(GENERATED_POS, transUnit.source.comment,
-                                         XMLNode::PRETTY));
-            }
-
-            // <source>
-            if (transUnit.source.id != "") {
-                transUnitNode->EditChildren().push_back(
-                                    create_string_node(transUnit.source, "source"));
-            }
-            
-            // <target>
-            if (transUnit.target.id != "") {
-                transUnitNode->EditChildren().push_back(
-                                    create_string_node(transUnit.target, "target"));
-            }
-
-            // <alt-trans>
-            if (transUnit.altSource.id != "" || transUnit.altTarget.id != ""
-                    || transUnit.rejectComment != "") {
-                vector<XMLAttribute> altTransAttrs;
-                XMLNode* altTransNode = XMLNode::NewElement(GENERATED_POS, XLIFF_XMLNS, "alt-trans",
-                                                            altTransAttrs, XMLNode::PRETTY);
-                transUnitNode->EditChildren().push_back(altTransNode);
-
-                // <extradata>
-                if (transUnit.rejectComment != "") {
-                    vector<XMLAttribute> extradataAttrs;
-                    XMLNode* extraNode = XMLNode::NewElement(GENERATED_POS, XLIFF_XMLNS,
-                                                                "extradata", extradataAttrs,
-                                                                XMLNode::EXACT);
-                    altTransNode->EditChildren().push_back(extraNode);
-                    extraNode->EditChildren().push_back(
-                            XMLNode::NewText(GENERATED_POS, transUnit.rejectComment,
-                                             XMLNode::PRETTY));
-                }
-                
-                // <source>
-                if (transUnit.altSource.id != "") {
-                    altTransNode->EditChildren().push_back(
-                                        create_string_node(transUnit.altSource, "source"));
-                }
-                
-                // <target>
-                if (transUnit.altTarget.id != "") {
-                    altTransNode->EditChildren().push_back(
-                                        create_string_node(transUnit.altTarget, "target"));
-                }
-            }
-            
-        }
-    }
-
-    return root;
-}
-
-
-string
-XLIFFFile::ToString() const
-{
-    XMLNode* xml = ToXMLNode();
-    string s = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n";
-    s += xml->ToString(XLIFF_NAMESPACES);
-    delete xml;
-    s += '\n';
-    return s;
-}
-
-Stats
-XLIFFFile::GetStats(const string& config) const
-{
-    Stats stat;
-    stat.config = config;
-    stat.files = m_files.size();
-    stat.toBeTranslated = 0;
-    stat.noComments = 0;
-
-    for (vector<File>::const_iterator file=m_files.begin(); file!=m_files.end(); file++) {
-        stat.toBeTranslated += file->transUnits.size();
-
-        for (vector<TransUnit>::const_iterator tu=file->transUnits.begin();
-                    tu!=file->transUnits.end(); tu++) {
-            if (tu->source.comment == "") {
-                stat.noComments++;
-            }
-        }
-    }
-
-    stat.totalStrings = stat.toBeTranslated;
-
-    return stat;
-}
diff --git a/tools/localize/XLIFFFile.h b/tools/localize/XLIFFFile.h
deleted file mode 100644
index a93d479..0000000
--- a/tools/localize/XLIFFFile.h
+++ /dev/null
@@ -1,98 +0,0 @@
-#ifndef XLIFF_FILE_H
-#define XLIFF_FILE_H
-
-#include "Values.h"
-
-#include "Configuration.h"
-
-#include <set>
-
-using namespace std;
-
-extern const XMLNamespaceMap XLIFF_NAMESPACES;
-
-extern const char*const XLIFF_XMLNS;
-
-struct Stats
-{
-    string config;
-    size_t files;
-    size_t toBeTranslated;
-    size_t noComments;
-    size_t totalStrings;
-};
-
-struct TransUnit {
-    string id;
-    StringResource source;
-    StringResource target;
-    StringResource altSource;
-    StringResource altTarget;
-    string rejectComment;
-};
-
-class XLIFFFile
-{
-public:
-    static XLIFFFile* Parse(const string& filename);
-    static XLIFFFile* Create(const Configuration& sourceConfig, const Configuration& targetConfig,
-                                const string& currentVersion);
-    ~XLIFFFile();
-
-    inline const Configuration& SourceConfig() const                { return m_sourceConfig; }
-    inline const Configuration& TargetConfig() const                { return m_targetConfig; }
-
-    inline const string& CurrentVersion() const                     { return m_currentVersion; }
-    inline const string& OldVersion() const                         { return m_oldVersion; }
-
-    set<string> Files() const;
-
-    void AddStringResource(const StringResource& res);
-    inline set<StringResource> const& GetStringResources() const { return m_strings; }
-    bool FindStringResource(const string& filename, int version, bool source);
-
-    void Filter(bool (*func)(const string&,const TransUnit&,void*), void* cookie);
-    void Map(void (*func)(const string&,TransUnit*,void*), void* cookie);
-
-    TransUnit* EditTransUnit(const string& file, const string& id);
-
-    // exports this file as a n XMLNode, you own this object
-    XMLNode* ToXMLNode() const;
-
-    // writes the ValuesFile out to a string in the canonical format (i.e. writes the contents of
-    // ToXMLNode()).
-    string ToString() const;
-
-    Stats GetStats(const string& config) const;
-
-private:
-    struct File {
-        int Compare(const File& that) const;
-
-        inline bool operator<(const File& that) const { return Compare(that) < 0; }
-        inline bool operator<=(const File& that) const { return Compare(that) <= 0; }
-        inline bool operator==(const File& that) const { return Compare(that) == 0; }
-        inline bool operator!=(const File& that) const { return Compare(that) != 0; }
-        inline bool operator>=(const File& that) const { return Compare(that) >= 0; }
-        inline bool operator>(const File& that) const { return Compare(that) > 0; }
-
-        string filename;
-        vector<TransUnit> transUnits;
-    };
-
-    XLIFFFile();
-    StringResource* find_string_res(TransUnit& g, const StringResource& str);
-    
-    Configuration m_sourceConfig;
-    Configuration m_targetConfig;
-
-    string m_currentVersion;
-    string m_oldVersion;
-
-    set<StringResource> m_strings;
-    vector<File> m_files;
-};
-
-int convert_html_to_xliff(const XMLNode* original, const string& name, XMLNode* addTo, int* phID);
-
-#endif // XLIFF_FILE_H
diff --git a/tools/localize/XLIFFFile_test.cpp b/tools/localize/XLIFFFile_test.cpp
deleted file mode 100644
index 52ed4c3..0000000
--- a/tools/localize/XLIFFFile_test.cpp
+++ /dev/null
@@ -1,115 +0,0 @@
-#include "XLIFFFile.h"
-#include <stdio.h>
-#include "ValuesFile.h"
-
-XMLNode* create_string_node(const StringResource& str, const string& name);
-
-static int
-Parse_test()
-{
-    XLIFFFile* xf = XLIFFFile::Parse("testdata/xliff1.xliff");
-    if (xf == NULL) {
-        return 1;
-    }
-
-    set<StringResource> const& strings = xf->GetStringResources();
-
-    if (false) {
-        for (set<StringResource>::iterator it=strings.begin(); it!=strings.end(); it++) {
-            const StringResource& str = *it;
-            printf("STRING!!! id=%s index=%d value='%s' pos=%s file=%s version=%d(%s)\n",
-                    str.id.c_str(), str.index,
-                    str.value->ContentsToString(ANDROID_NAMESPACES).c_str(),
-                    str.pos.ToString().c_str(), str.file.c_str(), str.version,
-                    str.versionString.c_str());
-        }
-        printf("XML:[[%s]]\n", xf->ToString().c_str());
-    }
-
-    delete xf;
-    return 0;
-}
-
-static XMLNode*
-add_html_tag(XMLNode* addTo, const string& tag)
-{
-    vector<XMLAttribute> attrs;
-    XMLNode* node = XMLNode::NewElement(GENERATED_POS, "", tag, attrs, XMLNode::EXACT);
-    addTo->EditChildren().push_back(node);
-    return node;
-}
-
-static int
-create_string_node_test()
-{
-    int err = 0;
-    StringResource res;
-    vector<XMLAttribute> attrs;
-    res.value = XMLNode::NewElement(GENERATED_POS, "", "something", attrs, XMLNode::EXACT);
-    res.value->EditChildren().push_back(XMLNode::NewText(GENERATED_POS, " begin ", XMLNode::EXACT));
-
-    XMLNode* child;
-
-    child = add_html_tag(res.value, "b");
-    child->EditChildren().push_back(XMLNode::NewText(GENERATED_POS, "b", XMLNode::EXACT));
-
-    child = add_html_tag(res.value, "i");
-    child->EditChildren().push_back(XMLNode::NewText(GENERATED_POS, "i", XMLNode::EXACT));
-
-    child = add_html_tag(child, "b");
-    child->EditChildren().push_back(XMLNode::NewText(GENERATED_POS, "b", XMLNode::EXACT));
-
-    child = add_html_tag(res.value, "u");
-    child->EditChildren().push_back(XMLNode::NewText(GENERATED_POS, "u", XMLNode::EXACT));
-
-
-    res.value->EditChildren().push_back(XMLNode::NewText(GENERATED_POS, " end ", XMLNode::EXACT));
-
-    XMLNode* xliff = create_string_node(res, "blah");
-
-    string oldString = res.value->ToString(XLIFF_NAMESPACES);
-    string newString = xliff->ToString(XLIFF_NAMESPACES);
-
-    if (false) {
-        printf("OLD=\"%s\"\n", oldString.c_str());
-        printf("NEW=\"%s\"\n", newString.c_str());
-    }
-
-    const char* const EXPECTED_OLD
-                    = "<something> begin <b>b</b><i>i<b>b</b></i><u>u</u> end </something>";
-    if (oldString != EXPECTED_OLD) {
-        fprintf(stderr, "oldString mismatch:\n");
-        fprintf(stderr, "    expected='%s'\n", EXPECTED_OLD);
-        fprintf(stderr, "      actual='%s'\n", oldString.c_str());
-        err |= 1;
-    }
-
-    const char* const EXPECTED_NEW
-                    = "<blah xml:space=\"preserve\"> begin <g ctype=\"bold\">b</g>"
-                    "<g ctype=\"italic\">i<g ctype=\"bold\">b</g></g><g ctype=\"underline\">u</g>"
-                    " end </blah>";
-    if (newString != EXPECTED_NEW) {
-        fprintf(stderr, "newString mismatch:\n");
-        fprintf(stderr, "    expected='%s'\n", EXPECTED_NEW);
-        fprintf(stderr, "      actual='%s'\n", newString.c_str());
-        err |= 1;
-    }
-
-    if (err != 0) {
-        fprintf(stderr, "create_string_node_test failed\n");
-    }
-    return err;
-}
-
-int
-XLIFFFile_test()
-{
-    bool all = true;
-    int err = 0;
-
-    if (all) err |= Parse_test();
-    if (all) err |= create_string_node_test();
-
-    return err;
-}
-
diff --git a/tools/localize/XMLHandler.cpp b/tools/localize/XMLHandler.cpp
deleted file mode 100644
index 3fab211..0000000
--- a/tools/localize/XMLHandler.cpp
+++ /dev/null
@@ -1,793 +0,0 @@
-#include "XMLHandler.h"
-
-#include <algorithm>
-#include <expat.h>
-#include <stdio.h>
-#include <string.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <errno.h>
-
-#define NS_SEPARATOR 1
-#define MORE_INDENT "  "
-
-static string
-xml_text_escape(const string& s)
-{
-    string result;
-    const size_t N = s.length();
-    for (size_t i=0; i<N; i++) {
-        char c = s[i];
-        switch (c) {
-            case '<':
-                result += "&lt;";
-                break;
-            case '>':
-                result += "&gt;";
-                break;
-            case '&':
-                result += "&amp;";
-                break;
-            default:
-                result += c;
-                break;
-        }
-    }
-    return result;
-}
-
-static string
-xml_attr_escape(const string& s)
-{
-    string result;
-    const size_t N = s.length();
-    for (size_t i=0; i<N; i++) {
-        char c = s[i];
-        switch (c) {
-            case '\"':
-                result += "&quot;";
-                break;
-            default:
-                result += c;
-                break;
-        }
-    }
-    return result;
-}
-
-XMLNamespaceMap::XMLNamespaceMap()
-{
-}
-
-XMLNamespaceMap::XMLNamespaceMap(char const*const* nspaces)
-
-{
-    while (*nspaces) {
-        m_map[nspaces[1]] = nspaces[0];
-        nspaces += 2;
-    }
-}
-
-string
-XMLNamespaceMap::Get(const string& ns) const
-{
-    if (ns == "xml") {
-        return ns;
-    }
-    map<string,string>::const_iterator it = m_map.find(ns);
-    if (it == m_map.end()) {
-        return "";
-    } else {
-        return it->second;
-    }
-}
-
-string
-XMLNamespaceMap::GetPrefix(const string& ns) const
-{
-    if (ns == "") {
-        return "";
-    }
-    map<string,string>::const_iterator it = m_map.find(ns);
-    if (it != m_map.end()) {
-        if (it->second == "") {
-            return "";
-        } else {
-            return it->second + ":";
-        }
-    } else {
-        return ":"; // invalid
-    }
-}
-
-void
-XMLNamespaceMap::AddToAttributes(vector<XMLAttribute>* attrs) const
-{
-    map<string,string>::const_iterator it;
-    for (it=m_map.begin(); it!=m_map.end(); it++) {
-        if (it->second == "xml") {
-            continue;
-        }
-        XMLAttribute attr;
-        if (it->second == "") {
-            attr.name = "xmlns";
-        } else {
-            attr.name = "xmlns:";
-            attr.name += it->second;
-        }
-        attr.value = it->first;
-        attrs->push_back(attr);
-    }
-}
-
-XMLAttribute::XMLAttribute()
-{
-}
-
-XMLAttribute::XMLAttribute(const XMLAttribute& that)
-    :ns(that.ns),
-     name(that.name),
-     value(that.value)
-{
-}
-
-XMLAttribute::XMLAttribute(string n, string na, string v)
-    :ns(n),
-     name(na),
-     value(v)
-{
-}
-
-XMLAttribute::~XMLAttribute()
-{
-}
-
-int
-XMLAttribute::Compare(const XMLAttribute& that) const
-{
-    if (ns != that.ns) {
-        return ns < that.ns ? -1 : 1;
-    }
-    if (name != that.name) {
-        return name < that.name ? -1 : 1;
-    }
-    return 0;
-}
-
-string
-XMLAttribute::Find(const vector<XMLAttribute>& list, const string& ns, const string& name,
-                    const string& def)
-{
-    const size_t N = list.size();
-    for (size_t i=0; i<N; i++) {
-        const XMLAttribute& attr = list[i];
-        if (attr.ns == ns && attr.name == name) {
-            return attr.value;
-        }
-    }
-    return def;
-}
-
-struct xml_handler_data {
-    vector<XMLHandler*> stack;
-    XML_Parser parser;
-    vector<vector<XMLAttribute>*> attributes;
-    string filename;
-};
-
-XMLNode::XMLNode()
-{
-}
-
-XMLNode::~XMLNode()
-{
-//    for_each(m_children.begin(), m_children.end(), delete_object<XMLNode>);
-}
-
-XMLNode*
-XMLNode::Clone() const
-{
-    switch (m_type) {
-        case ELEMENT: {
-            XMLNode* e = XMLNode::NewElement(m_pos, m_ns, m_name, m_attrs, m_pretty);
-            const size_t N = m_children.size();
-            for (size_t i=0; i<N; i++) {
-                e->m_children.push_back(m_children[i]->Clone());
-            }
-            return e;
-        }
-        case TEXT: {
-            return XMLNode::NewText(m_pos, m_text, m_pretty);
-        }
-        default:
-            return NULL;
-    }
-}
-
-XMLNode*
-XMLNode::NewElement(const SourcePos& pos, const string& ns, const string& name,
-                        const vector<XMLAttribute>& attrs, int pretty)
-{
-    XMLNode* node = new XMLNode();
-        node->m_type = ELEMENT;
-        node->m_pretty = pretty;
-        node->m_pos = pos;
-        node->m_ns = ns;
-        node->m_name = name;
-        node->m_attrs = attrs;
-    return node;
-}
-
-XMLNode*
-XMLNode::NewText(const SourcePos& pos, const string& text, int pretty)
-{
-    XMLNode* node = new XMLNode();
-        node->m_type = TEXT;
-        node->m_pretty = pretty;
-        node->m_pos = pos;
-        node->m_text = text;
-    return node;
-}
-
-void
-XMLNode::SetPrettyRecursive(int value)
-{
-    m_pretty = value;
-    const size_t N = m_children.size();
-    for (size_t i=0; i<N; i++) {
-        m_children[i]->SetPrettyRecursive(value);
-    }
-}
-
-string
-XMLNode::ContentsToString(const XMLNamespaceMap& nspaces) const
-{
-    return contents_to_string(nspaces, "");
-}
-
-string
-XMLNode::ToString(const XMLNamespaceMap& nspaces) const
-{
-    return to_string(nspaces, "");
-}
-
-string
-XMLNode::OpenTagToString(const XMLNamespaceMap& nspaces, int pretty) const
-{
-    return open_tag_to_string(nspaces, "", pretty);
-}
-
-string
-XMLNode::contents_to_string(const XMLNamespaceMap& nspaces, const string& indent) const
-{
-    string result;
-    const size_t N = m_children.size();
-    for (size_t i=0; i<N; i++) {
-        const XMLNode* child = m_children[i];
-        switch (child->Type()) {
-        case ELEMENT:
-            if (m_pretty == PRETTY) {
-                result += '\n';
-                result += indent;
-            }
-        case TEXT:
-            result += child->to_string(nspaces, indent);
-            break;
-        }
-    }
-    return result;
-}
-
-string
-trim_string(const string& str)
-{
-    const char* p = str.c_str();
-    while (*p && isspace(*p)) {
-        p++;
-    }
-    const char* q = str.c_str() + str.length() - 1;
-    while (q > p && isspace(*q)) {
-        q--;
-    }
-    q++;
-    return string(p, q-p);
-}
-
-string
-XMLNode::open_tag_to_string(const XMLNamespaceMap& nspaces, const string& indent, int pretty) const
-{
-    if (m_type != ELEMENT) {
-        return "";
-    }
-    string result = "<";
-    result += nspaces.GetPrefix(m_ns);
-    result += m_name;
-
-    vector<XMLAttribute> attrs = m_attrs;
-
-    sort(attrs.begin(), attrs.end());
-
-    const size_t N = attrs.size();
-    for (size_t i=0; i<N; i++) {
-        const XMLAttribute& attr = attrs[i];
-        if (i == 0 || m_pretty == EXACT || pretty == EXACT) {
-            result += ' ';
-        }
-        else {
-            result += "\n";
-            result += indent;
-            result += MORE_INDENT;
-            result += MORE_INDENT;
-        }
-        result += nspaces.GetPrefix(attr.ns);
-        result += attr.name;
-        result += "=\"";
-        result += xml_attr_escape(attr.value);
-        result += '\"';
-    }
-
-    if (m_children.size() > 0) {
-        result += '>';
-    } else {
-        result += " />";
-    }
-    return result;
-}
-
-string
-XMLNode::to_string(const XMLNamespaceMap& nspaces, const string& indent) const
-{
-    switch (m_type)
-    {
-        case TEXT: {
-            if (m_pretty == EXACT) {
-                return xml_text_escape(m_text);
-            } else {
-                return xml_text_escape(trim_string(m_text));
-            }
-        }
-        case ELEMENT: {
-            string result = open_tag_to_string(nspaces, indent, PRETTY);
-            
-            if (m_children.size() > 0) {
-                result += contents_to_string(nspaces, indent + MORE_INDENT);
-
-                if (m_pretty == PRETTY && m_children.size() > 0) {
-                    result += '\n';
-                    result += indent;
-                }
-
-                result += "</";
-                result += nspaces.GetPrefix(m_ns);
-                result += m_name;
-                result += '>';
-            }
-            return result;
-        }
-        default:
-            return "";
-    }
-}
-
-string
-XMLNode::CollapseTextContents() const
-{
-    if (m_type == TEXT) {
-        return m_text;
-    }
-    else if (m_type == ELEMENT) {
-        string result;
-
-        const size_t N=m_children.size();
-        for (size_t i=0; i<N; i++) {
-            result += m_children[i]->CollapseTextContents();
-        }
-
-        return result;
-    }
-    else {
-        return "";
-    }
-}
-
-vector<XMLNode*>
-XMLNode::GetElementsByName(const string& ns, const string& name) const
-{
-    vector<XMLNode*> result;
-    const size_t N=m_children.size();
-    for (size_t i=0; i<N; i++) {
-        XMLNode* child = m_children[i];
-        if (child->m_type == ELEMENT && child->m_ns == ns && child->m_name == name) {
-            result.push_back(child);
-        }
-    }
-    return result;
-}
-
-XMLNode*
-XMLNode::GetElementByNameAt(const string& ns, const string& name, size_t index) const
-{
-    vector<XMLNode*> result;
-    const size_t N=m_children.size();
-    for (size_t i=0; i<N; i++) {
-        XMLNode* child = m_children[i];
-        if (child->m_type == ELEMENT && child->m_ns == ns && child->m_name == name) {
-            if (index == 0) {
-                return child;
-            } else {
-                index--;
-            }
-        }
-    }
-    return NULL;
-}
-
-size_t
-XMLNode::CountElementsByName(const string& ns, const string& name) const
-{
-    size_t result = 0;
-    const size_t N=m_children.size();
-    for (size_t i=0; i<N; i++) {
-        XMLNode* child = m_children[i];
-        if (child->m_type == ELEMENT && child->m_ns == ns && child->m_name == name) {
-            result++;
-        }
-    }
-    return result;
-}
-
-string
-XMLNode::GetAttribute(const string& ns, const string& name, const string& def) const
-{
-    return XMLAttribute::Find(m_attrs, ns, name, def);
-}
-
-static void
-parse_namespace(const char* data, string* ns, string* name)
-{
-    const char* p = strchr(data, NS_SEPARATOR);
-    if (p != NULL) {
-        ns->assign(data, p-data);
-        name->assign(p+1);
-    } else {
-        ns->assign("");
-        name->assign(data);
-    }
-}
-
-static void
-convert_attrs(const char** in, vector<XMLAttribute>* out)
-{
-    while (*in) {
-        XMLAttribute attr;
-        parse_namespace(in[0], &attr.ns, &attr.name);
-        attr.value = in[1];
-        out->push_back(attr);
-        in += 2;
-    }
-}
-
-static bool
-list_contains(const vector<XMLHandler*>& stack, XMLHandler* handler)
-{
-    const size_t N = stack.size();
-    for (size_t i=0; i<N; i++) {
-        if (stack[i] == handler) {
-            return true;
-        }
-    }
-    return false;
-}
-
-static void XMLCALL
-start_element_handler(void *userData, const char *name, const char **attrs)
-{
-    xml_handler_data* data = (xml_handler_data*)userData;
-
-    XMLHandler* handler = data->stack[data->stack.size()-1];
-
-    SourcePos pos(data->filename, (int)XML_GetCurrentLineNumber(data->parser));
-    string nsString;
-    string nameString;
-    XMLHandler* next = handler;
-    vector<XMLAttribute> attributes;
-
-    parse_namespace(name, &nsString, &nameString);
-    convert_attrs(attrs, &attributes);
-
-    handler->OnStartElement(pos, nsString, nameString, attributes, &next);
-
-    if (next == NULL) {
-        next = handler;
-    }
-
-    if (next != handler) {
-        next->elementPos = pos;
-        next->elementNamespace = nsString;
-        next->elementName = nameString;
-        next->elementAttributes = attributes;
-    }
-
-    data->stack.push_back(next);
-}
-
-static void XMLCALL
-end_element_handler(void *userData, const char *name)
-{
-    xml_handler_data* data = (xml_handler_data*)userData;
-
-    XMLHandler* handler = data->stack[data->stack.size()-1];
-    data->stack.pop_back();
-
-    SourcePos pos(data->filename, (int)XML_GetCurrentLineNumber(data->parser));
-
-    if (!list_contains(data->stack, handler)) {
-        handler->OnDone(pos);
-        if (data->stack.size() > 1) {
-            // not top one
-            delete handler;
-        }
-    }
-
-    handler = data->stack[data->stack.size()-1];
-
-    string nsString;
-    string nameString;
-
-    parse_namespace(name, &nsString, &nameString);
-
-    handler->OnEndElement(pos, nsString, nameString);
-}
-
-static void XMLCALL
-text_handler(void *userData, const XML_Char *s, int len)
-{
-    xml_handler_data* data = (xml_handler_data*)userData;
-    XMLHandler* handler = data->stack[data->stack.size()-1];
-    SourcePos pos(data->filename, (int)XML_GetCurrentLineNumber(data->parser));
-    handler->OnText(pos, string(s, len));
-}
-
-static void XMLCALL
-comment_handler(void *userData, const char *comment)
-{
-    xml_handler_data* data = (xml_handler_data*)userData;
-    XMLHandler* handler = data->stack[data->stack.size()-1];
-    SourcePos pos(data->filename, (int)XML_GetCurrentLineNumber(data->parser));
-    handler->OnComment(pos, string(comment));
-}
-
-bool
-XMLHandler::ParseFile(const string& filename, XMLHandler* handler)
-{
-    char buf[16384];
-    int fd = open(filename.c_str(), O_RDONLY);
-    if (fd < 0) {
-        SourcePos(filename, -1).Error("Unable to open file for read: %s", strerror(errno));
-        return false;
-    }
-
-    XML_Parser parser = XML_ParserCreateNS(NULL, NS_SEPARATOR);
-    xml_handler_data state;
-    state.stack.push_back(handler);
-    state.parser = parser;
-    state.filename = filename;
-
-    XML_SetUserData(parser, &state);
-    XML_SetElementHandler(parser, start_element_handler, end_element_handler);
-    XML_SetCharacterDataHandler(parser, text_handler);
-    XML_SetCommentHandler(parser, comment_handler);
-
-    ssize_t len;
-    bool done;
-    do {
-        len = read(fd, buf, sizeof(buf));
-        done = len < (ssize_t)sizeof(buf);
-        if (len < 0) {
-            SourcePos(filename, -1).Error("Error reading file: %s\n", strerror(errno));
-            close(fd);
-            return false;
-        }
-        if (XML_Parse(parser, buf, len, done) == XML_STATUS_ERROR) {
-            SourcePos(filename, (int)XML_GetCurrentLineNumber(parser)).Error(
-                    "Error parsing XML: %s\n", XML_ErrorString(XML_GetErrorCode(parser)));
-            close(fd);
-            return false;
-        }
-    } while (!done);
-
-    XML_ParserFree(parser);
-
-    close(fd);
-    
-    return true;
-}
-
-bool
-XMLHandler::ParseString(const string& filename, const string& text, XMLHandler* handler)
-{
-    XML_Parser parser = XML_ParserCreateNS(NULL, NS_SEPARATOR);
-    xml_handler_data state;
-    state.stack.push_back(handler);
-    state.parser = parser;
-    state.filename = filename;
-
-    XML_SetUserData(parser, &state);
-    XML_SetElementHandler(parser, start_element_handler, end_element_handler);
-    XML_SetCharacterDataHandler(parser, text_handler);
-    XML_SetCommentHandler(parser, comment_handler);
-
-    if (XML_Parse(parser, text.c_str(), text.size(), true) == XML_STATUS_ERROR) {
-        SourcePos(filename, (int)XML_GetCurrentLineNumber(parser)).Error(
-                "Error parsing XML: %s\n", XML_ErrorString(XML_GetErrorCode(parser)));
-        return false;
-    }
-
-    XML_ParserFree(parser);
-    
-    return true;
-}
-
-XMLHandler::XMLHandler()
-{
-}
-
-XMLHandler::~XMLHandler()
-{
-}
-
-int
-XMLHandler::OnStartElement(const SourcePos& pos, const string& ns, const string& name,
-                            const vector<XMLAttribute>& attrs, XMLHandler** next)
-{
-    return 0;
-}
-
-int
-XMLHandler::OnEndElement(const SourcePos& pos, const string& ns, const string& name)
-{
-    return 0;
-}
-
-int
-XMLHandler::OnText(const SourcePos& pos, const string& text)
-{
-    return 0;
-}
-
-int
-XMLHandler::OnComment(const SourcePos& pos, const string& text)
-{
-    return 0;
-}
-
-int
-XMLHandler::OnDone(const SourcePos& pos)
-{
-    return 0;
-}
-
-TopElementHandler::TopElementHandler(const string& ns, const string& name, XMLHandler* next)
-    :m_ns(ns),
-     m_name(name),
-     m_next(next)
-{
-}
-
-int
-TopElementHandler::OnStartElement(const SourcePos& pos, const string& ns, const string& name,
-                            const vector<XMLAttribute>& attrs, XMLHandler** next)
-{
-    *next = m_next;
-    return 0;
-}
-
-int
-TopElementHandler::OnEndElement(const SourcePos& pos, const string& ns, const string& name)
-{
-    return 0;
-}
-
-int
-TopElementHandler::OnText(const SourcePos& pos, const string& text)
-{
-    return 0;
-}
-
-int
-TopElementHandler::OnDone(const SourcePos& pos)
-{
-    return 0;
-}
-
-
-NodeHandler::NodeHandler(XMLNode* root, int pretty)
-    :m_root(root),
-     m_pretty(pretty)
-{
-    if (root != NULL) {
-        m_nodes.push_back(root);
-    }
-}
-
-NodeHandler::~NodeHandler()
-{
-}
-
-int
-NodeHandler::OnStartElement(const SourcePos& pos, const string& ns, const string& name,
-                            const vector<XMLAttribute>& attrs, XMLHandler** next)
-{
-    int pretty;
-    if (XMLAttribute::Find(attrs, XMLNS_XMLNS, "space", "") == "preserve") {
-        pretty = XMLNode::EXACT;
-    } else {
-        if (m_root == NULL) {
-            pretty = m_pretty;
-        } else {
-            pretty = m_nodes[m_nodes.size()-1]->Pretty();
-        }
-    }
-    XMLNode* n = XMLNode::NewElement(pos, ns, name, attrs, pretty);
-    if (m_root == NULL) {
-        m_root = n;
-    } else {
-        m_nodes[m_nodes.size()-1]->EditChildren().push_back(n);
-    }
-    m_nodes.push_back(n);
-    return 0;
-}
-
-int
-NodeHandler::OnEndElement(const SourcePos& pos, const string& ns, const string& name)
-{
-    m_nodes.pop_back();
-    return 0;
-}
-
-int
-NodeHandler::OnText(const SourcePos& pos, const string& text)
-{
-    if (m_root == NULL) {
-        return 1;
-    }
-    XMLNode* n = XMLNode::NewText(pos, text, m_nodes[m_nodes.size()-1]->Pretty());
-    m_nodes[m_nodes.size()-1]->EditChildren().push_back(n);
-    return 0;
-}
-
-int
-NodeHandler::OnComment(const SourcePos& pos, const string& text)
-{
-    return 0;
-}
-
-int
-NodeHandler::OnDone(const SourcePos& pos)
-{
-    return 0;
-}
-
-XMLNode*
-NodeHandler::ParseFile(const string& filename, int pretty)
-{
-    NodeHandler handler(NULL, pretty);
-    if (!XMLHandler::ParseFile(filename, &handler)) {
-        fprintf(stderr, "error parsing file: %s\n", filename.c_str());
-        return NULL;
-    }
-    return handler.Root();
-}
-
-XMLNode*
-NodeHandler::ParseString(const string& filename, const string& text, int pretty)
-{
-    NodeHandler handler(NULL, pretty);
-    if (!XMLHandler::ParseString(filename, text, &handler)) {
-        fprintf(stderr, "error parsing file: %s\n", filename.c_str());
-        return NULL;
-    }
-    return handler.Root();
-}
-
-
diff --git a/tools/localize/XMLHandler.h b/tools/localize/XMLHandler.h
deleted file mode 100644
index 324385f..0000000
--- a/tools/localize/XMLHandler.h
+++ /dev/null
@@ -1,198 +0,0 @@
-#ifndef XML_H
-#define XML_H
-
-#include "SourcePos.h"
-
-#include <algorithm>
-#include <string>
-#include <vector>
-#include <map>
-
-#define XMLNS_XMLNS "http://www.w3.org/XML/1998/namespace"
-
-using namespace std;
-
-string trim_string(const string& str);
-
-struct XMLAttribute
-{
-    string ns;
-    string name;
-    string value;
-
-    XMLAttribute();
-    XMLAttribute(const XMLAttribute& that);
-    XMLAttribute(string ns, string name, string value);
-    ~XMLAttribute();
-
-    int Compare(const XMLAttribute& that) const;
-
-    inline bool operator<(const XMLAttribute& that) const { return Compare(that) < 0; }
-    inline bool operator<=(const XMLAttribute& that) const { return Compare(that) <= 0; }
-    inline bool operator==(const XMLAttribute& that) const { return Compare(that) == 0; }
-    inline bool operator!=(const XMLAttribute& that) const { return Compare(that) != 0; }
-    inline bool operator>=(const XMLAttribute& that) const { return Compare(that) >= 0; }
-    inline bool operator>(const XMLAttribute& that) const { return Compare(that) > 0; }
-
-    static string Find(const vector<XMLAttribute>& list,
-                                const string& ns, const string& name, const string& def);
-};
-
-class XMLNamespaceMap
-{
-public:
-    XMLNamespaceMap();
-    XMLNamespaceMap(char const*const* nspaces);
-    string Get(const string& ns) const;
-    string GetPrefix(const string& ns) const;
-    void AddToAttributes(vector<XMLAttribute>* attrs) const;
-private:
-    map<string,string> m_map;
-};
-
-struct XMLNode
-{
-public:
-    enum {
-        EXACT = 0,
-        PRETTY = 1
-    };
-
-    enum {
-        ELEMENT = 0,
-        TEXT = 1
-    };
-
-    static XMLNode* NewElement(const SourcePos& pos, const string& ns, const string& name,
-                        const vector<XMLAttribute>& attrs, int pretty);
-    static XMLNode* NewText(const SourcePos& pos, const string& text, int pretty);
-
-    ~XMLNode();
-
-    // a deep copy
-    XMLNode* Clone() const;
-
-    inline int Type() const                                     { return m_type; }
-    inline int Pretty() const                                   { return m_pretty; }
-    void SetPrettyRecursive(int value);
-    string ContentsToString(const XMLNamespaceMap& nspaces) const;
-    string ToString(const XMLNamespaceMap& nspaces) const;
-    string OpenTagToString(const XMLNamespaceMap& nspaces, int pretty) const;
-
-    string CollapseTextContents() const;
-
-    inline const SourcePos& Position() const                    { return m_pos; }
-
-    // element
-    inline string Namespace() const                             { return m_ns; }
-    inline string Name() const                                  { return m_name; }
-    inline void SetName(const string& ns, const string& n)      { m_ns = ns; m_name = n; }
-    inline const vector<XMLAttribute>& Attributes() const       { return m_attrs; }
-    inline vector<XMLAttribute>& EditAttributes()               { return m_attrs; }
-    inline const vector<XMLNode*>& Children() const             { return m_children; }
-    inline vector<XMLNode*>& EditChildren()                     { return m_children; }
-    vector<XMLNode*> GetElementsByName(const string& ns, const string& name) const;
-    XMLNode* GetElementByNameAt(const string& ns, const string& name, size_t index) const;
-    size_t CountElementsByName(const string& ns, const string& name) const;
-    string GetAttribute(const string& ns, const string& name, const string& def) const;
-
-    // text
-    inline string Text() const                                  { return m_text; }
-
-private:
-    XMLNode();
-    XMLNode(const XMLNode&);
-
-    string contents_to_string(const XMLNamespaceMap& nspaces, const string& indent) const;
-    string to_string(const XMLNamespaceMap& nspaces, const string& indent) const;
-    string open_tag_to_string(const XMLNamespaceMap& nspaces, const string& indent,
-            int pretty) const;
-
-    int m_type;
-    int m_pretty;
-    SourcePos m_pos;
-
-    // element
-    string m_ns;
-    string m_name;
-    vector<XMLAttribute> m_attrs;
-    vector<XMLNode*> m_children;
-
-    // text
-    string m_text;
-};
-
-class XMLHandler
-{
-public:
-    // information about the element that started us
-    SourcePos elementPos;
-    string elementNamespace;
-    string elementName;
-    vector<XMLAttribute> elementAttributes;
-
-    XMLHandler();
-    virtual ~XMLHandler();
-
-    XMLHandler* parent;
-
-    virtual int OnStartElement(const SourcePos& pos, const string& ns, const string& name,
-                                const vector<XMLAttribute>& attrs, XMLHandler** next);
-    virtual int OnEndElement(const SourcePos& pos, const string& ns, const string& name);
-    virtual int OnText(const SourcePos& pos, const string& text);
-    virtual int OnComment(const SourcePos& pos, const string& text);
-    virtual int OnDone(const SourcePos& pos);
-
-    static bool ParseFile(const string& filename, XMLHandler* handler);
-    static bool ParseString(const string& filename, const string& text, XMLHandler* handler);
-};
-
-class TopElementHandler : public XMLHandler
-{
-public:
-    TopElementHandler(const string& ns, const string& name, XMLHandler* next);
-
-    virtual int OnStartElement(const SourcePos& pos, const string& ns, const string& name,
-                                const vector<XMLAttribute>& attrs, XMLHandler** next);
-    virtual int OnEndElement(const SourcePos& pos, const string& ns, const string& name);
-    virtual int OnText(const SourcePos& pos, const string& text);
-    virtual int OnDone(const SourcePos& endPos);
-
-private:
-    string m_ns;
-    string m_name;
-    XMLHandler* m_next;
-};
-
-class NodeHandler : public XMLHandler
-{
-public:
-    // after it's done, you own everything created and added to root
-    NodeHandler(XMLNode* root, int pretty);
-    ~NodeHandler();
-
-    virtual int OnStartElement(const SourcePos& pos, const string& ns, const string& name,
-                                const vector<XMLAttribute>& attrs, XMLHandler** next);
-    virtual int OnEndElement(const SourcePos& pos, const string& ns, const string& name);
-    virtual int OnText(const SourcePos& pos, const string& text);
-    virtual int OnComment(const SourcePos& pos, const string& text);
-    virtual int OnDone(const SourcePos& endPos);
-
-    inline XMLNode* Root() const                { return m_root; }
-
-    static XMLNode* ParseFile(const string& filename, int pretty);
-    static XMLNode* ParseString(const string& filename, const string& text, int pretty);
-
-private:
-    XMLNode* m_root;
-    int m_pretty;
-    vector<XMLNode*> m_nodes;
-};
-
-template <class T>
-static void delete_object(T* obj)
-{
-    delete obj;
-}
-
-#endif // XML_H
diff --git a/tools/localize/XMLHandler_test.cpp b/tools/localize/XMLHandler_test.cpp
deleted file mode 100644
index 1c81c0c..0000000
--- a/tools/localize/XMLHandler_test.cpp
+++ /dev/null
@@ -1,133 +0,0 @@
-#include "XMLHandler.h"
-#include <stdio.h>
-#include <unistd.h>
-#include <fcntl.h>
-
-const char *const NS_MAP[] = {
-    "xml", XMLNS_XMLNS,
-    NULL, NULL
-};
-
-const XMLNamespaceMap NO_NAMESPACES(NS_MAP);
-
-char const*const EXPECTED_EXACT = 
-       "<ASDF>\n"
-        "    <a id=\"system\" old-cl=\"1\" new-cl=\"43019\">\n"
-        "        <app dir=\"apps/common\" />\n"
-        "    </a>\n"
-        "    <a id=\"samples\" old-cl=\"1\" new-cl=\"43019\">asdf\n"
-        "        <app dir=\"samples/NotePad\" />\n"
-        "        <app dir=\"samples/LunarLander\" />\n"
-        "        <something>a<b>,</b>b </something>\n"
-        "        <exact xml:space=\"preserve\">a<b>,</b>b </exact>\n"
-        "    </a>\n"
-        "</ASDF>\n";
-
-char const*const EXPECTED_PRETTY =
-        "<ASDF>\n"
-        "  <a id=\"system\"\n"
-        "      old-cl=\"1\"\n"
-        "      new-cl=\"43019\">\n"
-        "    <app dir=\"apps/common\" />\n"
-        "  </a>\n"
-        "  <a id=\"samples\"\n"
-        "      old-cl=\"1\"\n"
-        "      new-cl=\"43019\">asdf\n"
-        "    <app dir=\"samples/NotePad\" />\n"
-        "    <app dir=\"samples/LunarLander\" />\n"
-        "    <something>a\n"
-        "      <b>,\n"
-        "      </b>b \n"
-        "    </something>\n"
-        "    <exact xml:space=\"preserve\">a<b>,</b>b </exact>\n"
-        "  </a>\n"
-        "</ASDF>\n";
-
-static string
-read_file(const string& filename)
-{
-    char buf[1024];
-    int fd = open(filename.c_str(), O_RDONLY);
-    if (fd < 0) {
-        return "";
-    }
-    string result;
-    while (true) {
-        ssize_t len = read(fd, buf, sizeof(buf)-1);
-        buf[len] = '\0';
-        if (len <= 0) {
-            break;
-        }
-        result.append(buf, len);
-    }
-    close(fd);
-    return result;
-}
-
-static int
-ParseFile_EXACT_test()
-{
-    XMLNode* root = NodeHandler::ParseFile("testdata/xml.xml", XMLNode::EXACT);
-    if (root == NULL) {
-        return 1;
-    }
-    string result = root->ToString(NO_NAMESPACES);
-    delete root;
-    //printf("[[%s]]\n", result.c_str());
-    return result == EXPECTED_EXACT;
-}
-
-static int
-ParseFile_PRETTY_test()
-{
-    XMLNode* root = NodeHandler::ParseFile("testdata/xml.xml", XMLNode::PRETTY);
-    if (root == NULL) {
-        return 1;
-    }
-    string result = root->ToString(NO_NAMESPACES);
-    delete root;
-    //printf("[[%s]]\n", result.c_str());
-    return result == EXPECTED_PRETTY;
-}
-
-static int
-ParseString_EXACT_test()
-{
-    string text = read_file("testdata/xml.xml");
-    XMLNode* root = NodeHandler::ParseString("testdata/xml.xml", text, XMLNode::EXACT);
-    if (root == NULL) {
-        return 1;
-    }
-    string result = root->ToString(NO_NAMESPACES);
-    delete root;
-    //printf("[[%s]]\n", result.c_str());
-    return result == EXPECTED_EXACT;
-}
-
-static int
-ParseString_PRETTY_test()
-{
-    string text = read_file("testdata/xml.xml");
-    XMLNode* root = NodeHandler::ParseString("testdata/xml.xml", text, XMLNode::PRETTY);
-    if (root == NULL) {
-        return 1;
-    }
-    string result = root->ToString(NO_NAMESPACES);
-    delete root;
-    //printf("[[%s]]\n", result.c_str());
-    return result == EXPECTED_PRETTY;
-}
-
-int
-XMLHandler_test()
-{
-    int err = 0;
-    bool all = true;
-
-    if (all) err |= ParseFile_EXACT_test();
-    if (all) err |= ParseFile_PRETTY_test();
-    if (all) err |= ParseString_EXACT_test();
-    if (all) err |= ParseString_PRETTY_test();
-
-    return err;
-}
diff --git a/tools/localize/XMLNode.h b/tools/localize/XMLNode.h
deleted file mode 100644
index bfb9f55..0000000
--- a/tools/localize/XMLNode.h
+++ /dev/null
@@ -1,19 +0,0 @@
-#ifndef XMLNODE_H
-#define XMLNODE_H
-
-#include <string>
-
-using namespace std;
-
-struct XMLAttribute
-{
-    string ns;
-    string name;
-    string value;
-
-    static string Find(const vector<XMLAttribute>& list,
-                                const string& ns, const string& name, const string& def);
-};
-
-
-#endif // XMLNODE_H
diff --git a/tools/localize/file_utils.cpp b/tools/localize/file_utils.cpp
deleted file mode 100644
index 775ce2f..0000000
--- a/tools/localize/file_utils.cpp
+++ /dev/null
@@ -1,181 +0,0 @@
-#include <string.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include "file_utils.h"
-#include "Perforce.h"
-#include <utils/String8.h>
-#include <sys/fcntl.h>
-#include <sys/stat.h>
-#include <errno.h>
-#include <string.h>
-#include <stdlib.h>
-#include <cstdio>
-#include "log.h"
-
-using namespace android;
-using namespace std;
-
-static string
-parent_dir(const string& path)
-{
-    return string(String8(path.c_str()).getPathDir().string());
-}
-
-static int
-mkdirs(const char* last)
-{
-    String8 dest;
-    const char* s = last-1;
-    int err;
-    do {
-        s++;
-        if (s > last && (*s == '.' || *s == 0)) {
-            String8 part(last, s-last);
-            dest.appendPath(part);
-#ifdef HAVE_MS_C_RUNTIME
-            err = _mkdir(dest.string());
-#else                    
-            err = mkdir(dest.string(), S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP);
-#endif                    
-            if (err != 0) {
-                return err;
-            }
-            last = s+1;
-        }
-    } while (*s);
-    return 0;
-}
-
-string
-translated_file_name(const string& file, const string& locale)
-{
-    const char* str = file.c_str();
-    const char* p = str + file.length();
-    const char* rest = NULL;
-    const char* values = p;
-
-    while (p > str) {
-        p--;
-        if (*p == '/') {
-            rest = values;
-            values = p;
-            if (0 == strncmp("values", values+1, rest-values-1)) {
-                break;
-            }
-        }
-    }
-    values++;
-
-    string result(str, values-str);
-    result.append(values, rest-values);
-
-    string language, region;
-    if (locale == "") {
-        language = "";
-        region = "";
-    }
-    else if (!split_locale(locale, &language, &region)) {
-        return "";
-    }
-
-    if (language != "") {
-        result += '-';
-        result += language;
-    }
-    if (region != "") {
-        result += "-r";
-        result += region;
-    }
-
-    result += rest;
-
-    return result;
-}
-
-ValuesFile*
-get_values_file(const string& filename, const Configuration& configuration,
-                int version, const string& versionString, bool printOnFailure)
-{
-    int err;
-    string text;
-
-    log_printf("get_values_file filename=%s\n", filename.c_str());
-    err = Perforce::GetFile(filename, versionString, &text, printOnFailure);
-    if (err != 0 || text == "") {
-        return NULL;
-    }
-
-    ValuesFile* result = ValuesFile::ParseString(filename, text, configuration, version,
-                                                    versionString);
-    if (result == NULL) {
-        fprintf(stderr, "unable to parse file: %s\n", filename.c_str());
-        exit(1);
-    }
-    return result;
-}
-
-ValuesFile*
-get_local_values_file(const string& filename, const Configuration& configuration,
-                int version, const string& versionString, bool printOnFailure)
-{
-    int err;
-    string text;
-    char buf[2049];
-    int fd;
-    ssize_t amt;
-    
-    fd = open(filename.c_str(), O_RDONLY);
-    if (fd == -1) {
-        fprintf(stderr, "unable to open file: %s\n", filename.c_str());
-        return NULL;
-    }
-
-    while ((amt = read(fd, buf, sizeof(buf)-1)) > 0) {
-        text.append(buf, amt);
-    }
-
-    close(fd);
-    
-    if (text == "") {
-        return NULL;
-    }
-        
-    ValuesFile* result = ValuesFile::ParseString(filename, text, configuration, version,
-                                                    versionString);
-    if (result == NULL) {
-        fprintf(stderr, "unable to parse file: %s\n", filename.c_str());
-        exit(1);
-    }
-    return result;
-}
-
-void
-print_file_status(size_t j, size_t J, const string& message)
-{
-    printf("\r%s file %zd of %zd...", message.c_str(), j, J);
-    fflush(stdout);
-}
-
-int
-write_to_file(const string& filename, const string& text)
-{
-    mkdirs(parent_dir(filename).c_str());
-    int fd = open(filename.c_str(), O_RDWR | O_CREAT | O_TRUNC, 0666);
-    if (fd < 0) {
-        fprintf(stderr, "unable to open file for write (%s): %s\n", strerror(errno),
-                filename.c_str());
-        return -1;
-    }
-
-    ssize_t amt = write(fd, text.c_str(), text.length());
-
-    close(fd);
-
-    if (amt < 0) {
-        return amt;
-    }
-    return amt == (ssize_t)text.length() ? 0 : -1;
-}
-
-
diff --git a/tools/localize/file_utils.h b/tools/localize/file_utils.h
deleted file mode 100644
index 7706587..0000000
--- a/tools/localize/file_utils.h
+++ /dev/null
@@ -1,22 +0,0 @@
-#ifndef FILE_UTILS_H
-#define FILE_UTILS_H
-
-#include "ValuesFile.h"
-#include "Configuration.h"
-#include <string>
-#include <cstdio>
-
-using namespace std;
-
-string translated_file_name(const string& file, const string& locale);
-
-ValuesFile* get_values_file(const string& filename, const Configuration& configuration,
-                int version, const string& versionString, bool printOnFailure);
-ValuesFile* get_local_values_file(const string& filename, const Configuration& configuration,
-                int version, const string& versionString, bool printOnFailure);
-
-void print_file_status(size_t j, size_t J, const string& message = "Reading");
-int write_to_file(const string& filename, const string& text);
-
-
-#endif // FILE_UTILS_H
diff --git a/tools/localize/localize.cpp b/tools/localize/localize.cpp
deleted file mode 100644
index 68c03b6..0000000
--- a/tools/localize/localize.cpp
+++ /dev/null
@@ -1,768 +0,0 @@
-#include "SourcePos.h"
-#include "ValuesFile.h"
-#include "XLIFFFile.h"
-#include "Perforce.h"
-#include "merge_res_and_xliff.h"
-#include "localize.h"
-#include "file_utils.h"
-#include "res_check.h"
-#include "xmb.h"
-
-#include <host/pseudolocalize.h>
-
-#include <stdlib.h>
-#include <stdarg.h>
-#include <sstream>
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-
-using namespace std;
-
-FILE* g_logFile = NULL;
-
-int test();
-
-int
-read_settings(const string& filename, map<string,Settings>* result, const string& rootDir)
-{
-    XMLNode* root = NodeHandler::ParseFile(filename, XMLNode::PRETTY);
-    if (root == NULL) {
-        SourcePos(filename, -1).Error("Error reading file.");
-        return 1;
-    }
-
-    // <configuration>
-    vector<XMLNode*> configNodes = root->GetElementsByName("", "configuration");
-    const size_t I = configNodes.size();
-    for (size_t i=0; i<I; i++) {
-        const XMLNode* configNode = configNodes[i];
-
-        Settings settings;
-        settings.id = configNode->GetAttribute("", "id", "");
-        if (settings.id == "") {
-            configNode->Position().Error("<configuration> needs an id attribute.");
-            delete root;
-            return 1;
-        }
-
-        settings.oldVersion = configNode->GetAttribute("", "old-cl", "");
-
-        settings.currentVersion = configNode->GetAttribute("", "new-cl", "");
-        if (settings.currentVersion == "") {
-            configNode->Position().Error("<configuration> needs a new-cl attribute.");
-            delete root;
-            return 1;
-        }
-
-        // <app>
-        vector<XMLNode*> appNodes = configNode->GetElementsByName("", "app");
-
-        const size_t J = appNodes.size();
-        for (size_t j=0; j<J; j++) {
-            const XMLNode* appNode = appNodes[j];
-
-            string dir = appNode->GetAttribute("", "dir", "");
-            if (dir == "") {
-                appNode->Position().Error("<app> needs a dir attribute.");
-                delete root;
-                return 1;
-            }
-
-            settings.apps.push_back(dir);
-        }
-
-        // <reject>
-        vector<XMLNode*> rejectNodes = configNode->GetElementsByName("", "reject");
-
-        const size_t K = rejectNodes.size();
-        for (size_t k=0; k<K; k++) {
-            const XMLNode* rejectNode = rejectNodes[k];
-
-            Reject reject;
-
-            reject.file = rejectNode->GetAttribute("", "file", "");
-            if (reject.file == "") {
-                rejectNode->Position().Error("<reject> needs a file attribute.");
-                delete root;
-                return 1;
-            }
-            string f =  reject.file;
-            reject.file = rootDir;
-            reject.file += '/';
-            reject.file += f;
-            
-            reject.name = rejectNode->GetAttribute("", "name", "");
-            if (reject.name == "") {
-                rejectNode->Position().Error("<reject> needs a name attribute.");
-                delete root;
-                return 1;
-            }
-
-            reject.comment = trim_string(rejectNode->CollapseTextContents());
-
-            settings.reject.push_back(reject);
-        }
-
-        (*result)[settings.id] = settings;
-    }
-
-    delete root;
-    return 0;
-}
-
-
-static void
-ValuesFile_to_XLIFFFile(const ValuesFile* values, XLIFFFile* xliff, const string& englishFilename)
-{
-    const set<StringResource>& strings = values->GetStrings();
-    for (set<StringResource>::const_iterator it=strings.begin(); it!=strings.end(); it++) {
-        StringResource res = *it;
-        res.file = englishFilename;
-        xliff->AddStringResource(res);
-    }
-}
-
-static bool
-contains_reject(const Settings& settings, const string& file, const TransUnit& tu)
-{
-    const string name = tu.id;
-    const vector<Reject>& reject = settings.reject;
-    const size_t I = reject.size();
-    for (size_t i=0; i<I; i++) {
-        const Reject& r = reject[i];
-        if (r.file == file && r.name == name) {
-            return true;
-        }
-    }
-    return false;
-}
-
-/**
- * If it's been rejected, then we keep whatever info we have.
- *
- * Implements this truth table:
- *
- *    S   AT   AS     Keep
- *   -----------------------
- *    0    0    0      0    (this case can't happen)
- *    0    0    1      0    (it was there, never translated, and removed)
- *    0    1    0      0    (somehow it got translated, but it was removed)
- *    0    1    1      0    (it was removed after having been translated)
- *
- *    1    0    0      1    (it was just added)
- *    1    0    1      1    (it was added, has been changed, but it never got translated)
- *    1    1    0      1    (somehow it got translated, but we don't know based on what)
- *    1    1    1     0/1   (it's in both.  0 if S=AS b/c there's no need to retranslate if they're
- *                           the same.  1 if S!=AS because S changed, so it should be retranslated)
- *
- * The first four are cases where, whatever happened in the past, the string isn't there
- * now, so it shouldn't be in the XLIFF file.
- *
- * For cases 4 and 5, the string has never been translated, so get it translated.
- *
- * For case 6, it's unclear where the translated version came from, so we're conservative
- * and send it back for them to have another shot at.
- *
- * For case 7, we have some data.  We have two choices.  We could rely on the translator's
- * translation memory or tools to notice that the strings haven't changed, and populate the
- * <target> field themselves.  Or if the string hasn't changed since last time, we can just
- * not even tell them about it.  As the project nears the end, it will be convenient to see
- * the xliff files reducing in size, so we pick the latter.  Obviously, if the string has
- * changed, then we need to get it retranslated.
- */
-bool
-keep_this_trans_unit(const string& file, const TransUnit& unit, void* cookie)
-{
-    const Settings* settings = reinterpret_cast<const Settings*>(cookie);
-
-    if (contains_reject(*settings, file, unit)) {
-        return true;
-    }
-
-    if (unit.source.id == "") {
-        return false;
-    }
-    if (unit.altTarget.id == "" || unit.altSource.id == "") {
-        return true;
-    }
-    return unit.source.value->ContentsToString(XLIFF_NAMESPACES)
-            != unit.altSource.value->ContentsToString(XLIFF_NAMESPACES);
-}
-
-int
-validate_config(const string& settingsFile, const map<string,Settings>& settings,
-        const string& config)
-{
-    if (settings.find(config) == settings.end()) {
-        SourcePos(settingsFile, -1).Error("settings file does not contain setting: %s\n",
-                config.c_str());
-        return 1;
-    }
-    return 0;
-}
-
-int
-validate_configs(const string& settingsFile, const map<string,Settings>& settings,
-        const vector<string>& configs)
-{
-    int err = 0;
-    for (size_t i=0; i<configs.size(); i++) {
-        string config = configs[i];
-        err |= validate_config(settingsFile, settings, config);
-    }
-    return err;
-}
-
-int
-select_files(vector<string> *resFiles, const string& config,
-        const map<string,Settings>& settings, const string& rootDir)
-{
-    int err;
-    vector<vector<string> > allResFiles;
-    vector<string> configs;
-    configs.push_back(config);
-    err = select_files(&allResFiles, configs, settings, rootDir);
-    if (err == 0) {
-        *resFiles = allResFiles[0];
-    }
-    return err;
-}
-
-int
-select_files(vector<vector<string> > *allResFiles, const vector<string>& configs,
-        const map<string,Settings>& settings, const string& rootDir)
-{
-    int err;
-    printf("Selecting files...");
-    fflush(stdout);
-
-    for (size_t i=0; i<configs.size(); i++) {
-        const string& config = configs[i];
-        const Settings& setting = settings.find(config)->second;
-
-        vector<string> resFiles;
-        err = Perforce::GetResourceFileNames(setting.currentVersion, rootDir,
-                                                setting.apps, &resFiles, true);
-        if (err != 0) {
-            fprintf(stderr, "error with perforce.  bailing\n");
-            return err;
-        }
-
-        allResFiles->push_back(resFiles);
-    }
-    return 0;
-}
-
-static int
-do_export(const string& settingsFile, const string& rootDir, const string& outDir,
-            const string& targetLocale, const vector<string>& configs)
-{
-    bool success = true;
-    int err;
-
-    if (false) {
-        printf("settingsFile=%s\n", settingsFile.c_str());
-        printf("rootDir=%s\n", rootDir.c_str());
-        printf("outDir=%s\n", outDir.c_str());
-        for (size_t i=0; i<configs.size(); i++) {
-            printf("config[%zd]=%s\n", i, configs[i].c_str());
-        }
-    }
-
-    map<string,Settings> settings;
-    err = read_settings(settingsFile, &settings, rootDir);
-    if (err != 0) {
-        return err;
-    }
-
-    err = validate_configs(settingsFile, settings, configs);
-    if (err != 0) {
-        return err;
-    }
-
-    vector<vector<string> > allResFiles;
-    err = select_files(&allResFiles, configs, settings, rootDir);
-    if (err != 0) {
-        return err;
-    }
-
-    size_t totalFileCount = 0;
-    for (size_t i=0; i<allResFiles.size(); i++) {
-        totalFileCount += allResFiles[i].size();
-    }
-    totalFileCount *= 3; // we try all 3 versions of the file
-
-    size_t fileProgress = 0;
-    vector<Stats> stats;
-    vector<pair<string,XLIFFFile*> > xliffs;
-
-    for (size_t i=0; i<configs.size(); i++) {
-        const string& config = configs[i];
-        const Settings& setting = settings[config];
-
-        if (false) {
-            fprintf(stderr, "Configuration: %s (%zd of %zd)\n", config.c_str(), i+1,
-                    configs.size());
-            fprintf(stderr, "  Old CL:     %s\n", setting.oldVersion.c_str());
-            fprintf(stderr, "  Current CL: %s\n", setting.currentVersion.c_str());
-        }
-
-        Configuration english;
-            english.locale = "en_US";
-        Configuration translated;
-            translated.locale = targetLocale;
-        XLIFFFile* xliff = XLIFFFile::Create(english, translated, setting.currentVersion);
-
-        const vector<string>& resFiles = allResFiles[i];
-        const size_t J = resFiles.size();
-        for (size_t j=0; j<J; j++) {
-            string resFile = resFiles[j];
-
-            // parse the files into a ValuesFile
-            // pull out the strings and add them to the XLIFFFile
-            
-            // current file
-            print_file_status(++fileProgress, totalFileCount);
-            ValuesFile* currentFile = get_values_file(resFile, english, CURRENT_VERSION,
-                                                        setting.currentVersion, true);
-            if (currentFile != NULL) {
-                ValuesFile_to_XLIFFFile(currentFile, xliff, resFile);
-                //printf("currentFile=[%s]\n", currentFile->ToString().c_str());
-            } else {
-                fprintf(stderr, "error reading file %s@%s\n", resFile.c_str(),
-                            setting.currentVersion.c_str());
-                success = false;
-            }
-
-            // old file
-            print_file_status(++fileProgress, totalFileCount);
-            ValuesFile* oldFile = get_values_file(resFile, english, OLD_VERSION,
-                                                        setting.oldVersion, false);
-            if (oldFile != NULL) {
-                ValuesFile_to_XLIFFFile(oldFile, xliff, resFile);
-                //printf("oldFile=[%s]\n", oldFile->ToString().c_str());
-            }
-
-            // translated version
-            // (get the head of the tree for the most recent translation, but it's considered
-            // the old one because the "current" one hasn't been made yet, and this goes into
-            // the <alt-trans> tag if necessary
-            print_file_status(++fileProgress, totalFileCount);
-            string transFilename = translated_file_name(resFile, targetLocale);
-            ValuesFile* transFile = get_values_file(transFilename, translated, OLD_VERSION,
-                                                        setting.currentVersion, false);
-            if (transFile != NULL) {
-                ValuesFile_to_XLIFFFile(transFile, xliff, resFile);
-            }
-
-            delete currentFile;
-            delete oldFile;
-            delete transFile;
-        }
-
-        Stats beforeFilterStats = xliff->GetStats(config);
-
-        // run through the XLIFFFile and strip out TransUnits that have identical
-        // old and current source values and are not in the reject list, or just
-        // old values and no source values
-        xliff->Filter(keep_this_trans_unit, (void*)&setting);
-
-        Stats afterFilterStats = xliff->GetStats(config);
-        afterFilterStats.totalStrings = beforeFilterStats.totalStrings;
-
-        // add the reject comments
-        for (vector<Reject>::const_iterator reject = setting.reject.begin();
-                reject != setting.reject.end(); reject++) {
-            TransUnit* tu = xliff->EditTransUnit(reject->file, reject->name);
-            tu->rejectComment = reject->comment;
-        }
-
-        // config-locale-current_cl.xliff
-        stringstream filename;
-        if (outDir != "") {
-            filename << outDir << '/';
-        }
-        filename << config << '-' << targetLocale << '-' << setting.currentVersion << ".xliff";
-        xliffs.push_back(pair<string,XLIFFFile*>(filename.str(), xliff));
-
-        stats.push_back(afterFilterStats);
-    }
-
-    // today is a good day to die
-    if (!success || SourcePos::HasErrors()) {
-        return 1;
-    }
-
-    // write the XLIFF files
-    printf("\nWriting %zd file%s...\n", xliffs.size(), xliffs.size() == 1 ? "" : "s");
-    for (vector<pair<string,XLIFFFile*> >::iterator it = xliffs.begin(); it != xliffs.end(); it++) {
-        const string& filename = it->first;
-        XLIFFFile* xliff = it->second;
-        string text = xliff->ToString();
-        write_to_file(filename, text);
-    }
-
-    // the stats
-    printf("\n"
-           "                                  to          without     total\n"
-           " config               files       translate   comments    strings\n"
-           "-----------------------------------------------------------------------\n");
-    Stats totals;
-        totals.config = "total";
-        totals.files = 0;
-        totals.toBeTranslated = 0;
-        totals.noComments = 0;
-        totals.totalStrings = 0;
-    for (vector<Stats>::iterator it=stats.begin(); it!=stats.end(); it++) {
-        string cfg = it->config;
-        if (cfg.length() > 20) {
-            cfg.resize(20);
-        }
-        printf(" %-20s  %-9zd   %-9zd   %-9zd   %-19zd\n", cfg.c_str(), it->files,
-                it->toBeTranslated, it->noComments, it->totalStrings);
-        totals.files += it->files;
-        totals.toBeTranslated += it->toBeTranslated;
-        totals.noComments += it->noComments;
-        totals.totalStrings += it->totalStrings;
-    }
-    if (stats.size() > 1) {
-        printf("-----------------------------------------------------------------------\n"
-               " %-20s  %-9zd   %-9zd   %-9zd   %-19zd\n", totals.config.c_str(), totals.files,
-                    totals.toBeTranslated, totals.noComments, totals.totalStrings);
-    }
-    printf("\n");
-    return 0;
-}
-
-struct PseudolocalizeSettings {
-    XLIFFFile* xliff;
-    bool expand;
-};
-
-
-string
-pseudolocalize_string(const string& source, const PseudolocalizeSettings* settings)
-{
-    return pseudolocalize_string(source);
-}
-
-static XMLNode*
-pseudolocalize_xml_node(const XMLNode* source, const PseudolocalizeSettings* settings)
-{
-    if (source->Type() == XMLNode::TEXT) {
-        return XMLNode::NewText(source->Position(), pseudolocalize_string(source->Text(), settings),
-                                source->Pretty());
-    } else {
-        XMLNode* target;
-        if (source->Namespace() == XLIFF_XMLNS && source->Name() == "g") {
-            // XXX don't translate these
-            target = XMLNode::NewElement(source->Position(), source->Namespace(),
-                                    source->Name(), source->Attributes(), source->Pretty());
-        } else {
-            target = XMLNode::NewElement(source->Position(), source->Namespace(),
-                                    source->Name(), source->Attributes(), source->Pretty());
-        }
-
-        const vector<XMLNode*>& children = source->Children();
-        const size_t I = children.size();
-        for (size_t i=0; i<I; i++) {
-            target->EditChildren().push_back(pseudolocalize_xml_node(children[i], settings));
-        }
-
-        return target;
-    }
-}
-
-void
-pseudolocalize_trans_unit(const string&file, TransUnit* unit, void* cookie)
-{
-    const PseudolocalizeSettings* settings = (PseudolocalizeSettings*)cookie;
-
-    const StringResource& source = unit->source;
-    StringResource* target = &unit->target;
-    *target = source;
-
-    target->config = settings->xliff->TargetConfig();
-
-    delete target->value;
-    target->value = pseudolocalize_xml_node(source.value, settings);
-}
-
-int
-pseudolocalize_xliff(XLIFFFile* xliff, bool expand)
-{
-    PseudolocalizeSettings settings;
-
-    settings.xliff = xliff;
-    settings.expand = expand;
-    xliff->Map(pseudolocalize_trans_unit, &settings);
-    return 0;
-}
-
-static int
-do_pseudo(const string& infile, const string& outfile, bool expand)
-{
-    int err;
-
-    XLIFFFile* xliff = XLIFFFile::Parse(infile);
-    if (xliff == NULL) {
-        return 1;
-    }
-
-    pseudolocalize_xliff(xliff, expand);
-
-    err = write_to_file(outfile, xliff->ToString());
-
-    delete xliff;
-
-    return err;
-}
-
-void
-log_printf(const char *fmt, ...)
-{
-    int ret;
-    va_list ap;
-
-    if (g_logFile != NULL) {
-        va_start(ap, fmt);
-        ret = vfprintf(g_logFile, fmt, ap);
-        va_end(ap);
-        fflush(g_logFile);
-    }
-}
-
-void
-close_log_file()
-{
-    if (g_logFile != NULL) {
-        fclose(g_logFile);
-    }
-}
-
-void
-open_log_file(const char* file)
-{
-    g_logFile = fopen(file, "w");
-    printf("log file: %s -- %p\n", file, g_logFile);
-    atexit(close_log_file);
-}
-
-static int
-usage()
-{
-    fprintf(stderr,
-            "usage: localize export OPTIONS CONFIGS...\n"
-            "   REQUIRED OPTIONS\n"
-            "     --settings SETTINGS   The settings file to use.  See CONFIGS below.\n"
-            "     --root TREE_ROOT      The location in Perforce of the files.  e.g. //device\n"
-            "     --target LOCALE       The target locale.  See LOCALES below.\n"
-            "\n"
-            "   OPTIONAL OPTIONS\n"
-            "      --out DIR            Directory to put the output files.  Defaults to the\n"
-            "                           current directory if not supplied.  Files are\n"
-            "                           named as follows:\n"
-            "                               CONFIG-LOCALE-CURRENT_CL.xliff\n"
-            "\n"
-            "\n"
-            "usage: localize import XLIFF_FILE...\n"
-            "\n"
-            "Import a translated XLIFF file back into the tree.\n"
-            "\n"
-            "\n"
-            "usage: localize xlb XMB_FILE VALUES_FILES...\n"
-            "\n"
-            "Read resource files from the tree file and write the corresponding XLB file\n"
-            "\n"
-            "Supply all of the android resource files (values files) to export after that.\n"
-            "\n"
-            "\n"
-            "\n"
-            "CONFIGS\n"
-            "\n"
-            "LOCALES\n"
-            "Locales are specified in the form en_US  They will be processed correctly\n"
-            "to locate the resouce files in the tree.\n"
-            "\n"
-            "\n"
-            "usage: localize pseudo OPTIONS INFILE [OUTFILE]\n"
-            "   OPTIONAL OPTIONS\n"
-            "     --big                 Pad strings so they get longer.\n"
-            "\n"
-            "Read INFILE, an XLIFF file, and output a pseudotranslated version of that file.  If\n"
-            "OUTFILE is specified, the results are written there; otherwise, the results are\n"
-            "written back to INFILE.\n"
-            "\n"
-            "\n"
-            "usage: localize rescheck FILES...\n"
-            "\n"
-            "Reads the base strings and prints warnings about bad resources from the given files.\n"
-            "\n");
-    return 1;
-}
-
-int
-main(int argc, const char** argv)
-{
-    //open_log_file("log.txt");
-    //g_logFile = stdout;
-
-    if (argc == 2 && 0 == strcmp(argv[1], "--test")) {
-        return test();
-    }
-
-    if (argc < 2) {
-        return usage();
-    }
-
-    int index = 1;
-    
-    if (0 == strcmp("export", argv[index])) {
-        string settingsFile;
-        string rootDir;
-        string outDir;
-        string baseLocale = "en";
-        string targetLocale;
-        string language, region;
-        vector<string> configs;
-
-        index++;
-        while (index < argc) {
-            if (0 == strcmp("--settings", argv[index])) {
-                settingsFile = argv[index+1];
-                index += 2;
-            }
-            else if (0 == strcmp("--root", argv[index])) {
-                rootDir = argv[index+1];
-                index += 2;
-            }
-            else if (0 == strcmp("--out", argv[index])) {
-                outDir = argv[index+1];
-                index += 2;
-            }
-            else if (0 == strcmp("--target", argv[index])) {
-                targetLocale = argv[index+1];
-                index += 2;
-            }
-            else if (argv[index][0] == '-') {
-                fprintf(stderr, "unknown argument %s\n", argv[index]);
-                return usage();
-            }
-            else {
-                break;
-            }
-        }
-        for (; index<argc; index++) {
-            configs.push_back(argv[index]);
-        }
-
-        if (settingsFile == "" || rootDir == "" || configs.size() == 0 || targetLocale == "") {
-            return usage();
-        }
-        if (!split_locale(targetLocale, &language, &region)) {
-            fprintf(stderr, "illegal --target locale: '%s'\n", targetLocale.c_str());
-            return usage();
-        }
-
-
-        return do_export(settingsFile, rootDir, outDir, targetLocale, configs);
-    }
-    else if (0 == strcmp("import", argv[index])) {
-        vector<string> xliffFilenames;
-
-        index++;
-        for (; index<argc; index++) {
-            xliffFilenames.push_back(argv[index]);
-        }
-
-        return do_merge(xliffFilenames);
-    }
-    else if (0 == strcmp("xlb", argv[index])) {
-        string outfile;
-        vector<string> resFiles;
-
-        index++;
-        if (argc < index+1) {
-            return usage();
-        }
-
-        outfile = argv[index];
-
-        index++;
-        for (; index<argc; index++) {
-            resFiles.push_back(argv[index]);
-        }
-
-        return do_xlb_export(outfile, resFiles);
-    }
-    else if (0 == strcmp("pseudo", argv[index])) {
-        string infile;
-        string outfile;
-        bool big = false;
-
-        index++;
-        while (index < argc) {
-            if (0 == strcmp("--big", argv[index])) {
-                big = true;
-                index += 1;
-            }
-            else if (argv[index][0] == '-') {
-                fprintf(stderr, "unknown argument %s\n", argv[index]);
-                return usage();
-            }
-            else {
-                break;
-            }
-        }
-
-        if (index == argc-1) {
-            infile = argv[index];
-            outfile = argv[index];
-        }
-        else if (index == argc-2) {
-            infile = argv[index];
-            outfile = argv[index+1];
-        }
-        else {
-            fprintf(stderr, "unknown argument %s\n", argv[index]);
-            return usage();
-        }
-
-        return do_pseudo(infile, outfile, big);
-    }
-    else if (0 == strcmp("rescheck", argv[index])) {
-        vector<string> files;
-
-        index++;
-        while (index < argc) {
-            if (argv[index][0] == '-') {
-                fprintf(stderr, "unknown argument %s\n", argv[index]);
-                return usage();
-            }
-            else {
-                break;
-            }
-        }
-        for (; index<argc; index++) {
-            files.push_back(argv[index]);
-        }
-
-        if (files.size() == 0) {
-            return usage();
-        }
-
-        return do_rescheck(files);
-    }
-    else {
-        return usage();
-    }
-
-    if (SourcePos::HasErrors()) {
-        SourcePos::PrintErrors(stderr);
-        return 1;
-    }
-
-    return 0;
-}
-
diff --git a/tools/localize/localize.h b/tools/localize/localize.h
deleted file mode 100644
index 615d14e..0000000
--- a/tools/localize/localize.h
+++ /dev/null
@@ -1,40 +0,0 @@
-#ifndef LOCALIZE_H
-#define LOCALIZE_H
-
-#include "XLIFFFile.h"
-
-#include <map>
-#include <string>
-
-using namespace std;
-
-struct Reject
-{
-    string file;
-    string name;
-    string comment;
-};
-
-struct Settings
-{
-    string id;
-    string oldVersion;
-    string currentVersion;
-    vector<string> apps;
-    vector<Reject> reject;
-};
-
-int read_settings(const string& filename, map<string,Settings>* result, const string& rootDir);
-string translated_file_name(const string& file, const string& locale);
-bool keep_this_trans_unit(const string& file, const TransUnit& unit, void* cookie);
-int validate_config(const string& settingsFile, const map<string,Settings>& settings,
-        const string& configs);
-int validate_configs(const string& settingsFile, const map<string,Settings>& settings,
-        const vector<string>& configs);
-int select_files(vector<string> *resFiles, const string& config,
-        const map<string,Settings>& settings, const string& rootDir);
-int select_files(vector<vector<string> > *allResFiles, const vector<string>& configs,
-        const map<string,Settings>& settings, const string& rootDir);
-
-
-#endif // LOCALIZE_H
diff --git a/tools/localize/localize_test.cpp b/tools/localize/localize_test.cpp
deleted file mode 100644
index 1d0ac9a..0000000
--- a/tools/localize/localize_test.cpp
+++ /dev/null
@@ -1,221 +0,0 @@
-#include <cstdio>
-#include "XLIFFFile.h"
-#include "ValuesFile.h"
-#include "localize.h"
-#include <stdio.h>
-
-int pseudolocalize_xliff(XLIFFFile* xliff, bool expand);
-
-static int
-test_filename(const string& file, const string& locale, const string& expected)
-{
-    string result = translated_file_name(file, locale);
-    if (result != expected) {
-        fprintf(stderr, "translated_file_name test failed\n");
-        fprintf(stderr, "  locale='%s'\n", locale.c_str());
-        fprintf(stderr, "  expected='%s'\n", expected.c_str());
-        fprintf(stderr, "    result='%s'\n", result.c_str());
-        return 1;
-    } else {
-        if (false) {
-            fprintf(stderr, "translated_file_name test passed\n");
-            fprintf(stderr, "  locale='%s'\n", locale.c_str());
-            fprintf(stderr, "  expected='%s'\n", expected.c_str());
-            fprintf(stderr, "    result='%s'\n", result.c_str());
-        }
-        return 0;
-    }
-}
-
-static int
-translated_file_name_test()
-{
-    bool all = true;
-    int err = 0;
-
-    if (all) err |= test_filename("//device/samples/NotePad/res/values/strings.xml", "zz_ZZ",
-                                  "//device/samples/NotePad/res/values-zz-rZZ/strings.xml");
-
-    if (all) err |= test_filename("//device/samples/NotePad/res/values/strings.xml", "zz",
-                                  "//device/samples/NotePad/res/values-zz/strings.xml");
-
-    if (all) err |= test_filename("//device/samples/NotePad/res/values/strings.xml", "",
-                                  "//device/samples/NotePad/res/values/strings.xml");
-
-    return err;
-}
-
-bool
-return_false(const string&, const TransUnit& unit, void* cookie)
-{
-    return false;
-}
-
-static int
-delete_trans_units()
-{
-    XLIFFFile* xliff = XLIFFFile::Parse("testdata/strip_xliff.xliff");
-    if (xliff == NULL) {
-        printf("couldn't read file\n");
-        return 1;
-    }
-    if (false) {
-        printf("XLIFF was [[%s]]\n", xliff->ToString().c_str());
-    }
-
-    xliff->Filter(return_false, NULL);
-
-    if (false) {
-        printf("XLIFF is [[%s]]\n", xliff->ToString().c_str());
-
-        set<StringResource> const& strings = xliff->GetStringResources();
-        printf("strings.size=%zd\n", strings.size());
-        for (set<StringResource>::iterator it=strings.begin(); it!=strings.end(); it++) {
-            const StringResource& str = *it;
-            printf("STRING!!! id=%s value='%s' pos=%s file=%s version=%d(%s)\n", str.id.c_str(),
-                    str.value->ContentsToString(ANDROID_NAMESPACES).c_str(),
-                    str.pos.ToString().c_str(), str.file.c_str(), str.version,
-                    str.versionString.c_str());
-        }
-    }
- 
-    return 0;
-}
-
-static int
-filter_trans_units()
-{
-    XLIFFFile* xliff = XLIFFFile::Parse("testdata/strip_xliff.xliff");
-    if (xliff == NULL) {
-        printf("couldn't read file\n");
-        return 1;
-    }
-
-    if (false) {
-        printf("XLIFF was [[%s]]\n", xliff->ToString().c_str());
-    }
-
-    Settings setting;
-    xliff->Filter(keep_this_trans_unit, &setting);
-
-    if (false) {
-        printf("XLIFF is [[%s]]\n", xliff->ToString().c_str());
-
-        set<StringResource> const& strings = xliff->GetStringResources();
-        printf("strings.size=%zd\n", strings.size());
-        for (set<StringResource>::iterator it=strings.begin(); it!=strings.end(); it++) {
-            const StringResource& str = *it;
-            printf("STRING!!! id=%s value='%s' pos=%s file=%s version=%d(%s)\n", str.id.c_str(),
-                    str.value->ContentsToString(ANDROID_NAMESPACES).c_str(),
-                    str.pos.ToString().c_str(), str.file.c_str(), str.version,
-                    str.versionString.c_str());
-        }
-    }
- 
-    return 0;
-}
-
-static int
-settings_test()
-{
-    int err;
-    map<string,Settings> settings;
-    map<string,Settings>::iterator it;
-
-    err = read_settings("testdata/config.xml", &settings, "//asdf");
-    if (err != 0) {
-        return err;
-    }
-
-    if (false) {
-        for (it=settings.begin(); it!=settings.end(); it++) {
-            const Settings& setting = it->second;
-            printf("CONFIG:\n");
-            printf("              id='%s'\n", setting.id.c_str());
-            printf("      oldVersion='%s'\n", setting.oldVersion.c_str());
-            printf("  currentVersion='%s'\n", setting.currentVersion.c_str());
-            int i=0;
-            for (vector<string>::const_iterator app=setting.apps.begin();
-                    app!=setting.apps.end(); app++) {
-                printf("        apps[%02d]='%s'\n", i, app->c_str());
-                i++;
-            }
-            i=0;
-            for (vector<Reject>::const_iterator reject=setting.reject.begin();
-                    reject!=setting.reject.end(); reject++) {
-                i++;
-                printf("      reject[%02d]=('%s','%s','%s')\n", i, reject->file.c_str(),
-                        reject->name.c_str(), reject->comment.c_str());
-            }
-        }
-    }
-
-    for (it=settings.begin(); it!=settings.end(); it++) {
-        const Settings& setting = it->second;
-        if (it->first != setting.id) {
-            fprintf(stderr, "it->first='%s' setting.id='%s'\n", it->first.c_str(),
-                    setting.id.c_str());
-            err |= 1;
-        }
-    }
-
-
-    return err;
-}
-
-static int
-test_one_pseudo(bool big, const char* expected)
-{
-    XLIFFFile* xliff = XLIFFFile::Parse("testdata/pseudo.xliff");
-    if (xliff == NULL) {
-        printf("couldn't read file\n");
-        return 1;
-    }
-    if (false) {
-        printf("XLIFF was [[%s]]\n", xliff->ToString().c_str());
-    }
-
-    pseudolocalize_xliff(xliff, big);
-    string newString = xliff->ToString();
-    delete xliff;
-
-    if (false) {
-        printf("XLIFF is [[%s]]\n", newString.c_str());
-    }
-
-    if (false && newString != expected) {
-        fprintf(stderr, "xliff didn't translate as expected\n");
-        fprintf(stderr, "newString=[[%s]]\n", newString.c_str());
-        fprintf(stderr, "expected=[[%s]]\n", expected);
-        return 1;
-    }
-
-    return 0;
-}
-
-static int
-pseudolocalize_test()
-{
-    int err = 0;
-    
-    err |= test_one_pseudo(false, "");
-    //err |= test_one_pseudo(true, "");
-
-    return err;
-}
-
-int
-localize_test()
-{
-    bool all = true;
-    int err = 0;
-
-    if (all) err |= translated_file_name_test();
-    if (all) err |= delete_trans_units();
-    if (all) err |= filter_trans_units();
-    if (all) err |= settings_test();
-    if (all) err |= pseudolocalize_test();
-
-    return err;
-}
-
diff --git a/tools/localize/log.h b/tools/localize/log.h
deleted file mode 100644
index 4a5fa7f..0000000
--- a/tools/localize/log.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef LOG_H
-#define LOG_H
-
-void log_printf(const char* fmt, ...);
-
-#endif // LOG_H
-
diff --git a/tools/localize/merge_res_and_xliff.cpp b/tools/localize/merge_res_and_xliff.cpp
deleted file mode 100644
index 1fdaa0e..0000000
--- a/tools/localize/merge_res_and_xliff.cpp
+++ /dev/null
@@ -1,392 +0,0 @@
-#include "merge_res_and_xliff.h"
-
-#include "file_utils.h"
-#include "Perforce.h"
-#include "log.h"
-#include <stdio.h>
-
-static set<StringResource>::const_iterator
-find_id(const set<StringResource>& s, const string& id, int index)
-{
-    for (set<StringResource>::const_iterator it = s.begin(); it != s.end(); it++) {
-        if (it->id == id && it->index == index) {
-            return it;
-        }
-    }
-    return s.end();
-}
-
-static set<StringResource>::const_iterator
-find_in_xliff(const set<StringResource>& s, const string& filename, const string& id, int index,
-                int version, const Configuration& config)
-{
-    for (set<StringResource>::const_iterator it = s.begin(); it != s.end(); it++) {
-        if (it->file == filename && it->id == id && it->index == index && it->version == version
-                && it->config == config) {
-            return it;
-        }
-    }
-    return s.end();
-}
-
-
-static void
-printit(const set<StringResource>& s, const set<StringResource>::const_iterator& it)
-{
-    if (it == s.end()) {
-        printf("(none)\n");
-    } else {
-        printf("id=%s index=%d config=%s file=%s value='%s'\n", it->id.c_str(), it->index,
-                it->config.ToString().c_str(), it->file.c_str(),
-                it->value->ToString(ANDROID_NAMESPACES).c_str());
-    }
-}
-
-StringResource
-convert_resource(const StringResource& s, const string& file, const Configuration& config,
-                    int version, const string& versionString)
-{
-    return StringResource(s.pos, file, config, s.id, s.index, s.value ? s.value->Clone() : NULL,
-            version, versionString, s.comment);
-}
-
-static bool
-resource_has_contents(const StringResource& res)
-{
-    XMLNode* value = res.value;
-    if (value == NULL) {
-        return false;
-    }
-    string contents = value->ContentsToString(ANDROID_NAMESPACES);
-    return contents != "";
-}
-
-ValuesFile*
-merge_res_and_xliff(const ValuesFile* en_currentFile,
-        const ValuesFile* xx_currentFile, const ValuesFile* xx_oldFile,
-        const string& filename, const XLIFFFile* xliffFile)
-{
-    bool success = true;
-
-    Configuration en_config = xliffFile->SourceConfig();
-    Configuration xx_config = xliffFile->TargetConfig();
-    string currentVersion = xliffFile->CurrentVersion();
-
-    ValuesFile* result = new ValuesFile(xx_config);
-
-    set<StringResource> en_cur = en_currentFile->GetStrings();
-    set<StringResource> xx_cur = xx_currentFile->GetStrings();
-    set<StringResource> xx_old = xx_oldFile->GetStrings();
-    set<StringResource> xliff = xliffFile->GetStringResources();
-
-    // for each string in en_current
-    for (set<StringResource>::const_iterator en_c = en_cur.begin();
-            en_c != en_cur.end(); en_c++) {
-        set<StringResource>::const_iterator xx_c = find_id(xx_cur, en_c->id, en_c->index);
-        set<StringResource>::const_iterator xx_o = find_id(xx_old, en_c->id, en_c->index);
-        set<StringResource>::const_iterator xlf = find_in_xliff(xliff, en_c->file, en_c->id,
-                                                        en_c->index, CURRENT_VERSION, xx_config);
-
-        if (false) {
-            printf("\nen_c: "); printit(en_cur, en_c);
-            printf("xx_c: "); printit(xx_cur, xx_c);
-            printf("xx_o: "); printit(xx_old, xx_o);
-            printf("xlf:  "); printit(xliff, xlf);
-        }
-
-        // if it changed between xx_old and xx_current, use xx_current
-        // (someone changed it by hand)
-        if (xx_o != xx_old.end() && xx_c != xx_cur.end()) {
-            string xx_o_value = xx_o->value->ToString(ANDROID_NAMESPACES);
-            string xx_c_value = xx_c->value->ToString(ANDROID_NAMESPACES);
-            if (xx_o_value != xx_c_value && xx_c_value != "") {
-                StringResource r(convert_resource(*xx_c, filename, xx_config,
-                                                    CURRENT_VERSION, currentVersion));
-                if (resource_has_contents(r)) {
-                    result->AddString(r);
-                }
-                continue;
-            }
-        }
-
-        // if it is present in xliff, use that
-        // (it just got translated)
-        if (xlf != xliff.end() && xlf->value->ToString(ANDROID_NAMESPACES) != "") {
-            StringResource r(convert_resource(*xlf, filename, xx_config,
-                                                CURRENT_VERSION, currentVersion));
-            if (resource_has_contents(r)) {
-                result->AddString(r);
-            }
-        }
-
-        // if it is present in xx_current, use that
-        // (it was already translated, and not retranslated)
-        // don't filter out empty strings if they were added by hand, the above code just
-        // guarantees that this tool never adds an empty one.
-        if (xx_c != xx_cur.end()) {
-            StringResource r(convert_resource(*xx_c, filename, xx_config,
-                                                CURRENT_VERSION, currentVersion));
-            result->AddString(r);
-        }
-
-        // othwerwise, leave it out.  The resource fall-through code will use the English
-        // one at runtime, and the xliff export code will pick it up for translation next time.
-    }
-
-    if (success) {
-        return result;
-    } else {
-        delete result;
-        return NULL;
-    }
-}
-
-
-struct MergedFile {
-    XLIFFFile* xliff;
-    string xliffFilename;
-    string original;
-    string translated;
-    ValuesFile* en_current;
-    ValuesFile* xx_current;
-    ValuesFile* xx_old;
-    ValuesFile* xx_new;
-    string xx_new_text;
-    string xx_new_filename;
-    bool new_file;
-    bool deleted_file;
-
-    MergedFile();
-    MergedFile(const MergedFile&);
-};
-
-struct compare_filenames {
-    bool operator()(const MergedFile& lhs, const MergedFile& rhs) const
-    {
-        return lhs.original < rhs.original;
-    }
-};
-
-MergedFile::MergedFile()
-    :xliff(NULL),
-     xliffFilename(),
-     original(),
-     translated(),
-     en_current(NULL),
-     xx_current(NULL),
-     xx_old(NULL),
-     xx_new(NULL),
-     xx_new_text(),
-     xx_new_filename(),
-     new_file(false),
-     deleted_file(false)
-{
-}
-
-MergedFile::MergedFile(const MergedFile& that)
-    :xliff(that.xliff),
-     xliffFilename(that.xliffFilename),
-     original(that.original),
-     translated(that.translated),
-     en_current(that.en_current),
-     xx_current(that.xx_current),
-     xx_old(that.xx_old),
-     xx_new(that.xx_new),
-     xx_new_text(that.xx_new_text),
-     xx_new_filename(that.xx_new_filename),
-     new_file(that.new_file),
-     deleted_file(that.deleted_file)
-{
-}
-
-
-typedef set<MergedFile, compare_filenames> MergedFileSet;
-
-int
-do_merge(const vector<string>& xliffFilenames)
-{
-    int err = 0;
-    MergedFileSet files;
-
-    printf("\rPreparing..."); fflush(stdout);
-    string currentChange = Perforce::GetCurrentChange(true);
-
-    // for each xliff, make a MergedFile record and do a little error checking
-    for (vector<string>::const_iterator xliffFilename=xliffFilenames.begin();
-            xliffFilename!=xliffFilenames.end(); xliffFilename++) {
-        XLIFFFile* xliff = XLIFFFile::Parse(*xliffFilename);
-        if (xliff == NULL) {
-            fprintf(stderr, "localize import: unable to read file %s\n", xliffFilename->c_str());
-            err = 1;
-            continue;
-        }
-
-        set<string> xf = xliff->Files();
-        for (set<string>::const_iterator f=xf.begin(); f!=xf.end(); f++) {
-            MergedFile mf;
-            mf.xliff = xliff;
-            mf.xliffFilename = *xliffFilename;
-            mf.original = *f;
-            mf.translated = translated_file_name(mf.original, xliff->TargetConfig().locale);
-            log_printf("mf.translated=%s mf.original=%s locale=%s\n", mf.translated.c_str(),
-                    mf.original.c_str(), xliff->TargetConfig().locale.c_str());
-
-            if (files.find(mf) != files.end()) {
-                fprintf(stderr, "%s: duplicate string resources for file %s\n",
-                        xliffFilename->c_str(), f->c_str());
-                fprintf(stderr, "%s: previously defined here.\n",
-                        files.find(mf)->xliffFilename.c_str());
-                err = 1;
-                continue;
-            }
-            files.insert(mf);
-        }
-    }
-
-    size_t deletedFileCount = 0;
-    size_t J = files.size() * 3;
-    size_t j = 1;
-    // Read all of the files from perforce.
-    for (MergedFileSet::iterator mf = files.begin(); mf != files.end(); mf++) {
-        MergedFile* file = const_cast<MergedFile*>(&(*mf));
-        // file->en_current
-        print_file_status(j++, J);
-        file->en_current = get_values_file(file->original, file->xliff->SourceConfig(),
-                                            CURRENT_VERSION, currentChange, true);
-        if (file->en_current == NULL) {
-            // deleted file
-            file->deleted_file = true;
-            deletedFileCount++;
-            continue;
-        }
-
-        // file->xx_current;
-        print_file_status(j++, J);
-        file->xx_current = get_values_file(file->translated, file->xliff->TargetConfig(),
-                                            CURRENT_VERSION, currentChange, false);
-        if (file->xx_current == NULL) {
-            file->xx_current = new ValuesFile(file->xliff->TargetConfig());
-            file->new_file = true;
-        }
-
-        // file->xx_old (note that the xliff's current version is our old version, because that
-        // was the current version when it was exported)
-        print_file_status(j++, J);
-        file->xx_old = get_values_file(file->translated, file->xliff->TargetConfig(),
-                                            OLD_VERSION, file->xliff->CurrentVersion(), false);
-        if (file->xx_old == NULL) {
-            file->xx_old = new ValuesFile(file->xliff->TargetConfig());
-            file->new_file = true;
-        }
-    }
-
-    // merge them
-    for (MergedFileSet::iterator mf = files.begin(); mf != files.end(); mf++) {
-        MergedFile* file = const_cast<MergedFile*>(&(*mf));
-        if (file->deleted_file) {
-            continue;
-        }
-        file->xx_new = merge_res_and_xliff(file->en_current, file->xx_current, file->xx_old,
-                                            file->original, file->xliff);
-    }
-
-    // now is a good time to stop if there was an error
-    if (err != 0) {
-        return err;
-    }
-
-    // locate the files
-    j = 1;
-    for (MergedFileSet::iterator mf = files.begin(); mf != files.end(); mf++) {
-        MergedFile* file = const_cast<MergedFile*>(&(*mf));
-        print_file_status(j++, J, "Locating");
-
-        file->xx_new_filename = Perforce::Where(file->translated, true);
-        if (file->xx_new_filename == "") {
-            fprintf(stderr, "\nWas not able to determine the location of depot file %s\n",
-                    file->translated.c_str());
-            err = 1;
-        }
-    }
-
-    if (err != 0) {
-        return err;
-    }
-
-    // p4 edit the files
-    // only do this if it changed - no need to submit files that haven't changed meaningfully
-    vector<string> filesToEdit;
-    vector<string> filesToAdd;
-    vector<string> filesToDelete;
-    for (MergedFileSet::iterator mf = files.begin(); mf != files.end(); mf++) {
-        MergedFile* file = const_cast<MergedFile*>(&(*mf));
-        if (file->deleted_file) {
-            filesToDelete.push_back(file->xx_new_filename);
-            continue;
-        }
-        string xx_current_text = file->xx_current->ToString();
-        string xx_new_text = file->xx_new->ToString();
-        if (xx_current_text != xx_new_text) {
-            if (file->xx_new->GetStrings().size() == 0) {
-                file->deleted_file = true;
-                filesToDelete.push_back(file->xx_new_filename);
-            } else {
-                file->xx_new_text = xx_new_text;
-                if (file->new_file) {
-                    filesToAdd.push_back(file->xx_new_filename);
-                } else {
-                    filesToEdit.push_back(file->xx_new_filename);
-                }
-            }
-        }
-    }
-    if (filesToAdd.size() == 0 && filesToEdit.size() == 0 && deletedFileCount == 0) {
-        printf("\nAll of the files are the same.  Nothing to change.\n");
-        return 0;
-    }
-    if (filesToEdit.size() > 0) {
-        printf("\np4 editing files...\n");
-        if (0 != Perforce::EditFiles(filesToEdit, true)) {
-            return 1;
-        }
-    }
-
-
-    printf("\n");
-
-    for (MergedFileSet::iterator mf = files.begin(); mf != files.end(); mf++) {
-        MergedFile* file = const_cast<MergedFile*>(&(*mf));
-        if (file->deleted_file) {
-            continue;
-        }
-        if (file->xx_new_text != "" && file->xx_new_filename != "") {
-            if (0 != write_to_file(file->xx_new_filename, file->xx_new_text)) {
-                err = 1;
-            }
-        }
-    }
-
-    if (err != 0) {
-        return err;
-    }
-
-    if (filesToAdd.size() > 0) {
-        printf("p4 adding %zd new files...\n", filesToAdd.size());
-        err = Perforce::AddFiles(filesToAdd, true);
-    }
-
-    if (filesToDelete.size() > 0) {
-        printf("p4 deleting %zd removed files...\n", filesToDelete.size());
-        err = Perforce::DeleteFiles(filesToDelete, true);
-    }
-
-    if (err != 0) {
-        return err;
-    }
-
-    printf("\n"
-           "Theoretically, this merge was successfull.  Next you should\n"
-           "review the diffs, get a code review, and submit it.  Enjoy.\n\n");
-    return 0;
-}
-
diff --git a/tools/localize/merge_res_and_xliff.h b/tools/localize/merge_res_and_xliff.h
deleted file mode 100644
index acf2fff..0000000
--- a/tools/localize/merge_res_and_xliff.h
+++ /dev/null
@@ -1,13 +0,0 @@
-#ifndef MERGE_RES_AND_XLIFF_H
-#define MERGE_RES_AND_XLIFF_H
-
-#include "ValuesFile.h"
-#include "XLIFFFile.h"
-
-ValuesFile* merge_res_and_xliff(const ValuesFile* en_current,
-                                const ValuesFile* xx_current, const ValuesFile* xx_old,
-                                const string& filename, const XLIFFFile* xliff);
-
-int do_merge(const vector<string>& xliffFilenames);
-
-#endif // MERGE_RES_AND_XLIFF_H
diff --git a/tools/localize/merge_res_and_xliff_test.cpp b/tools/localize/merge_res_and_xliff_test.cpp
deleted file mode 100644
index 6fe2629..0000000
--- a/tools/localize/merge_res_and_xliff_test.cpp
+++ /dev/null
@@ -1,48 +0,0 @@
-#include <cstdio>
-#include "merge_res_and_xliff.h"
-#include <stdio.h>
-
-int
-merge_test()
-{
-    Configuration english;
-        english.locale = "en_US";
-    Configuration translated;
-        translated.locale = "zz_ZZ";
-
-    ValuesFile* en_current = ValuesFile::ParseFile("testdata/merge_en_current.xml", english,
-                                                    CURRENT_VERSION, "3");
-    if (en_current == NULL) {
-        fprintf(stderr, "merge_test: unable to read testdata/merge_en_current.xml\n");
-        return 1;
-    }
-
-    ValuesFile* xx_current = ValuesFile::ParseFile("testdata/merge_xx_current.xml", translated,
-                                                    CURRENT_VERSION, "3");
-    if (xx_current == NULL) {
-        fprintf(stderr, "merge_test: unable to read testdata/merge_xx_current.xml\n");
-        return 1;
-    }
-    ValuesFile* xx_old = ValuesFile::ParseFile("testdata/merge_xx_old.xml", translated,
-                                                    OLD_VERSION, "2");
-    if (xx_old == NULL) {
-        fprintf(stderr, "merge_test: unable to read testdata/merge_xx_old.xml\n");
-        return 1;
-    }
-
-    XLIFFFile* xliff = XLIFFFile::Parse("testdata/merge.xliff");
-
-    ValuesFile* result = merge_res_and_xliff(en_current, xx_current, xx_old,
-                                "//device/tools/localize/testdata/res/values/strings.xml", xliff);
-
-    if (result == NULL) {
-        fprintf(stderr, "merge_test: result is NULL\n");
-        return 1;
-    }
-
-    printf("======= RESULT =======\n%s===============\n", result->ToString().c_str());
-
-    return 0;
-}
-
-
diff --git a/tools/localize/res_check.cpp b/tools/localize/res_check.cpp
deleted file mode 100644
index 0fab98a..0000000
--- a/tools/localize/res_check.cpp
+++ /dev/null
@@ -1,106 +0,0 @@
-#include "res_check.h"
-#include "localize.h"
-#include "file_utils.h"
-#include "ValuesFile.h"
-
-#include <stdio.h>
-
-static int check_file(const ValuesFile* file);
-static int check_value(const SourcePos& pos, const XMLNode* value);
-static int scan_for_unguarded_format(const SourcePos& pos, const XMLNode* value, int depth = 0);
-
-int
-do_rescheck(const vector<string>& files)
-{
-    int err;
-
-    Configuration english;
-        english.locale = "en_US";
-
-    for (size_t i=0; i<files.size(); i++) {
-        const string filename = files[i];
-        ValuesFile* valuesFile = get_local_values_file(filename, english, CURRENT_VERSION,
-                "0", true);
-        if (valuesFile != NULL) {
-            err |= check_file(valuesFile);
-            delete valuesFile;
-        } else {
-            err |= 1;
-        }
-    }
-
-    return err;
-}
-
-static int
-check_file(const ValuesFile* file)
-{
-    int err = 0;
-    set<StringResource> strings = file->GetStrings();
-    for (set<StringResource>::iterator it=strings.begin(); it!=strings.end(); it++) {
-        XMLNode* value = it->value;
-        if (value != NULL) {
-            err |= check_value(it->pos, value);
-        }
-    }
-    return err;
-}
-
-static bool
-contains_percent(const string& str)
-{
-    const size_t len = str.length();
-    for (size_t i=0; i<len; i++) {
-        char c = str[i];
-        if (c == '%') {
-            return true;
-        }
-    }
-    return false;
-}
-
-static int
-check_value(const SourcePos& pos, const XMLNode* value)
-{
-    int err = 0;
-    err |= scan_for_unguarded_format(pos, value);
-    return err;
-}
-
-static bool
-is_xliff_block(const string& ns, const string& name)
-{
-    if (ns == XLIFF_XMLNS) {
-        return name == "g";
-    } else {
-        return false;
-    }
-}
-
-static int
-scan_for_unguarded_format(const SourcePos& pos, const string& string)
-{
-    bool containsPercent = contains_percent(string);
-    if (containsPercent) {
-        pos.Error("unguarded percent: '%s'\n", string.c_str());
-    }
-    return 0;
-}
-
-static int
-scan_for_unguarded_format(const SourcePos& pos, const XMLNode* value, int depth)
-{
-    if (value->Type() == XMLNode::ELEMENT) {
-        int err = 0;
-        if (depth == 0 || !is_xliff_block(value->Namespace(), value->Name())) {
-            const vector<XMLNode*>& children = value->Children();
-            for (size_t i=0; i<children.size(); i++) {
-                err |= scan_for_unguarded_format(pos, children[i], depth+1);
-            }
-        }
-        return err;
-    } else {
-        return scan_for_unguarded_format(pos, value->Text());
-    }
-}
-
diff --git a/tools/localize/res_check.h b/tools/localize/res_check.h
deleted file mode 100644
index 86e7ce6..0000000
--- a/tools/localize/res_check.h
+++ /dev/null
@@ -1,12 +0,0 @@
-#ifndef RESCHECK_H
-#define RESCHECK_H
-
-#include <map>
-#include <string>
-#include <vector>
-
-using namespace std;
-
-int do_rescheck(const vector<string>& files);
-
-#endif // RESCHECK_H
diff --git a/tools/localize/test.cpp b/tools/localize/test.cpp
deleted file mode 100644
index 5fa2c17..0000000
--- a/tools/localize/test.cpp
+++ /dev/null
@@ -1,31 +0,0 @@
-#include "SourcePos.h"
-#include <stdio.h>
-
-int ValuesFile_test();
-int XLIFFFile_test();
-int XMLHandler_test();
-int Perforce_test();
-int localize_test();
-int merge_test();
-
-int
-test()
-{
-    bool all = true;
-    int err = 0;
-
-    if (all) err |= XMLHandler_test();
-    if (all) err |= ValuesFile_test();
-    if (all) err |= XLIFFFile_test();
-    if (all) err |= Perforce_test();
-    if (all) err |= localize_test();
-    if (all) err |= merge_test();
-
-    if (err != 0) {
-        fprintf(stderr, "some tests failed\n");
-    } else {
-        fprintf(stderr, "all tests passed\n");
-    }
-
-    return err;
-}
diff --git a/tools/localize/testdata/config.xml b/tools/localize/testdata/config.xml
deleted file mode 100644
index affa140f..0000000
--- a/tools/localize/testdata/config.xml
+++ /dev/null
@@ -1,15 +0,0 @@
-<localize-config>
-    <configuration id="system"
-            old-cl="1"
-            new-cl="43019">
-        <app dir="apps/common" />
-    </configuration>
-    <configuration id="samples"
-            old-cl="24801"
-            new-cl="43019">
-        <app dir="samples/NotePad" />
-        <reject file="samples/NotePad/res/values/strings.xml" name="string:menu_delete">
-            QA says this sounds <b>rude</b>.
-        </reject>
-    </configuration>
-</localize-config>
diff --git a/tools/localize/testdata/import.xliff b/tools/localize/testdata/import.xliff
deleted file mode 100644
index b99b739..0000000
--- a/tools/localize/testdata/import.xliff
+++ /dev/null
@@ -1,72 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2"
-        version="1.2"
-        >
-    <file datatype="x-android-res"
-            original="//device/tools/localize/testdata/res/values/strings.xml"
-            product-version="1.0"
-            date="08:10:54 12/07/07 PST"
-            source-language="en_US"
-            product-name="kila"
-            target-language="zz_ZZ"
-            build-num="44391"
-            >
-        <body>
-            <trans-unit id="string:changed_in_xx">
-                <source>aaa</source>
-                <target>AAA</target>
-            </trans-unit>
-            <trans-unit id="string:first_translation">
-                <source>bbb</source>
-                <target>BBB</target>
-            </trans-unit>
-            <trans-unit id="string:deleted_string">
-                <source>ddd</source>
-                <target>DDDD</target>
-            </trans-unit>
-            <trans-unit id="array:0:growing_array">
-                <source>1-One</source>
-                <target>1-oNE</target>
-            </trans-unit>
-            <trans-unit id="array:1:growing_array">
-                <source>1-Two</source>
-                <target>1-tWO</target>
-            </trans-unit>
-            <trans-unit id="array:2:growing_array">
-                <source>1-Three</source>
-                <target>1-tHREE</target>
-            </trans-unit>
-            <trans-unit id="array:0:shrinking_array">
-                <source>2-One</source>
-                <target>2-oNE</target>
-            </trans-unit>
-            <trans-unit id="array:1:shrinking_array">
-                <source>2-Two</source>
-                <target>2-tWO</target>
-            </trans-unit>
-            <trans-unit id="array:2:shrinking_array">
-                <source>2-Three</source>
-                <target>2-tHREE</target>
-            </trans-unit>
-            <trans-unit id="array:3:shrinking_array">
-                <source>2-Four</source>
-                <target>2-fOUR</target>
-            </trans-unit>
-            <trans-unit id="array:0:deleted_array">
-                <source>4-One</source>
-                <target>4-oNE</target>
-            </trans-unit>
-            <trans-unit id="array:1:deleted_array">
-                <source>4-Two</source>
-                <target>4-tWO</target>
-            </trans-unit>
-            <trans-unit id="array:2:deleted_array">
-                <source>4-Three</source>
-                <target>4-tHREE</target>
-            </trans-unit>
-
-        </body>
-    </file>
-</xliff>
-
-
diff --git a/tools/localize/testdata/merge.xliff b/tools/localize/testdata/merge.xliff
deleted file mode 100644
index 2b78c45..0000000
--- a/tools/localize/testdata/merge.xliff
+++ /dev/null
@@ -1,72 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2"
-        version="1.2"
-        >
-    <file datatype="x-android-res"
-            original="testdata/merge_en_current.xml"
-            product-version="1.0"
-            date="08:10:54 12/07/07 PST"
-            source-language="en-US"
-            product-name="kila"
-            target-language="zz-ZZ"
-            build-num="44391"
-            >
-        <body>
-            <trans-unit id="string:changed_in_xx">
-                <source>aaa</source>
-                <target>AAA</target>
-            </trans-unit>
-            <trans-unit id="string:first_translation">
-                <source>bbb</source>
-                <target>BBB</target>
-            </trans-unit>
-            <trans-unit id="string:deleted_string">
-                <source>ddd</source>
-                <target>DDDD</target>
-            </trans-unit>
-            <trans-unit id="array:0:growing_array">
-                <source>1-One</source>
-                <target>1-oNE</target>
-            </trans-unit>
-            <trans-unit id="array:1:growing_array">
-                <source>1-Two</source>
-                <target>1-tWO</target>
-            </trans-unit>
-            <trans-unit id="array:2:growing_array">
-                <source>1-Three</source>
-                <target>1-tHREE</target>
-            </trans-unit>
-            <trans-unit id="array:0:shrinking_array">
-                <source>2-One</source>
-                <target>2-oNE</target>
-            </trans-unit>
-            <trans-unit id="array:1:shrinking_array">
-                <source>2-Two</source>
-                <target>2-tWO</target>
-            </trans-unit>
-            <trans-unit id="array:2:shrinking_array">
-                <source>2-Three</source>
-                <target>2-tHREE</target>
-            </trans-unit>
-            <trans-unit id="array:3:shrinking_array">
-                <source>2-Four</source>
-                <target>2-fOUR</target>
-            </trans-unit>
-            <trans-unit id="array:0:deleted_array">
-                <source>4-One</source>
-                <target>4-oNE</target>
-            </trans-unit>
-            <trans-unit id="array:1:deleted_array">
-                <source>4-Two</source>
-                <target>4-tWO</target>
-            </trans-unit>
-            <trans-unit id="array:2:deleted_array">
-                <source>4-Three</source>
-                <target>4-tHREE</target>
-            </trans-unit>
-
-        </body>
-    </file>
-</xliff>
-
-
diff --git a/tools/localize/testdata/merge_en_current.xml b/tools/localize/testdata/merge_en_current.xml
deleted file mode 100644
index 6a11e68..0000000
--- a/tools/localize/testdata/merge_en_current.xml
+++ /dev/null
@@ -1,44 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2007 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-  
-          http://www.apache.org/licenses/LICENSE-2.0
-  
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="changed_in_xx">aaa</string>
-    <string name="first_translation">bbb</string>
-    <string name="previously_translated">ccc</string>
-    <string name="new_string">ccc</string>
-
-    <string name="formatted_string"><b>bold</b><i>italic<u>italic_underline</u></i><u>underline</u></string>
-
-    <array name="growing_array">
-        <!-- somebody wrote a comment! -->
-        <item>1-One</item>
-        <item>1-Two</item>
-        <item>1-Three</item>
-        <item>1-Four</item>
-    </array>
-    <array name="shrinking_array">
-        <!-- somebody wrote a comment! -->
-        <item>2-One</item>
-        <item>2-Two</item>
-        <item>2-Three</item>
-    </array>
-    <array name="new_array">
-        <!-- somebody wrote a comment! -->
-        <item>3-One</item>
-        <item>3-Two</item>
-        <item>3-Three</item>
-    </array>
-</resources>
diff --git a/tools/localize/testdata/merge_en_old.xml b/tools/localize/testdata/merge_en_old.xml
deleted file mode 100644
index 933f98e..0000000
--- a/tools/localize/testdata/merge_en_old.xml
+++ /dev/null
@@ -1,45 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2007 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-  
-          http://www.apache.org/licenses/LICENSE-2.0
-  
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="changed_in_xx">aaa</string>
-    <string name="first_translation">bbb</string>
-    <string name="previously_translated">ccc</string>
-    <string name="deleted_string">ddd</string>
-
-    <string name="formatted_string"><b>bold</b><i>italic<u>italic_underline</u></i><u>underline</u></string>
-
-    <array name="growing_array">
-        <!-- somebody wrote a comment! -->
-        <item>1-One</item>
-        <item>1-Two</item>
-        <item>1-Three</item>
-    </array>
-    <array name="shrinking_array">
-        <!-- somebody wrote a comment! -->
-        <item>2-One</item>
-        <item>2-Two</item>
-        <item>2-Three</item>
-        <item>2-Four</item>
-    </array>
-    <array name="deleted_array">
-        <!-- somebody wrote a comment! -->
-        <item>4-One</item>
-        <item>4-Two</item>
-        <item>4-Three</item>
-    </array>
-</resources>
-
diff --git a/tools/localize/testdata/merge_xx_current.xml b/tools/localize/testdata/merge_xx_current.xml
deleted file mode 100644
index c2a783d..0000000
--- a/tools/localize/testdata/merge_xx_current.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2007 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-  
-          http://www.apache.org/licenses/LICENSE-2.0
-  
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="changed_in_xx">AAAA</string>
-    <string name="previously_translated">CCC</string>
-</resources>
-
-
diff --git a/tools/localize/testdata/pseudo.xliff b/tools/localize/testdata/pseudo.xliff
deleted file mode 100644
index 5b44f86..0000000
--- a/tools/localize/testdata/pseudo.xliff
+++ /dev/null
@@ -1,40 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2"
-        version="1.2"
-        >
-    <file datatype="x-android-res"
-            original="//device/tools/localization/tests/res/values/strings.xml"
-            product-version="1.0"
-            date="08:10:54 12/07/07 PST"
-            source-language="en-US"
-            product-name="kila"
-            target-language="zz-ZZ"
-            build-num="32138"
-            >
-        <body>
-            <trans-unit id="string:complex">
-                <source>First <g id="string:complex:0" ctype="underline">underline</g>, <g id="string:complex:1" ctype="italic">italic<g id="string:complex:2" ctype="bold">italicbold</g></g> End </source>
-            </trans-unit>
-            <trans-unit id="string:complex-quoted">
-                <source xml:space="preserve">First <g id="string:complex-quoted:0" ctype="underline">underline</g>, <g id="string:complex-quoted:1" ctype="italic">italic<g id="string:complex-quoted:2" ctype="bold">italicbold</g></g> End</source>
-            </trans-unit>
-            <trans-unit id="string:simple">
-                <source>Simple</source>
-            </trans-unit>
-            <trans-unit id="array:0:simple">
-                <source>Simple</source>
-            </trans-unit>
-            <trans-unit id="array:1:simple">
-                <source>Simple</source>
-            </trans-unit>
-            <trans-unit id="string:simple-quoted">
-                <source xml:space="preserve"> Quote</source>
-                <alt-trans>
-                    <source xml:lang="en" xml:space="preserve"> OLD Quote</source>
-                    <target xml:lang="xx"> OLD Ờũỡŧę</target>
-                </alt-trans>
-            </trans-unit>
-        </body>
-    </file>
-</xliff>
-
diff --git a/tools/localize/testdata/res/values/strings.xml b/tools/localize/testdata/res/values/strings.xml
deleted file mode 100644
index 6a11e68..0000000
--- a/tools/localize/testdata/res/values/strings.xml
+++ /dev/null
@@ -1,44 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2007 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-  
-          http://www.apache.org/licenses/LICENSE-2.0
-  
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="changed_in_xx">aaa</string>
-    <string name="first_translation">bbb</string>
-    <string name="previously_translated">ccc</string>
-    <string name="new_string">ccc</string>
-
-    <string name="formatted_string"><b>bold</b><i>italic<u>italic_underline</u></i><u>underline</u></string>
-
-    <array name="growing_array">
-        <!-- somebody wrote a comment! -->
-        <item>1-One</item>
-        <item>1-Two</item>
-        <item>1-Three</item>
-        <item>1-Four</item>
-    </array>
-    <array name="shrinking_array">
-        <!-- somebody wrote a comment! -->
-        <item>2-One</item>
-        <item>2-Two</item>
-        <item>2-Three</item>
-    </array>
-    <array name="new_array">
-        <!-- somebody wrote a comment! -->
-        <item>3-One</item>
-        <item>3-Two</item>
-        <item>3-Three</item>
-    </array>
-</resources>
diff --git a/tools/localize/testdata/strip_xliff.xliff b/tools/localize/testdata/strip_xliff.xliff
deleted file mode 100644
index 9254cf2..0000000
--- a/tools/localize/testdata/strip_xliff.xliff
+++ /dev/null
@@ -1,70 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2"
-        version="1.2"
-        >
-    <file datatype="x-android-res"
-            original="//device/tools/localization/tests/res/values/strings.xml"
-            product-version="1.0"
-            date="08:10:54 12/07/07 PST"
-            source-language="en-US"
-            product-name="kila"
-            target-language="zz-ZZ"
-            build-num="32138"
-            >
-        <body>
-
-            <trans-unit id="string:string-000-0">
-            </trans-unit>
-            <trans-unit id="string:string-001-0">
-                <alt-trans>
-                    <source xml:lang="en" xml:space="preserve">source</source>
-                </alt-trans>
-            </trans-unit>
-            <trans-unit id="string:string-010-0">
-                <alt-trans>
-                    <target xml:lang="zz" xml:space="preserve">target</target>
-                </alt-trans>
-            </trans-unit>
-            <trans-unit id="string:string-011-0">
-                <alt-trans>
-                    <source xml:lang="en" xml:space="preserve">source</source>
-                    <target xml:lang="zz" xml:space="preserve">target</target>
-                </alt-trans>
-            </trans-unit>
-
-            <trans-unit id="string:string-100-1">
-                <source xml:space="preserve">source</source>
-            </trans-unit>
-            <trans-unit id="string:string-101-1">
-                <source xml:space="preserve">source</source>
-                <alt-trans>
-                    <source xml:lang="en" xml:space="preserve">source</source>
-                </alt-trans>
-            </trans-unit>
-            <trans-unit id="string:string-110-1">
-                <source xml:space="preserve">source</source>
-                <alt-trans>
-                    <target xml:lang="zz" xml:space="preserve">target</target>
-                </alt-trans>
-            </trans-unit>
-
-            <trans-unit id="string:string-111-0">
-                <source xml:space="preserve">source</source>
-                <alt-trans>
-                    <source xml:lang="en" xml:space="preserve">source</source>
-                    <target xml:lang="zz" xml:space="preserve">target</target>
-                </alt-trans>
-            </trans-unit>
-            <trans-unit id="string:string-111-1">
-                <source xml:space="preserve">source</source>
-                <alt-trans>
-                    <source xml:lang="en" xml:space="preserve">alt-source</source>
-                    <target xml:lang="zz" xml:space="preserve">target</target>
-                </alt-trans>
-            </trans-unit>
-
-        </body>
-    </file>
-</xliff>
-
-
diff --git a/tools/localize/testdata/values/strings.xml b/tools/localize/testdata/values/strings.xml
deleted file mode 100644
index 5e8d43d..0000000
--- a/tools/localize/testdata/values/strings.xml
+++ /dev/null
@@ -1,32 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2007 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-  
-          http://www.apache.org/licenses/LICENSE-2.0
-  
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-
-<resources
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="test1">Discard</string>
-    <!-- comment -->
-    <string name="test2">a<b>b<i>c</i></b>d</string>
-    <string name="test3">a<xliff:g  a="b" xliff:a="asdf">bBb</xliff:g>C</string>
-
-    <!-- Email address types from android.provider.Contacts -->
-    <array name="emailAddressTypes">
-        <!-- somebody wrote a comment! -->
-        <item>Email</item>
-        <item>Home</item>
-        <item>Work</item>
-        <item>Other\u2026</item>
-    </array>
-</resources>
diff --git a/tools/localize/testdata/xliff1.xliff b/tools/localize/testdata/xliff1.xliff
deleted file mode 100644
index 55a8d8e..0000000
--- a/tools/localize/testdata/xliff1.xliff
+++ /dev/null
@@ -1,46 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2"
-        version="1.2"
-        >
-    <file datatype="x-android-res"
-            original="//device/tools/localization/tests/res/values/strings.xml"
-            product-version="1.0"
-            date="08:10:54 12/07/07 PST"
-            source-language="en-US"
-            product-name="kila"
-            target-language="zz-ZZ"
-            build-num="32138"
-            >
-        <body>
-            <trans-unit id="string:complex">
-                <source>First <g id="string:complex:0" ctype="underline">underline</g>, <g id="string:complex:1" ctype="italic">italic<g id="string:complex:2" ctype="bold">italicbold</g></g> End </source>
-                <target>Ḟịṙṩŧ ,  Ḛŋḋ </target>
-            </trans-unit>
-            <trans-unit id="string:complex-quoted">
-                <source xml:space="preserve">First <g id="string:complex-quoted:0" ctype="underline">underline</g>, <g id="string:complex-quoted:1" ctype="italic">italic<g id="string:complex-quoted:2" ctype="bold">italicbold</g></g> End</source>
-                <target>Ḟịṙṩŧ ,  Ḛŋḋ</target>
-            </trans-unit>
-            <trans-unit id="string:simple">
-                <source>Simple</source>
-                <target>Ṩịṃṕļę</target>
-            </trans-unit>
-            <trans-unit id="array:0:simple">
-                <source>Simple</source>
-                <target>Ṩịṃṕļę</target>
-            </trans-unit>
-            <trans-unit id="array:1:simple">
-                <source>Simple</source>
-                <target>Ṩịṃṕļę</target>
-            </trans-unit>
-            <trans-unit id="string:simple-quoted">
-                <source xml:space="preserve"> Quote</source>
-                <target> Ờũỡŧę</target>
-                <alt-trans>
-                    <source xml:lang="en" xml:space="preserve"> OLD Quote</source>
-                    <target xml:lang="xx"> OLD Ờũỡŧę</target>
-                </alt-trans>
-            </trans-unit>
-        </body>
-    </file>
-</xliff>
-
diff --git a/tools/localize/testdata/xml.xml b/tools/localize/testdata/xml.xml
deleted file mode 100644
index ef930d0..0000000
--- a/tools/localize/testdata/xml.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-<ASDF>
-    <a id="system"
-            old-cl="1"
-            new-cl="43019">
-        <app dir="apps/common" />
-    </a>
-    <a id="samples"
-            old-cl="1"
-            new-cl="43019">asdf
-        <app dir="samples/NotePad" />
-        <app dir="samples/LunarLander" />
-        <something>a<b>,</b>b </something>
-        <exact xml:space="preserve">a<b>,</b>b </exact>
-    </a>
-</ASDF>
-
diff --git a/tools/localize/xmb.cpp b/tools/localize/xmb.cpp
deleted file mode 100644
index d8f6ff0..0000000
--- a/tools/localize/xmb.cpp
+++ /dev/null
@@ -1,182 +0,0 @@
-#include "xmb.h"
-
-#include "file_utils.h"
-#include "localize.h"
-#include "ValuesFile.h"
-#include "XMLHandler.h"
-#include "XLIFFFile.h"
-
-#include <map>
-#include <cstdio>
-
-using namespace std;
-
-const char *const NS_MAP[] = {
-    "xml", XMLNS_XMLNS,
-    NULL, NULL
-};
-
-set<string> g_tags;
-
-static string
-strip_newlines(const string& str)
-{
-    string res;
-    const size_t N = str.length();
-    for (size_t i=0; i<N; i++) {
-        char c = str[i];
-        if (c != '\n' && c != '\r') {
-            res += c;
-        } else {
-            res += ' ';
-        }
-    }
-    return res;
-}
-
-static int
-rename_id_attribute(XMLNode* node)
-{
-    vector<XMLAttribute>& attrs = node->EditAttributes();
-    const size_t I = attrs.size();
-    for (size_t i=0; i<I; i++) {
-        XMLAttribute attr = attrs[i];
-        if (attr.name == "id") {
-            attr.name = "name";
-            attrs.erase(attrs.begin()+i);
-            attrs.push_back(attr);
-            return 0;
-        }
-    }
-    return 1;
-}
-
-static int
-convert_xliff_to_ph(XMLNode* node, int* phID)
-{
-    int err = 0;
-    if (node->Type() == XMLNode::ELEMENT) {
-        if (node->Namespace() == XLIFF_XMLNS) {
-            g_tags.insert(node->Name());
-            node->SetName("", "ph");
-
-            err = rename_id_attribute(node);
-            if (err != 0) {
-                char name[30];
-                (*phID)++;
-                sprintf(name, "id-%d", *phID);
-                node->EditAttributes().push_back(XMLAttribute("", "name", name));
-                err = 0;
-            }
-        }
-        vector<XMLNode*>& children = node->EditChildren();
-        const size_t I = children.size();
-        for (size_t i=0; i<I; i++) {
-            err |= convert_xliff_to_ph(children[i], phID);
-        }
-    }
-    return err;
-}
-
-XMLNode*
-resource_to_xmb_msg(const StringResource& res)
-{
-    // the msg element
-    vector<XMLAttribute> attrs;
-    string name = res.pos.file;
-    name += ":";
-    name += res.TypedID();
-    attrs.push_back(XMLAttribute("", "name", name));
-    attrs.push_back(XMLAttribute("", "desc", strip_newlines(res.comment)));
-    attrs.push_back(XMLAttribute(XMLNS_XMLNS, "space", "preserve"));
-    XMLNode* msg = XMLNode::NewElement(res.pos, "", "msg", attrs, XMLNode::EXACT);
-
-    // the contents are in xliff/html, convert it to xliff
-    int err = 0;
-    XMLNode* value = res.value;
-    string tag = value->Name();
-    int phID = 0;
-    for (vector<XMLNode*>::const_iterator it=value->Children().begin();
-            it!=value->Children().end(); it++) {
-        err |= convert_html_to_xliff(*it, tag, msg, &phID);
-    }
-
-    if (err != 0) {
-        return NULL;
-    }
-
-    // and then convert that to xmb
-    for (vector<XMLNode*>::iterator it=msg->EditChildren().begin();
-            it!=msg->EditChildren().end(); it++) {
-        err |= convert_xliff_to_ph(*it, &phID);
-    }
-
-    if (err == 0) {
-        return msg;
-    } else {
-        return NULL;
-    }
-}
-
-int
-do_xlb_export(const string& outfile, const vector<string>& resFiles)
-{
-    int err = 0;
-
-    size_t totalFileCount = resFiles.size();
-
-    Configuration english;
-        english.locale = "en_US";
-
-    set<StringResource> allResources;
-
-    const size_t J = resFiles.size();
-    for (size_t j=0; j<J; j++) {
-        string resFile = resFiles[j];
-
-        ValuesFile* valuesFile = get_local_values_file(resFile, english, CURRENT_VERSION, "", true);
-        if (valuesFile != NULL) {
-            set<StringResource> resources = valuesFile->GetStrings();
-            allResources.insert(resources.begin(), resources.end());
-        } else {
-            fprintf(stderr, "error reading file %s\n", resFile.c_str());
-        }
-
-        delete valuesFile;
-    }
-
-    // Construct the XLB xml
-    vector<XMLAttribute> attrs;
-    attrs.push_back(XMLAttribute("", "locale", "en"));
-    XMLNode* localizationbundle = XMLNode::NewElement(GENERATED_POS, "", "localizationbundle",
-            attrs, XMLNode::PRETTY);
-
-    for (set<StringResource>::iterator it=allResources.begin(); it!=allResources.end(); it++) {
-        XMLNode* msg = resource_to_xmb_msg(*it);
-        if (msg) {
-            localizationbundle->EditChildren().push_back(msg);
-        } else {
-            err = 1;
-        }
-    }
-
-#if 0
-    for (set<string>::iterator it=g_tags.begin(); it!=g_tags.end(); it++) {
-        printf("tag: %s\n", it->c_str());
-    }
-    printf("err=%d\n", err);
-#endif
-    if (err == 0) {
-        FILE* f = fopen(outfile.c_str(), "wb");
-        if (f == NULL) {
-            fprintf(stderr, "can't open outputfile: %s\n", outfile.c_str());
-            return 1;
-        }
-        fprintf(f, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
-        fprintf(f, "%s\n", localizationbundle->ToString(NS_MAP).c_str());
-        fclose(f);
-    }
-
-    return err;
-}
-
diff --git a/tools/localize/xmb.h b/tools/localize/xmb.h
deleted file mode 100644
index 96492b1..0000000
--- a/tools/localize/xmb.h
+++ /dev/null
@@ -1,11 +0,0 @@
-#ifndef XMB_H
-#define XMB_H
-
-#include <string>
-#include <vector>
-
-using namespace std;
-
-int do_xlb_export(const string& outFile, const vector<string>& resFiles);
-
-#endif // XMB_H
diff --git a/tools/orientationplot/README.txt b/tools/orientationplot/README.txt
index 0143510..d53f65e 100644
--- a/tools/orientationplot/README.txt
+++ b/tools/orientationplot/README.txt
@@ -16,15 +16,15 @@
 The tool works by scaping the debug log output from WindowOrientationListener
 for interesting data and then plotting it.
 
-1. Enable the Window Orientation Listener debugging data log using the
-   Development Settings in the Dev Tools application (Development.apk).
-
-2. Plug in the device.  Ensure that it is the only device plugged in
+1. Plug in the device.  Ensure that it is the only device plugged in
    since this script is of very little brain and will get confused otherwise.
 
-3. Run "orientationplot.py".
+2. Enable the Window Orientation Listener debugging data log.
+   adb shell setprop debug.orientation.log true
+   adb shell stop
+   adb shell start
 
-4. When finished, remember to disable the debug log output since it is quite verbose!
+3. Run "orientationplot.py".
 
 
 WHAT IT ALL MEANS
diff --git a/tools/orientationplot/orientationplot.py b/tools/orientationplot/orientationplot.py
index f4e6b45..6fc3922 100755
--- a/tools/orientationplot/orientationplot.py
+++ b/tools/orientationplot/orientationplot.py
@@ -152,6 +152,7 @@
     self.time_until_settled = self._make_timeseries()
     self.time_until_flat_delay_expired = self._make_timeseries()
     self.time_until_swing_delay_expired = self._make_timeseries()
+    self.time_until_acceleration_delay_expired = self._make_timeseries()
     self.stability_axes = self._add_timeseries_axes(
         6, 'Proposal Stability', 'ms', [-10, 600],
         sharex=shared_axis,
@@ -162,6 +163,8 @@
         self.stability_axes, 'time until flat delay expired', 'green')
     self.time_until_swing_delay_expired_line = self._add_timeseries_line(
         self.stability_axes, 'time until swing delay expired', 'blue')
+    self.time_until_acceleration_delay_expired_line = self._add_timeseries_line(
+        self.stability_axes, 'time until acceleration delay expired', 'red')
     self._add_timeseries_legend(self.stability_axes)
 
     self.sample_latency = self._make_timeseries()
@@ -253,6 +256,7 @@
     self.parse_time_until_settled = None
     self.parse_time_until_flat_delay_expired = None
     self.parse_time_until_swing_delay_expired = None
+    self.parse_time_until_acceleration_delay_expired = None
     self.parse_sample_latency = None
 
   # Update samples.
@@ -303,6 +307,7 @@
         self.parse_time_until_settled = self._get_following_number(line, 'timeUntilSettledMS=')
         self.parse_time_until_flat_delay_expired = self._get_following_number(line, 'timeUntilFlatDelayExpiredMS=')
         self.parse_time_until_swing_delay_expired = self._get_following_number(line, 'timeUntilSwingDelayExpiredMS=')
+        self.parse_time_until_acceleration_delay_expired = self._get_following_number(line, 'timeUntilAccelerationDelayExpiredMS=')
 
         self._append(self.raw_acceleration_x, timeindex, self.parse_raw_acceleration_x)
         self._append(self.raw_acceleration_y, timeindex, self.parse_raw_acceleration_y)
@@ -326,6 +331,7 @@
         self._append(self.time_until_settled, timeindex, self.parse_time_until_settled)
         self._append(self.time_until_flat_delay_expired, timeindex, self.parse_time_until_flat_delay_expired)
         self._append(self.time_until_swing_delay_expired, timeindex, self.parse_time_until_swing_delay_expired)
+        self._append(self.time_until_acceleration_delay_expired, timeindex, self.parse_time_until_acceleration_delay_expired)
         self._append(self.sample_latency, timeindex, self.parse_sample_latency)
         self._reset_parse_state()
 
@@ -349,6 +355,7 @@
       self._scroll(self.time_until_settled, bottom)
       self._scroll(self.time_until_flat_delay_expired, bottom)
       self._scroll(self.time_until_swing_delay_expired, bottom)
+      self._scroll(self.time_until_acceleration_delay_expired, bottom)
       self._scroll(self.sample_latency, bottom)
 
     # Redraw the plots.
@@ -368,6 +375,7 @@
     self.time_until_settled_line.set_data(self.time_until_settled)
     self.time_until_flat_delay_expired_line.set_data(self.time_until_flat_delay_expired)
     self.time_until_swing_delay_expired_line.set_data(self.time_until_swing_delay_expired)
+    self.time_until_acceleration_delay_expired_line.set_data(self.time_until_acceleration_delay_expired)
     self.sample_latency_line.set_data(self.sample_latency)
 
     self.fig.canvas.draw_idle()