Merge "Support for correctly scaling text selection handles"
diff --git a/CleanSpec.mk b/CleanSpec.mk
index 7bab945..6ae887b 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -112,6 +112,7 @@
 $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/wifi/java)
 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/media/audio/)
 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/fonts/Lohit_Hindi.ttf)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/media/audio/)
 # ************************************************
 # NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
 # ************************************************
diff --git a/cmds/stagefright/sf2.cpp b/cmds/stagefright/sf2.cpp
index 6fa66cf..263ecd1 100644
--- a/cmds/stagefright/sf2.cpp
+++ b/cmds/stagefright/sf2.cpp
@@ -569,12 +569,16 @@
         CHECK(control->isValid());
 
         SurfaceComposerClient::openGlobalTransaction();
-        CHECK_EQ(control->setLayer(30000), (status_t)OK);
+        CHECK_EQ(control->setLayer(INT_MAX), (status_t)OK);
         CHECK_EQ(control->show(), (status_t)OK);
         SurfaceComposerClient::closeGlobalTransaction();
 
         surface = control->getSurface();
         CHECK(surface != NULL);
+
+        CHECK_EQ((status_t)OK,
+                 native_window_api_connect(
+                     surface.get(), NATIVE_WINDOW_API_MEDIA));
     }
 
     sp<Controller> controller =
@@ -589,6 +593,10 @@
     looper->unregisterHandler(controller->id());
 
     if (!decodeAudio && useSurface) {
+        CHECK_EQ((status_t)OK,
+                 native_window_api_disconnect(
+                     surface.get(), NATIVE_WINDOW_API_MEDIA));
+
         composerClient->dispose();
     }
 
diff --git a/cmds/stagefright/stagefright.cpp b/cmds/stagefright/stagefright.cpp
index a126e83..528d197 100644
--- a/cmds/stagefright/stagefright.cpp
+++ b/cmds/stagefright/stagefright.cpp
@@ -917,7 +917,7 @@
             CHECK(control->isValid());
 
             SurfaceComposerClient::openGlobalTransaction();
-            CHECK_EQ(control->setLayer(30000), (status_t)OK);
+            CHECK_EQ(control->setLayer(INT_MAX), (status_t)OK);
             CHECK_EQ(control->show(), (status_t)OK);
             SurfaceComposerClient::closeGlobalTransaction();
 
@@ -929,6 +929,10 @@
             sp<SurfaceTexture> texture = new SurfaceTexture(0 /* tex */);
             gSurface = new SurfaceTextureClient(texture);
         }
+
+        CHECK_EQ((status_t)OK,
+                 native_window_api_connect(
+                     gSurface.get(), NATIVE_WINDOW_API_MEDIA));
     }
 
     DataSource::RegisterDefaultSniffers();
@@ -1122,6 +1126,10 @@
     }
 
     if ((useSurfaceAlloc || useSurfaceTexAlloc) && !audioOnly) {
+        CHECK_EQ((status_t)OK,
+                 native_window_api_disconnect(
+                     gSurface.get(), NATIVE_WINDOW_API_MEDIA));
+
         gSurface.clear();
 
         if (useSurfaceAlloc) {
diff --git a/cmds/stagefright/stream.cpp b/cmds/stagefright/stream.cpp
index b13236a..2378345 100644
--- a/cmds/stagefright/stream.cpp
+++ b/cmds/stagefright/stream.cpp
@@ -323,7 +323,7 @@
     CHECK(control->isValid());
 
     SurfaceComposerClient::openGlobalTransaction();
-    CHECK_EQ(control->setLayer(30000), (status_t)OK);
+    CHECK_EQ(control->setLayer(INT_MAX), (status_t)OK);
     CHECK_EQ(control->show(), (status_t)OK);
     SurfaceComposerClient::closeGlobalTransaction();
 
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index 254c98f..ea5c3db 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -781,7 +781,7 @@
      * Get the current connection state of a profile.
      * This function can be used to check whether the local Bluetooth adapter
      * is connected to any remote device for a specific profile.
-     * Profile can be one of {@link BluetoothProfile#HEADSET},
+     * Profile can be one of {@link BluetoothProfile#HEALTH}, {@link BluetoothProfile#HEADSET},
      * {@link BluetoothProfile#A2DP}.
      *
      * <p>Requires {@link android.Manifest.permission#BLUETOOTH}.
@@ -1132,15 +1132,15 @@
     /**
      * Get the profile proxy object associated with the profile.
      *
-     * <p>Profile can be one of {@link BluetoothProfile#HEADSET} or
+     * <p>Profile can be one of {@link BluetoothProfile#HEALTH}, {@link BluetoothProfile#HEADSET} or
      * {@link BluetoothProfile#A2DP}. Clients must implements
      * {@link BluetoothProfile.ServiceListener} to get notified of
      * the connection status and to get the proxy object.
      *
      * @param context Context of the application
      * @param listener The service Listener for connection callbacks.
-     * @param profile The Bluetooth profile; either {@link BluetoothProfile#HEADSET}
-     *                or {@link BluetoothProfile#A2DP}.
+     * @param profile The Bluetooth profile; either {@link BluetoothProfile#HEALTH},
+     *                {@link BluetoothProfile#HEADSET} or {@link BluetoothProfile#A2DP}.
      * @return true on success, false on error
      */
     public boolean getProfileProxy(Context context, BluetoothProfile.ServiceListener listener,
@@ -1172,7 +1172,7 @@
      *
      * <p> Clients should call this when they are no longer using
      * the proxy obtained from {@link #getProfileProxy}.
-     * Profile can be one of {@link BluetoothProfile#HEADSET} or
+     * Profile can be one of  {@link BluetoothProfile#HEALTH}, {@link BluetoothProfile#HEADSET} or
      * {@link BluetoothProfile#A2DP}
      *
      * @param profile
diff --git a/core/java/android/bluetooth/BluetoothProfile.java b/core/java/android/bluetooth/BluetoothProfile.java
index f7ccfbd..1920efa 100644
--- a/core/java/android/bluetooth/BluetoothProfile.java
+++ b/core/java/android/bluetooth/BluetoothProfile.java
@@ -161,9 +161,9 @@
         /**
          * Called to notify the client when the proxy object has been
          * connected to the service.
-         * @param profile - One of {@link #HEADSET} or
+         * @param profile - One of {@link #HEALTH}, {@link #HEADSET} or
          *                  {@link #A2DP}
-         * @param proxy - One of {@link BluetoothHeadset} or
+         * @param proxy - One of {@link BluetoothHealth}, {@link BluetoothHeadset} or
          *                {@link BluetoothA2dp}
          */
         public void onServiceConnected(int profile, BluetoothProfile proxy);
@@ -171,7 +171,7 @@
         /**
          * Called to notify the client that this proxy object has been
          * disconnected from the service.
-         * @param profile - One of {@link #HEADSET} or
+         * @param profile - One of {@link #HEALTH}, {@link #HEADSET} or
          *                  {@link #A2DP}
          */
         public void onServiceDisconnected(int profile);
diff --git a/core/java/android/content/SyncManager.java b/core/java/android/content/SyncManager.java
index 684c4fe..127efa2 100644
--- a/core/java/android/content/SyncManager.java
+++ b/core/java/android/content/SyncManager.java
@@ -16,6 +16,26 @@
 
 package android.content;
 
+import com.android.internal.R;
+import com.android.internal.util.ArrayUtils;
+import com.google.android.collect.Lists;
+import com.google.android.collect.Maps;
+
+import android.accounts.Account;
+import android.accounts.AccountManager;
+import android.accounts.OnAccountsUpdateListener;
+import android.app.AlarmManager;
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ProviderInfo;
+import android.content.pm.RegisteredServicesCache;
+import android.content.pm.RegisteredServicesCacheListener;
+import android.content.pm.ResolveInfo;
+import android.net.ConnectivityManager;
+import android.net.NetworkInfo;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.HandlerThread;
@@ -27,27 +47,6 @@
 import android.os.RemoteException;
 import android.os.SystemClock;
 import android.os.SystemProperties;
-import com.google.android.collect.Lists;
-import com.google.android.collect.Maps;
-
-import com.android.internal.R;
-import com.android.internal.util.ArrayUtils;
-
-import android.accounts.Account;
-import android.accounts.AccountManager;
-import android.accounts.OnAccountsUpdateListener;
-import android.app.AlarmManager;
-import android.app.Notification;
-import android.app.NotificationManager;
-import android.app.PendingIntent;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
-import android.content.pm.RegisteredServicesCache;
-import android.content.pm.ProviderInfo;
-import android.content.pm.RegisteredServicesCacheListener;
-import android.net.ConnectivityManager;
-import android.net.NetworkInfo;
 import android.os.WorkSource;
 import android.provider.Settings;
 import android.text.format.DateUtils;
@@ -59,12 +58,15 @@
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.Comparator;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Map;
 import java.util.Random;
 import java.util.concurrent.CountDownLatch;
 
@@ -1006,9 +1008,8 @@
     }
 
     protected void dump(FileDescriptor fd, PrintWriter pw) {
-        StringBuilder sb = new StringBuilder();
-        dumpSyncState(pw, sb);
-        dumpSyncHistory(pw, sb);
+        dumpSyncState(pw);
+        dumpSyncHistory(pw);
 
         pw.println();
         pw.println("SyncAdapters:");
@@ -1023,7 +1024,7 @@
         return tobj.format("%Y-%m-%d %H:%M:%S");
     }
 
-    protected void dumpSyncState(PrintWriter pw, StringBuilder sb) {
+    protected void dumpSyncState(PrintWriter pw) {
         pw.print("data connected: "); pw.println(mDataConnectionIsConnected);
         pw.print("memory low: "); pw.println(mStorageIsLow);
 
@@ -1055,7 +1056,7 @@
         }
 
         pw.print("notification info: ");
-        sb.setLength(0);
+        final StringBuilder sb = new StringBuilder();
         mSyncHandler.mSyncNotificationInfo.toString(sb);
         pw.println(sb.toString());
 
@@ -1204,7 +1205,197 @@
         pw.println(")");
     }
 
-    protected void dumpSyncHistory(PrintWriter pw, StringBuilder sb) {
+    protected void dumpSyncHistory(PrintWriter pw) {
+        dumpRecentHistory(pw);
+        dumpDayStatistics(pw);
+    }
+
+    private void dumpRecentHistory(PrintWriter pw) {
+        final ArrayList<SyncStorageEngine.SyncHistoryItem> items
+                = mSyncStorageEngine.getSyncHistory();
+        if (items != null && items.size() > 0) {
+            final Map<String, AuthoritySyncStats> authorityMap = Maps.newHashMap();
+            long totalElapsedTime = 0;
+            long totalTimes = 0;
+            final int N = items.size();
+
+            int maxAuthority = 0;
+            int maxAccount = 0;
+            for (SyncStorageEngine.SyncHistoryItem item : items) {
+                SyncStorageEngine.AuthorityInfo authority
+                        = mSyncStorageEngine.getAuthority(item.authorityId);
+                final String authorityName;
+                final String accountKey;
+                if (authority != null) {
+                    authorityName = authority.authority;
+                    accountKey = authority.account.name + "/" + authority.account.type;
+                } else {
+                    authorityName = "Unknown";
+                    accountKey = "Unknown";
+                }
+
+                int length = authorityName.length();
+                if (length > maxAuthority) {
+                    maxAuthority = length;
+                }
+                length = accountKey.length();
+                if (length > maxAccount) {
+                    maxAccount = length;
+                }
+
+                final long elapsedTime = item.elapsedTime;
+                totalElapsedTime += elapsedTime;
+                totalTimes++;
+                AuthoritySyncStats authoritySyncStats = authorityMap.get(authorityName);
+                if (authoritySyncStats == null) {
+                    authoritySyncStats = new AuthoritySyncStats(authorityName);
+                    authorityMap.put(authorityName, authoritySyncStats);
+                }
+                authoritySyncStats.elapsedTime += elapsedTime;
+                authoritySyncStats.times++;
+                final Map<String, AccountSyncStats> accountMap = authoritySyncStats.accountMap;
+                AccountSyncStats accountSyncStats = accountMap.get(accountKey);
+                if (accountSyncStats == null) {
+                    accountSyncStats = new AccountSyncStats(accountKey);
+                    accountMap.put(accountKey, accountSyncStats);
+                }
+                accountSyncStats.elapsedTime += elapsedTime;
+                accountSyncStats.times++;
+
+            }
+
+            pw.println();
+            pw.printf("Detailed Statistics (Recent history):  %d (# of times) %ds (sync time)\n",
+                    totalTimes, totalElapsedTime / 1000);
+
+            final List<AuthoritySyncStats> sortedAuthorities =
+                    new ArrayList<AuthoritySyncStats>(authorityMap.values());
+            Collections.sort(sortedAuthorities, new Comparator<AuthoritySyncStats>() {
+                @Override
+                public int compare(AuthoritySyncStats lhs, AuthoritySyncStats rhs) {
+                    // reverse order
+                    int compare = Integer.compare(rhs.times, lhs.times);
+                    if (compare == 0) {
+                        compare = Long.compare(rhs.elapsedTime, lhs.elapsedTime);
+                    }
+                    return compare;
+                }
+            });
+
+            final int maxLength = Math.max(maxAuthority, maxAccount + 3);
+            final int padLength = 2 + 2 + maxLength + 2 + 10 + 11;
+            final char chars[] = new char[padLength];
+            Arrays.fill(chars, '-');
+            final String separator = new String(chars);
+
+            final String authorityFormat = String.format("  %%-%ds: %%-9s  %%-11s\n", maxLength + 2);
+            final String accountFormat = String.format("    %%-%ds:   %%-9s  %%-11s\n", maxLength);
+
+            pw.println(separator);
+            for (AuthoritySyncStats authoritySyncStats : sortedAuthorities) {
+                String name = authoritySyncStats.name;
+                long elapsedTime;
+                int times;
+                String timeStr;
+                String timesStr;
+
+                elapsedTime = authoritySyncStats.elapsedTime;
+                times = authoritySyncStats.times;
+                timeStr = String.format("%d/%d%%",
+                        elapsedTime / 1000,
+                        elapsedTime * 100 / totalElapsedTime);
+                timesStr = String.format("%d/%d%%",
+                        times,
+                        times * 100 / totalTimes);
+                pw.printf(authorityFormat, name, timesStr, timeStr);
+
+                if (authoritySyncStats.accountMap.size() > 1) {
+                    final List<AccountSyncStats> sortedAccounts =
+                            new ArrayList<AccountSyncStats>(
+                                    authoritySyncStats.accountMap.values());
+                    Collections.sort(sortedAccounts, new Comparator<AccountSyncStats>() {
+                        @Override
+                        public int compare(AccountSyncStats lhs, AccountSyncStats rhs) {
+                            // reverse order
+                            int compare = Integer.compare(rhs.times, lhs.times);
+                            if (compare == 0) {
+                                compare = Long.compare(rhs.elapsedTime, lhs.elapsedTime);
+                            }
+                            return compare;
+                        }
+                    });
+                    for (AccountSyncStats stats: sortedAccounts) {
+                        elapsedTime = stats.elapsedTime;
+                        times = stats.times;
+                        timeStr = String.format("%d/%d%%",
+                                elapsedTime / 1000,
+                                elapsedTime * 100 / totalElapsedTime);
+                        timesStr = String.format("%d/%d%%",
+                                times,
+                                times * 100 / totalTimes);
+                        pw.printf(accountFormat, stats.name, timesStr, timeStr);
+                    }
+                }
+                pw.println(separator);
+            }
+
+            pw.println();
+            pw.println("Recent Sync History");
+            final String format = "  %-" + maxAccount + "s  %s\n";
+            String lastAuthorityName = null;
+            String lastAccountKey = null;
+            long lastEventTime = 0;
+            for (int i = 0; i < N; i++) {
+                SyncStorageEngine.SyncHistoryItem item = items.get(i);
+                SyncStorageEngine.AuthorityInfo authority
+                        = mSyncStorageEngine.getAuthority(item.authorityId);
+                final String authorityName;
+                final String accountKey;
+                if (authority != null) {
+                    authorityName = authority.authority;
+                    accountKey = authority.account.name + "/" + authority.account.type;
+                } else {
+                    authorityName = "Unknown";
+                    accountKey = "Unknown";
+                }
+                final long elapsedTime = item.elapsedTime;
+                final Time time = new Time();
+                final long eventTime = item.eventTime;
+                time.set(eventTime);
+
+                pw.printf("  #%-3d: %s %8s  %5.1fs",
+                        i + 1,
+                        formatTime(eventTime),
+                        SyncStorageEngine.SOURCES[item.source],
+                        ((float) elapsedTime) / 1000);
+                if (authorityName.equals(lastAuthorityName) && accountKey.equals(lastAccountKey)) {
+                    final long span = (lastEventTime - eventTime) / 1000;
+                    pw.printf("  %02d:%02d\n", span / 60, span % 60);
+                } else {
+                    pw.printf(format, accountKey, authorityName);
+                }
+
+                lastAuthorityName = authorityName;
+                lastAccountKey = accountKey;
+                lastEventTime = eventTime;
+
+                if (item.event != SyncStorageEngine.EVENT_STOP
+                        || item.upstreamActivity != 0
+                        || item.downstreamActivity != 0) {
+                    pw.printf("    event=%d upstreamActivity=%d downstreamActivity=%d\n",
+                            item.event,
+                            item.upstreamActivity,
+                            item.downstreamActivity);
+                }
+                if (item.mesg != null
+                        && !SyncStorageEngine.MESG_SUCCESS.equals(item.mesg)) {
+                    pw.printf("    mesg=%s\n", item.mesg);
+                }
+            }
+        }
+    }
+
+    private void dumpDayStatistics(PrintWriter pw) {
         SyncStorageEngine.DayStats dses[] = mSyncStorageEngine.getDayStatistics();
         if (dses != null && dses[0] != null) {
             pw.println();
@@ -1254,47 +1445,26 @@
                 }
             }
         }
+    }
 
-        ArrayList<SyncStorageEngine.SyncHistoryItem> items
-                = mSyncStorageEngine.getSyncHistory();
-        if (items != null && items.size() > 0) {
-            pw.println();
-            pw.println("Recent Sync History");
-            final int N = items.size();
-            for (int i=0; i<N; i++) {
-                SyncStorageEngine.SyncHistoryItem item = items.get(i);
-                SyncStorageEngine.AuthorityInfo authority
-                        = mSyncStorageEngine.getAuthority(item.authorityId);
-                pw.print("  #"); pw.print(i+1); pw.print(": ");
-                        if (authority != null) {
-                            pw.print(authority.account.name);
-                            pw.print(":");
-                            pw.print(authority.account.type);
-                            pw.print(" ");
-                            pw.print(authority.authority);
-                        } else {
-                            pw.print("<no account>");
-                        }
-                Time time = new Time();
-                time.set(item.eventTime);
-                pw.print(" "); pw.print(SyncStorageEngine.SOURCES[item.source]);
-                        pw.print(" @ ");
-                        pw.print(formatTime(item.eventTime));
-                        pw.print(" for ");
-                        dumpTimeSec(pw, item.elapsedTime);
-                        pw.println();
-                if (item.event != SyncStorageEngine.EVENT_STOP
-                        || item.upstreamActivity !=0
-                        || item.downstreamActivity != 0) {
-                    pw.print("    event="); pw.print(item.event);
-                            pw.print(" upstreamActivity="); pw.print(item.upstreamActivity);
-                            pw.print(" downstreamActivity="); pw.println(item.downstreamActivity);
-                }
-                if (item.mesg != null
-                        && !SyncStorageEngine.MESG_SUCCESS.equals(item.mesg)) {
-                    pw.print("    mesg="); pw.println(item.mesg);
-                }
-            }
+    private static class AuthoritySyncStats {
+        String name;
+        long elapsedTime;
+        int times;
+        Map<String, AccountSyncStats> accountMap = Maps.newHashMap();
+
+        private AuthoritySyncStats(String name) {
+            this.name = name;
+        }
+    }
+
+    private static class AccountSyncStats {
+        String name;
+        long elapsedTime;
+        int times;
+
+        private AccountSyncStats(String name) {
+            this.name = name;
         }
     }
 
diff --git a/core/java/android/content/pm/PackageInfoLite.java b/core/java/android/content/pm/PackageInfoLite.java
index da97fde0..9625944 100644
--- a/core/java/android/content/pm/PackageInfoLite.java
+++ b/core/java/android/content/pm/PackageInfoLite.java
@@ -41,6 +41,8 @@
     public int recommendedInstallLocation;
     public int installLocation;
 
+    public VerifierInfo[] verifiers;
+
     public PackageInfoLite() {
     }
 
@@ -58,6 +60,13 @@
         dest.writeString(packageName);
         dest.writeInt(recommendedInstallLocation);
         dest.writeInt(installLocation);
+
+        if (verifiers == null || verifiers.length == 0) {
+            dest.writeInt(0);
+        } else {
+            dest.writeInt(verifiers.length);
+            dest.writeTypedArray(verifiers, parcelableFlags);
+        }
     }
 
     public static final Parcelable.Creator<PackageInfoLite> CREATOR
@@ -75,5 +84,13 @@
         packageName = source.readString();
         recommendedInstallLocation = source.readInt();
         installLocation = source.readInt();
+
+        final int verifiersLength = source.readInt();
+        if (verifiersLength == 0) {
+            verifiers = new VerifierInfo[0];
+        } else {
+            verifiers = new VerifierInfo[verifiersLength];
+            source.readTypedArray(verifiers, VerifierInfo.CREATOR);
+        }
     }
 }
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index ef7e233..7a7e4f4 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -725,6 +725,16 @@
     public static final int MOVE_EXTERNAL_MEDIA = 0x00000002;
 
     /**
+     * Usable by the required verifier as the {@code verificationCode} argument
+     * for {@link PackageManager#verifyPendingInstall} to indicate that it will
+     * allow the installation to proceed without any of the optional verifiers
+     * needing to vote.
+     *
+     * @hide
+     */
+    public static final int VERIFICATION_ALLOW_WITHOUT_SUFFICIENT = 2;
+
+    /**
      * Used as the {@code verificationCode} argument for
      * {@link PackageManager#verifyPendingInstall} to indicate that the calling
      * package verifier allows the installation to proceed.
@@ -2527,6 +2537,7 @@
      * {@link #COMPONENT_ENABLED_STATE_DEFAULT}.  The last one means the
      * application's enabled state is based on the original information in
      * the manifest as found in {@link ComponentInfo}.
+     * @throws IllegalArgumentException if the named package does not exist.
      */
     public abstract int getApplicationEnabledSetting(String packageName);
 
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index e7b844c..c30675b 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -28,7 +28,9 @@
 import android.os.Bundle;
 import android.os.PatternMatcher;
 import android.util.AttributeSet;
+import android.util.Base64;
 import android.util.DisplayMetrics;
+import android.util.Log;
 import android.util.Slog;
 import android.util.TypedValue;
 import com.android.internal.util.XmlUtils;
@@ -40,11 +42,18 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.lang.ref.WeakReference;
+import java.security.KeyFactory;
+import java.security.NoSuchAlgorithmException;
+import java.security.PublicKey;
 import java.security.cert.Certificate;
 import java.security.cert.CertificateEncodingException;
+import java.security.spec.EncodedKeySpec;
+import java.security.spec.InvalidKeySpecException;
+import java.security.spec.X509EncodedKeySpec;
 import java.util.ArrayList;
 import java.util.Enumeration;
 import java.util.Iterator;
+import java.util.List;
 import java.util.jar.Attributes;
 import java.util.jar.JarEntry;
 import java.util.jar.JarFile;
@@ -150,12 +159,14 @@
      * @hide
      */
     public static class PackageLite {
-        public String packageName;
-        public int installLocation;
-        public String mScanPath;
-        public PackageLite(String packageName, int installLocation) {
+        public final String packageName;
+        public final int installLocation;
+        public final VerifierInfo[] verifiers;
+
+        public PackageLite(String packageName, int installLocation, List<VerifierInfo> verifiers) {
             this.packageName = packageName;
             this.installLocation = installLocation;
+            this.verifiers = verifiers.toArray(new VerifierInfo[verifiers.size()]);
         }
     }
 
@@ -619,8 +630,9 @@
      * @return PackageLite object with package information or null on failure.
      */
     public static PackageLite parsePackageLite(String packageFilePath, int flags) {
-        XmlResourceParser parser = null;
         AssetManager assmgr = null;
+        final XmlResourceParser parser;
+        final Resources res;
         try {
             assmgr = new AssetManager();
             assmgr.setConfiguration(0, 0, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
@@ -631,6 +643,9 @@
                 return null;
             }
 
+            final DisplayMetrics metrics = new DisplayMetrics();
+            metrics.setToDefaults();
+            res = new Resources(assmgr, metrics, null);
             parser = assmgr.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME);
         } catch (Exception e) {
             if (assmgr != null) assmgr.close();
@@ -638,11 +653,12 @@
                     + packageFilePath, e);
             return null;
         }
-        AttributeSet attrs = parser;
-        String errors[] = new String[1];
+
+        final AttributeSet attrs = parser;
+        final String errors[] = new String[1];
         PackageLite packageLite = null;
         try {
-            packageLite = parsePackageLite(parser, attrs, flags, errors);
+            packageLite = parsePackageLite(res, parser, attrs, flags, errors);
         } catch (IOException e) {
             Slog.w(TAG, packageFilePath, e);
         } catch (XmlPullParserException e) {
@@ -719,9 +735,9 @@
         return pkgName.intern();
     }
 
-    private static PackageLite parsePackageLite(XmlPullParser parser,
-            AttributeSet attrs, int flags, String[] outError)
-            throws IOException, XmlPullParserException {
+    private static PackageLite parsePackageLite(Resources res, XmlPullParser parser,
+            AttributeSet attrs, int flags, String[] outError) throws IOException,
+            XmlPullParserException {
 
         int type;
         while ((type = parser.next()) != XmlPullParser.START_TAG
@@ -759,7 +775,26 @@
                 break;
             }
         }
-        return new PackageLite(pkgName.intern(), installLocation);
+
+        // Only search the tree when the tag is directly below <manifest>
+        final int searchDepth = parser.getDepth() + 1;
+
+        final List<VerifierInfo> verifiers = new ArrayList<VerifierInfo>();
+        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+                && (type != XmlPullParser.END_TAG || parser.getDepth() >= searchDepth)) {
+            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
+                continue;
+            }
+
+            if (parser.getDepth() == searchDepth && "package-verifier".equals(parser.getName())) {
+                final VerifierInfo verifier = parseVerifier(res, parser, attrs, flags, outError);
+                if (verifier != null) {
+                    verifiers.add(verifier);
+                }
+            }
+        }
+
+        return new PackageLite(pkgName.intern(), installLocation, verifiers);
     }
 
     /**
@@ -2691,6 +2726,63 @@
         return data;
     }
 
+    private static VerifierInfo parseVerifier(Resources res, XmlPullParser parser,
+            AttributeSet attrs, int flags, String[] outError) throws XmlPullParserException,
+            IOException {
+        final TypedArray sa = res.obtainAttributes(attrs,
+                com.android.internal.R.styleable.AndroidManifestPackageVerifier);
+
+        final String packageName = sa.getNonResourceString(
+                com.android.internal.R.styleable.AndroidManifestPackageVerifier_name);
+
+        final String encodedPublicKey = sa.getNonResourceString(
+                com.android.internal.R.styleable.AndroidManifestPackageVerifier_publicKey);
+
+        sa.recycle();
+
+        if (packageName == null || packageName.length() == 0) {
+            Slog.i(TAG, "verifier package name was null; skipping");
+            return null;
+        } else if (encodedPublicKey == null) {
+            Slog.i(TAG, "verifier " + packageName + " public key was null; skipping");
+        }
+
+        EncodedKeySpec keySpec;
+        try {
+            final byte[] encoded = Base64.decode(encodedPublicKey, Base64.DEFAULT);
+            keySpec = new X509EncodedKeySpec(encoded);
+        } catch (IllegalArgumentException e) {
+            Slog.i(TAG, "Could not parse verifier " + packageName + " public key; invalid Base64");
+            return null;
+        }
+
+        /* First try the key as an RSA key. */
+        try {
+            final KeyFactory keyFactory = KeyFactory.getInstance("RSA");
+            final PublicKey publicKey = keyFactory.generatePublic(keySpec);
+            return new VerifierInfo(packageName, publicKey);
+        } catch (NoSuchAlgorithmException e) {
+            Log.wtf(TAG, "Could not parse public key because RSA isn't included in build");
+            return null;
+        } catch (InvalidKeySpecException e) {
+            // Not a RSA public key.
+        }
+
+        /* Now try it as a DSA key. */
+        try {
+            final KeyFactory keyFactory = KeyFactory.getInstance("DSA");
+            final PublicKey publicKey = keyFactory.generatePublic(keySpec);
+            return new VerifierInfo(packageName, publicKey);
+        } catch (NoSuchAlgorithmException e) {
+            Log.wtf(TAG, "Could not parse public key because DSA isn't included in build");
+            return null;
+        } catch (InvalidKeySpecException e) {
+            // Not a DSA public key.
+        }
+
+        return null;
+    }
+
     private static final String ANDROID_RESOURCES
             = "http://schemas.android.com/apk/res/android";
 
diff --git a/core/java/android/content/pm/Signature.java b/core/java/android/content/pm/Signature.java
index c6aefb8..9c9340d 100644
--- a/core/java/android/content/pm/Signature.java
+++ b/core/java/android/content/pm/Signature.java
@@ -19,7 +19,12 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 
+import java.io.ByteArrayInputStream;
 import java.lang.ref.SoftReference;
+import java.security.PublicKey;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
 import java.util.Arrays;
 
 /**
@@ -135,6 +140,20 @@
         return bytes;
     }
 
+    /**
+     * Returns the public key for this signature.
+     *
+     * @throws CertificateException when Signature isn't a valid X.509
+     *             certificate; shouldn't happen.
+     * @hide
+     */
+    public PublicKey getPublicKey() throws CertificateException {
+        final CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
+        final ByteArrayInputStream bais = new ByteArrayInputStream(mSignature);
+        final Certificate cert = certFactory.generateCertificate(bais);
+        return cert.getPublicKey();
+    }
+
     @Override
     public boolean equals(Object obj) {
         try {
diff --git a/core/java/android/content/pm/VerifierInfo.aidl b/core/java/android/content/pm/VerifierInfo.aidl
new file mode 100644
index 0000000..7702d38
--- /dev/null
+++ b/core/java/android/content/pm/VerifierInfo.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2011, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.content.pm;
+
+parcelable VerifierInfo;
diff --git a/core/java/android/content/pm/VerifierInfo.java b/core/java/android/content/pm/VerifierInfo.java
new file mode 100644
index 0000000..0a2b283
--- /dev/null
+++ b/core/java/android/content/pm/VerifierInfo.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.content.pm;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.security.PublicKey;
+
+/**
+ * Contains information about a package verifier as used by
+ * {@code PackageManagerService} during package verification.
+ *
+ * @hide
+ */
+public class VerifierInfo implements Parcelable {
+    /** Package name of the verifier. */
+    public final String packageName;
+
+    /** Signatures used to sign the package verifier's package. */
+    public final PublicKey publicKey;
+
+    /**
+     * Creates an object that represents a verifier info object.
+     *
+     * @param packageName the package name in Java-style. Must not be {@code
+     *            null} or empty.
+     * @param publicKey the public key for the signer encoded in Base64. Must
+     *            not be {@code null} or empty.
+     * @throws IllegalArgumentException if either argument is null or empty.
+     */
+    public VerifierInfo(String packageName, PublicKey publicKey) {
+        if (packageName == null || packageName.length() == 0) {
+            throw new IllegalArgumentException("packageName must not be null or empty");
+        } else if (publicKey == null) {
+            throw new IllegalArgumentException("publicKey must not be null");
+        }
+
+        this.packageName = packageName;
+        this.publicKey = publicKey;
+    }
+
+    private VerifierInfo(Parcel source) {
+        packageName = source.readString();
+        publicKey = (PublicKey) source.readSerializable();
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeString(packageName);
+        dest.writeSerializable(publicKey);
+    }
+
+    public static final Parcelable.Creator<VerifierInfo> CREATOR
+            = new Parcelable.Creator<VerifierInfo>() {
+        public VerifierInfo createFromParcel(Parcel source) {
+            return new VerifierInfo(source);
+        }
+
+        public VerifierInfo[] newArray(int size) {
+            return new VerifierInfo[size];
+        }
+    };
+}
\ No newline at end of file
diff --git a/core/java/android/net/NetworkTemplate.java b/core/java/android/net/NetworkTemplate.java
index cd49023..418b82f 100644
--- a/core/java/android/net/NetworkTemplate.java
+++ b/core/java/android/net/NetworkTemplate.java
@@ -19,14 +19,15 @@
 import static android.net.ConnectivityManager.TYPE_ETHERNET;
 import static android.net.ConnectivityManager.TYPE_WIFI;
 import static android.net.ConnectivityManager.TYPE_WIMAX;
-import static android.net.ConnectivityManager.isNetworkTypeMobile;
 import static android.net.NetworkIdentity.scrubSubscriberId;
 import static android.telephony.TelephonyManager.NETWORK_CLASS_2_G;
 import static android.telephony.TelephonyManager.NETWORK_CLASS_3_G;
 import static android.telephony.TelephonyManager.NETWORK_CLASS_4_G;
 import static android.telephony.TelephonyManager.NETWORK_CLASS_UNKNOWN;
 import static android.telephony.TelephonyManager.getNetworkClass;
+import static com.android.internal.util.ArrayUtils.contains;
 
+import android.content.res.Resources;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -52,6 +53,16 @@
     public static final int MATCH_ETHERNET = 5;
 
     /**
+     * Set of {@link NetworkInfo#getType()} that reflect data usage.
+     */
+    private static final int[] DATA_USAGE_NETWORK_TYPES;
+
+    static {
+        DATA_USAGE_NETWORK_TYPES = Resources.getSystem().getIntArray(
+                com.android.internal.R.array.config_data_usage_network_types);
+    }
+
+    /**
      * Template to combine all {@link ConnectivityManager#TYPE_MOBILE} style
      * networks together. Only uses statistics for requested IMSI.
      */
@@ -151,7 +162,7 @@
     }
 
     /**
-     * Test if this network matches the given template and IMSI.
+     * Test if given {@link NetworkIdentity} matches this template.
      */
     public boolean matches(NetworkIdentity ident) {
         switch (mMatchRule) {
@@ -171,23 +182,25 @@
     }
 
     /**
-     * Check if mobile network with matching IMSI. Also matches
-     * {@link #TYPE_WIMAX}.
+     * Check if mobile network with matching IMSI.
      */
     private boolean matchesMobile(NetworkIdentity ident) {
-        if (isNetworkTypeMobile(ident.mType) && Objects.equal(mSubscriberId, ident.mSubscriberId)) {
+        if (ident.mType == TYPE_WIMAX) {
+            // TODO: consider matching against WiMAX subscriber identity
             return true;
-        } else if (ident.mType == TYPE_WIMAX) {
-            return true;
+        } else {
+            return (contains(DATA_USAGE_NETWORK_TYPES, ident.mType)
+                    && Objects.equal(mSubscriberId, ident.mSubscriberId));
         }
-        return false;
     }
 
     /**
      * Check if mobile network classified 3G or lower with matching IMSI.
      */
     private boolean matchesMobile3gLower(NetworkIdentity ident) {
-        if (isNetworkTypeMobile(ident.mType) && Objects.equal(mSubscriberId, ident.mSubscriberId)) {
+        if (ident.mType == TYPE_WIMAX) {
+            return false;
+        } else if (matchesMobile(ident)) {
             switch (getNetworkClass(ident.mSubType)) {
                 case NETWORK_CLASS_UNKNOWN:
                 case NETWORK_CLASS_2_G:
@@ -199,17 +212,17 @@
     }
 
     /**
-     * Check if mobile network classified 4G with matching IMSI. Also matches
-     * {@link #TYPE_WIMAX}.
+     * Check if mobile network classified 4G with matching IMSI.
      */
     private boolean matchesMobile4g(NetworkIdentity ident) {
-        if (isNetworkTypeMobile(ident.mType) && Objects.equal(mSubscriberId, ident.mSubscriberId)) {
+        if (ident.mType == TYPE_WIMAX) {
+            // TODO: consider matching against WiMAX subscriber identity
+            return true;
+        } else if (matchesMobile(ident)) {
             switch (getNetworkClass(ident.mSubType)) {
                 case NETWORK_CLASS_4_G:
                     return true;
             }
-        } else if (ident.mType == TYPE_WIMAX) {
-            return true;
         }
         return false;
     }
diff --git a/core/java/android/nfc/NfcAdapter.java b/core/java/android/nfc/NfcAdapter.java
index e392bca..fe0106d 100644
--- a/core/java/android/nfc/NfcAdapter.java
+++ b/core/java/android/nfc/NfcAdapter.java
@@ -208,7 +208,9 @@
     final NfcActivityManager mNfcActivityManager;
 
     /**
-     * @see {@link #setNdefPushMessageCallback}
+     * A callback to be invoked when the system successfully delivers your {@link NdefMessage}
+     * to another device.
+     * @see #setOnNdefPushCompleteCallback
      */
     public interface OnNdefPushCompleteCallback {
         /**
@@ -217,13 +219,21 @@
          * <p>This callback is usually made on a binder thread (not the UI thread).
          *
          * @param event {@link NfcEvent} with the {@link NfcEvent#nfcAdapter} field set
-         * @see {@link #setNdefPushMessageCallback}
+         * @see #setNdefPushMessageCallback
          */
         public void onNdefPushComplete(NfcEvent event);
     }
 
     /**
-     * @see {@link #setCeateNdefMessageCallback}
+     * A callback to be invoked when another NFC device capable of NDEF push (Android Beam)
+     * is within range.
+     * <p>Implement this interface and pass it to {@link
+     * NfcAdapter#setNdefPushMessageCallback setNdefPushMessageCallback()} in order to create an
+     * {@link NdefMessage} at the moment that another device is within range for NFC. Using this
+     * callback allows you to create a message with data that might vary based on the
+     * content currently visible to the user. Alternatively, you can call {@link
+     * #setNdefPushMessage setNdefPushMessage()} if the {@link NdefMessage} always contains the
+     * same data.
      */
     public interface CreateNdefMessageCallback {
         /**
@@ -507,13 +517,15 @@
      * <p>Pass a null NDEF message to disable foreground NDEF push in the
      * specified activities.
      *
-     * <p>One or more activities must be specified.
+     * <p>At least one activity must be specified, and usually only one is necessary.
      *
      * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission.
      *
      * @param message NDEF message to push over NFC, or null to disable
-     * @param activity an activity to enable for NDEF push (at least one is required)
-     * @param activities zero or more additional activities to enable for NDEF Push
+     * @param activity an activity in which NDEF push should be enabled to share the provided
+     *                 NDEF message
+     * @param activities optional additional activities that should also enable NDEF push with
+     *                   the provided NDEF message
      */
     public void setNdefPushMessage(NdefMessage message, Activity activity,
             Activity ... activities) {
@@ -544,13 +556,15 @@
      * <p>Pass a null callback to disable the callback in the
      * specified activities.
      *
-     * <p>One or more activities must be specified.
+     * <p>At least one activity must be specified, and usually only one is necessary.
      *
      * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission.
      *
      * @param callback callback, or null to disable
-     * @param activity an activity to enable for NDEF push (at least one is required)
-     * @param activities zero or more additional activities to enable for NDEF Push
+     * @param activity an activity in which NDEF push should be enabled to share an NDEF message
+     *                 that's retrieved from the provided callback
+     * @param activities optional additional activities that should also enable NDEF push using
+     *                   the provided callback
      */
     public void setNdefPushMessageCallback(CreateNdefMessageCallback callback, Activity activity,
             Activity ... activities) {
diff --git a/core/java/android/nfc/NfcEvent.java b/core/java/android/nfc/NfcEvent.java
index b00d8b7..860700a 100644
--- a/core/java/android/nfc/NfcEvent.java
+++ b/core/java/android/nfc/NfcEvent.java
@@ -29,8 +29,8 @@
  * in the callback) because it allows new fields to be added without breaking
  * API compatibility.
  *
- * @see {@link NfcAdapter.OnNdefPushCompleteCallback#onNdefPushComplete}
- * @see {@link NfcAdapter.CreateNdefMessageCallback#createNdefMessage}
+ * @see NfcAdapter.OnNdefPushCompleteCallback#onNdefPushComplete
+ * @see NfcAdapter.CreateNdefMessageCallback#createNdefMessage
  */
 public final class NfcEvent {
     /**
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index ca1d0d9..fb119b3 100644
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -2983,8 +2983,9 @@
      * long streamItemId = ContentUris.parseId(streamItemUri);
      * </pre>
      * </dd>
-     * <dt>Via the {@link StreamItems#CONTENT_URI} URI:</dt>
+     * <dt>Via {@link StreamItems#CONTENT_URI}:</dt>
      * <dd>
+     *<pre>
      * ContentValues values = new ContentValues();
      * values.put(StreamItems.RAW_CONTACT_ID, rawContactId);
      * values.put(StreamItems.TEXT, "Breakfasted at Tiffanys");
@@ -2992,6 +2993,7 @@
      * values.put(StreamItems.COMMENTS, "3 people reshared this");
      * Uri streamItemUri = getContentResolver().insert(StreamItems.CONTENT_URI, values);
      * long streamItemId = ContentUris.parseId(streamItemUri);
+     *</pre>
      * </dd>
      * </dl>
      * </dd>
@@ -3012,7 +3014,7 @@
      *     StreamItems.StreamItemPhotos.CONTENT_DIRECTORY), values);
      * </pre>
      * </dd>
-     * <dt>Via {@link ContactsContract.StreamItems#CONTENT_PHOTO_URI}</dt>
+     * <dt>Via {@link ContactsContract.StreamItems#CONTENT_PHOTO_URI}:</dt>
      * <dd>
      * <pre>
      * values.clear();
@@ -3021,7 +3023,7 @@
      * values.put(StreamItemPhotos.PHOTO, photoData);
      * getContentResolver().insert(StreamItems.CONTENT_PHOTO_URI, values);
      * </pre>
-     * Note that this latter form allows the insertion of a stream item and its
+     * <p>Note that this latter form allows the insertion of a stream item and its
      * photos in a single transaction, by using {@link ContentProviderOperation} with
      * back references to populate the stream item ID in the {@link ContentValues}.
      * </dd>
diff --git a/core/java/android/text/DynamicLayout.java b/core/java/android/text/DynamicLayout.java
index 2f9852d..f82c9c4 100644
--- a/core/java/android/text/DynamicLayout.java
+++ b/core/java/android/text/DynamicLayout.java
@@ -275,7 +275,7 @@
         }
 
         if (reflowed == null) {
-            reflowed = new StaticLayout(getText());
+            reflowed = new StaticLayout(null);
         } else {
             reflowed.prepare();
         }
@@ -488,7 +488,7 @@
 
     private int mTopPadding, mBottomPadding;
 
-    private static StaticLayout sStaticLayout = null;
+    private static StaticLayout sStaticLayout = new StaticLayout(null);
 
     private static final Object[] sLock = new Object[0];
 
diff --git a/core/java/android/text/SpannableStringBuilder.java b/core/java/android/text/SpannableStringBuilder.java
index 5fed775..fdbec20 100644
--- a/core/java/android/text/SpannableStringBuilder.java
+++ b/core/java/android/text/SpannableStringBuilder.java
@@ -709,8 +709,6 @@
         T ret1 = null;
 
         for (int i = 0; i < spanCount; i++) {
-            if (!kind.isInstance(spans[i])) continue;
-
             int spanStart = starts[i];
             int spanEnd = ends[i];
 
@@ -735,6 +733,9 @@
                     continue;
             }
 
+            // Expensive test, should be performed after the previous tests
+            if (!kind.isInstance(spans[i])) continue;
+
             if (count == 0) {
                 // Safe conversion thanks to the isInstance test above
                 ret1 = (T) spans[i];
diff --git a/core/java/android/text/StaticLayout.java b/core/java/android/text/StaticLayout.java
index e8b2045..583cbe6 100644
--- a/core/java/android/text/StaticLayout.java
+++ b/core/java/android/text/StaticLayout.java
@@ -763,7 +763,8 @@
             return;
         }
 
-        float ellipsisWidth = paint.measureText(HORIZONTAL_ELLIPSIS);
+        float ellipsisWidth = paint.measureText(
+                (where == TextUtils.TruncateAt.END_SMALL) ? ELLIPSIS_TWO_DOTS : ELLIPSIS_NORMAL);
         int ellipsisStart = 0;
         int ellipsisCount = 0;
         int len = lineEnd - lineStart;
@@ -791,7 +792,8 @@
                     Log.w(TAG, "Start Ellipsis only supported with one line");
                 }
             }
-        } else if (where == TextUtils.TruncateAt.END || where == TextUtils.TruncateAt.MARQUEE) {
+        } else if (where == TextUtils.TruncateAt.END || where == TextUtils.TruncateAt.MARQUEE ||
+                where == TextUtils.TruncateAt.END_SMALL) {
             float sum = 0;
             int i;
 
@@ -1001,7 +1003,9 @@
     private static final char CHAR_HYPHEN = '-';
 
     private static final double EXTRA_ROUNDING = 0.5;
-    private static final String HORIZONTAL_ELLIPSIS = "\u2026"; // this is "..."
+
+    private static final String ELLIPSIS_NORMAL = "\u2026"; // this is "..."
+    private static final String ELLIPSIS_TWO_DOTS = "\u2025"; // this is ".."
 
     private static final int CHAR_FIRST_HIGH_SURROGATE = 0xD800;
     private static final int CHAR_LAST_LOW_SURROGATE = 0xDFFF;
diff --git a/core/java/android/text/TextLine.java b/core/java/android/text/TextLine.java
index 1e17632..68fea19 100644
--- a/core/java/android/text/TextLine.java
+++ b/core/java/android/text/TextLine.java
@@ -30,6 +30,8 @@
 
 import com.android.internal.util.ArrayUtils;
 
+import java.lang.reflect.Array;
+
 /**
  * Represents a line of styled text, for measuring in visual order and
  * for rendering.
@@ -850,6 +852,73 @@
         return runIsRtl ? -ret : ret;
     }
 
+    private static class SpanSet<E> {
+        final int numberOfSpans;
+        final E[] spans;
+        final int[] spanStarts;
+        final int[] spanEnds;
+        final int[] spanFlags;
+
+        @SuppressWarnings("unchecked")
+        SpanSet(Spanned spanned, int start, int limit, Class<? extends E> type) {
+            final E[] allSpans = spanned.getSpans(start, limit, type);
+            final int length = allSpans.length;
+            // These arrays may end up being too large because of empty spans
+            spans = (E[]) Array.newInstance(type, length);
+            spanStarts = new int[length];
+            spanEnds = new int[length];
+            spanFlags = new int[length];
+
+            int count = 0;
+            for (int i = 0; i < length; i++) {
+                final E span = allSpans[i];
+
+                final int spanStart = spanned.getSpanStart(span);
+                final int spanEnd = spanned.getSpanEnd(span);
+                if (spanStart == spanEnd) continue;
+
+                final int spanFlag = spanned.getSpanFlags(span);
+                final int priority = spanFlag & Spanned.SPAN_PRIORITY;
+                if (priority != 0 && count != 0) {
+                    int j;
+
+                    for (j = 0; j < count; j++) {
+                        final int otherPriority = spanFlags[j] & Spanned.SPAN_PRIORITY;
+                        if (priority > otherPriority) break;
+                    }
+
+                    System.arraycopy(spans, j, spans, j + 1, count - j);
+                    System.arraycopy(spanStarts, j, spanStarts, j + 1, count - j);
+                    System.arraycopy(spanEnds, j, spanEnds, j + 1, count - j);
+                    System.arraycopy(spanFlags, j, spanFlags, j + 1, count - j);
+
+                    spans[j] = span;
+                    spanStarts[j] = spanStart;
+                    spanEnds[j] = spanEnd;
+                    spanFlags[j] = spanFlag;
+                } else {
+                    spans[i] = span;
+                    spanStarts[i] = spanStart;
+                    spanEnds[i] = spanEnd;
+                    spanFlags[i] = spanFlag;
+                }
+
+                count++;
+            }
+            numberOfSpans = count;
+        }
+
+        int getNextTransition(int start, int limit) {
+            for (int i = 0; i < numberOfSpans; i++) {
+                final int spanStart = spanStarts[i];
+                final int spanEnd = spanEnds[i];
+                if (spanStart > start && spanStart < limit) limit = spanStart;
+                if (spanEnd > start && spanEnd < limit) limit = spanEnd;
+            }
+            return limit;
+        }
+    }
+
     /**
      * Utility function for handling a unidirectional run.  The run must not
      * contain tabs or emoji but can contain styles.
@@ -883,66 +952,70 @@
             return 0f;
         }
 
+        if (mSpanned == null) {
+            TextPaint wp = mWorkPaint;
+            wp.set(mPaint);
+            final int mlimit = measureLimit;
+            return handleText(wp, start, mlimit, start, limit, runIsRtl, c, x, top,
+                    y, bottom, fmi, needWidth || mlimit < measureLimit);
+        }
+
+        final SpanSet<MetricAffectingSpan> metricAffectingSpans = new SpanSet<MetricAffectingSpan>(
+                mSpanned, mStart + start, mStart + limit, MetricAffectingSpan.class);
+        final SpanSet<CharacterStyle> characterStyleSpans = new SpanSet<CharacterStyle>(
+                    mSpanned, mStart + start, mStart + limit, CharacterStyle.class);
+
         // Shaping needs to take into account context up to metric boundaries,
         // but rendering needs to take into account character style boundaries.
         // So we iterate through metric runs to get metric bounds,
         // then within each metric run iterate through character style runs
         // for the run bounds.
-        float ox = x;
+        final float originalX = x;
         for (int i = start, inext; i < measureLimit; i = inext) {
             TextPaint wp = mWorkPaint;
             wp.set(mPaint);
 
-            int mlimit;
-            if (mSpanned == null) {
-                inext = limit;
-                mlimit = measureLimit;
-            } else {
-                inext = mSpanned.nextSpanTransition(mStart + i, mStart + limit,
-                        MetricAffectingSpan.class) - mStart;
+            inext = metricAffectingSpans.getNextTransition(mStart + i, mStart + limit) - mStart;
+            int mlimit = Math.min(inext, measureLimit);
 
-                mlimit = inext < measureLimit ? inext : measureLimit;
-                MetricAffectingSpan[] spans = mSpanned.getSpans(mStart + i,
-                        mStart + mlimit, MetricAffectingSpan.class);
-                spans = TextUtils.removeEmptySpans(spans, mSpanned, MetricAffectingSpan.class);
+            ReplacementSpan replacement = null;
 
-                if (spans.length > 0) {
-                    ReplacementSpan replacement = null;
-                    for (int j = 0; j < spans.length; j++) {
-                        MetricAffectingSpan span = spans[j];
-                        if (span instanceof ReplacementSpan) {
-                            replacement = (ReplacementSpan)span;
-                        } else {
-                            // We might have a replacement that uses the draw
-                            // state, otherwise measure state would suffice.
-                            span.updateDrawState(wp);
-                        }
-                    }
-
-                    if (replacement != null) {
-                        x += handleReplacement(replacement, wp, i,
-                                mlimit, runIsRtl, c, x, top, y, bottom, fmi,
-                                needWidth || mlimit < measureLimit);
-                        continue;
-                    }
+            for (int j = 0; j < metricAffectingSpans.numberOfSpans; j++) {
+                // Both intervals [spanStarts..spanEnds] and [mStart + i..mStart + mlimit] are NOT
+                // empty by construction. This special case in getSpans() explains the >= & <= tests
+                if ((metricAffectingSpans.spanStarts[j] >= mStart + mlimit) ||
+                        (metricAffectingSpans.spanEnds[j] <= mStart + i)) continue;
+                MetricAffectingSpan span = metricAffectingSpans.spans[j];
+                if (span instanceof ReplacementSpan) {
+                    replacement = (ReplacementSpan)span;
+                } else {
+                    // We might have a replacement that uses the draw
+                    // state, otherwise measure state would suffice.
+                    span.updateDrawState(wp);
                 }
             }
 
-            if (mSpanned == null || c == null) {
+            if (replacement != null) {
+                x += handleReplacement(replacement, wp, i, mlimit, runIsRtl, c, x, top, y,
+                        bottom, fmi, needWidth || mlimit < measureLimit);
+                continue;
+            }
+
+            if (c == null) {
                 x += handleText(wp, i, mlimit, i, inext, runIsRtl, c, x, top,
                         y, bottom, fmi, needWidth || mlimit < measureLimit);
             } else {
                 for (int j = i, jnext; j < mlimit; j = jnext) {
-                    jnext = mSpanned.nextSpanTransition(mStart + j,
-                            mStart + mlimit, CharacterStyle.class) - mStart;
-
-                    CharacterStyle[] spans = mSpanned.getSpans(mStart + j,
-                            mStart + jnext, CharacterStyle.class);
-                    spans = TextUtils.removeEmptySpans(spans, mSpanned, CharacterStyle.class);
+                    jnext = characterStyleSpans.getNextTransition(mStart + j, mStart + mlimit) -
+                            mStart;
 
                     wp.set(mPaint);
-                    for (int k = 0; k < spans.length; k++) {
-                        CharacterStyle span = spans[k];
+                    for (int k = 0; k < characterStyleSpans.numberOfSpans; k++) {
+                        // Intentionally using >= and <= as explained above
+                        if ((characterStyleSpans.spanStarts[k] >= mStart + jnext) ||
+                                (characterStyleSpans.spanEnds[k] <= mStart + j)) continue;
+
+                        CharacterStyle span = characterStyleSpans.spans[k];
                         span.updateDrawState(wp);
                     }
 
@@ -952,7 +1025,7 @@
             }
         }
 
-        return x - ox;
+        return x - originalX;
     }
 
     /**
@@ -997,8 +1070,7 @@
         }
 
         pos += mStart;
-        MetricAffectingSpan[] spans = mSpanned.getSpans(pos, pos + 1,
-                MetricAffectingSpan.class);
+        MetricAffectingSpan[] spans = mSpanned.getSpans(pos, pos + 1, MetricAffectingSpan.class);
         if (spans.length == 0) {
             return mPaint.ascent();
         }
diff --git a/core/java/android/text/TextUtils.java b/core/java/android/text/TextUtils.java
index 894afbd..95a3cdc 100644
--- a/core/java/android/text/TextUtils.java
+++ b/core/java/android/text/TextUtils.java
@@ -53,9 +53,8 @@
 import java.util.regex.Pattern;
 
 public class TextUtils {
-    private TextUtils() { /* cannot be instantiated */ }
 
-    private static String[] EMPTY_STRING_ARRAY = new String[]{};
+    private TextUtils() { /* cannot be instantiated */ }
 
     public static void getChars(CharSequence s, int start, int end,
                                 char[] dest, int destoff) {
@@ -1000,6 +999,10 @@
         MIDDLE,
         END,
         MARQUEE,
+        /**
+         * @hide
+         */
+        END_SMALL
     }
 
     public interface EllipsizeCallback {
@@ -1010,8 +1013,6 @@
         public void ellipsized(int start, int end);
     }
 
-    private static String sEllipsis = null;
-
     /**
      * Returns the original text if it fits in the specified width
      * given the properties of the specified Paint,
@@ -1042,7 +1043,8 @@
                                          boolean preserveLength,
                                          EllipsizeCallback callback) {
         return ellipsize(text, paint, avail, where, preserveLength, callback,
-                TextDirectionHeuristics.FIRSTSTRONG_LTR);
+                TextDirectionHeuristics.FIRSTSTRONG_LTR,
+                (where == TruncateAt.END_SMALL) ? ELLIPSIS_TWO_DOTS : ELLIPSIS_NORMAL);
     }
 
     /**
@@ -1063,11 +1065,7 @@
             float avail, TruncateAt where,
             boolean preserveLength,
             EllipsizeCallback callback,
-            TextDirectionHeuristic textDir) {
-        if (sEllipsis == null) {
-            Resources r = Resources.getSystem();
-            sEllipsis = r.getString(R.string.ellipsis);
-        }
+            TextDirectionHeuristic textDir, String ellipsis) {
 
         int len = text.length();
 
@@ -1085,7 +1083,7 @@
 
             // XXX assumes ellipsis string does not require shaping and
             // is unaffected by style
-            float ellipsiswid = paint.measureText(sEllipsis);
+            float ellipsiswid = paint.measureText(ellipsis);
             avail -= ellipsiswid;
 
             int left = 0;
@@ -1094,7 +1092,7 @@
                 // it all goes
             } else if (where == TruncateAt.START) {
                 right = len - mt.breakText(0, len, false, avail);
-            } else if (where == TruncateAt.END) {
+            } else if (where == TruncateAt.END || where == TruncateAt.END_SMALL) {
                 left = mt.breakText(0, len, true, avail);
             } else {
                 right = len - mt.breakText(0, len, false, avail / 2);
@@ -1112,10 +1110,10 @@
             int remaining = len - (right - left);
             if (preserveLength) {
                 if (remaining > 0) { // else eliminate the ellipsis too
-                    buf[left++] = '\u2026';
+                    buf[left++] = ellipsis.charAt(0);
                 }
                 for (int i = left; i < right; i++) {
-                    buf[i] = '\uFEFF';
+                    buf[i] = ZWNBS_CHAR;
                 }
                 String s = new String(buf, 0, len);
                 if (sp == null) {
@@ -1131,16 +1129,16 @@
             }
 
             if (sp == null) {
-                StringBuilder sb = new StringBuilder(remaining + sEllipsis.length());
+                StringBuilder sb = new StringBuilder(remaining + ellipsis.length());
                 sb.append(buf, 0, left);
-                sb.append(sEllipsis);
+                sb.append(ellipsis);
                 sb.append(buf, right, len - right);
                 return sb.toString();
             }
 
             SpannableStringBuilder ssb = new SpannableStringBuilder();
             ssb.append(text, 0, left);
-            ssb.append(sEllipsis);
+            ssb.append(ellipsis);
             ssb.append(text, right, len);
             return ssb;
         } finally {
@@ -1664,4 +1662,13 @@
 
     private static Object sLock = new Object();
     private static char[] sTemp = null;
+
+    private static String[] EMPTY_STRING_ARRAY = new String[]{};
+
+    private static final char ZWNBS_CHAR = '\uFEFF';
+
+    private static final String ELLIPSIS_NORMAL = Resources.getSystem().getString(
+            R.string.ellipsis);
+    private static final String ELLIPSIS_TWO_DOTS = Resources.getSystem().getString(
+            R.string.ellipsis_two_dots);
 }
diff --git a/core/java/android/view/TextureView.java b/core/java/android/view/TextureView.java
index c735d6b..c974ba1 100644
--- a/core/java/android/view/TextureView.java
+++ b/core/java/android/view/TextureView.java
@@ -93,6 +93,11 @@
  * been invoked.) It is therefore highly recommended you use a listener to
  * be notified when the SurfaceTexture becomes available.</p>
  * 
+ * <p>It is important to note that only one producer can use the TextureView.
+ * For instance, if you use a TextureView to display the camera preview, you
+ * cannot use {@link #lockCanvas()} to draw onto the TextureView at the same
+ * time.</p>
+ * 
  * @see SurfaceView
  * @see SurfaceTexture
  */
@@ -523,6 +528,10 @@
      * rectangle is specified, in which case, non-dirty pixels will be
      * preserved.</p>
      * 
+     * <p>This method can only be used if the underlying surface is not already
+     * owned by another producer. For instance, if the TextureView is being used
+     * to render the camera's preview you cannot invoke this method.</p>
+     * 
      * @return A Canvas used to draw into the surface.
      * 
      * @see #lockCanvas(android.graphics.Rect) 
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index a29cf13..28e4485 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -2824,6 +2824,13 @@
 
         if (hasDisplayList) {
             displayList = child.getDisplayList();
+            if (!displayList.isValid()) {
+                // Uncommon, but possible. If a view is removed from the hierarchy during the call
+                // to getDisplayList(), the display list will be marked invalid and we should not
+                // try to use it again.
+                displayList = null;
+                hasDisplayList = false;
+            }
         }
 
         if (hasNoCache) {
diff --git a/core/java/android/webkit/BrowserFrame.java b/core/java/android/webkit/BrowserFrame.java
index 309857d..28f54aa 100644
--- a/core/java/android/webkit/BrowserFrame.java
+++ b/core/java/android/webkit/BrowserFrame.java
@@ -1159,51 +1159,49 @@
     }
 
     /**
-     * Called by JNI when the native HTTPS stack gets an invalid cert chain.
+     * Called by JNI when the Chromium HTTP stack gets an invalid certificate chain.
      *
      * We delegate the request to CallbackProxy, and route its response to
      * {@link #nativeSslCertErrorProceed(int)} or
      * {@link #nativeSslCertErrorCancel(int, int)}.
      */
-    private void reportSslCertError(
-            final int handle, final int cert_error, byte cert_der[], String url) {
-        final SslError ssl_error;
+    private void reportSslCertError(final int handle, final int certError, byte certDER[],
+            String url) {
+        final SslError sslError;
         try {
-            X509Certificate cert = new X509CertImpl(cert_der);
+            X509Certificate cert = new X509CertImpl(certDER);
             SslCertificate sslCert = new SslCertificate(cert);
             if (JniUtil.useChromiumHttpStack()) {
-                ssl_error = SslError.SslErrorFromChromiumErrorCode(cert_error, sslCert,
+                sslError = SslError.SslErrorFromChromiumErrorCode(certError, sslCert,
                         new URL(url).getHost());
             } else {
-                ssl_error = new SslError(cert_error, cert, url);
+                sslError = new SslError(certError, cert, url);
             }
         } catch (IOException e) {
             // Can't get the certificate, not much to do.
             Log.e(LOGTAG, "Can't get the certificate from WebKit, canceling");
-            nativeSslCertErrorCancel(handle, cert_error);
+            nativeSslCertErrorCancel(handle, certError);
+            return;
+        }
+
+        if (SslCertLookupTable.getInstance().isAllowed(sslError)) {
+            nativeSslCertErrorProceed(handle);
             return;
         }
 
         SslErrorHandler handler = new SslErrorHandler() {
-
             @Override
             public void proceed() {
-                SslCertLookupTable.getInstance().Allow(ssl_error);
+                SslCertLookupTable.getInstance().setIsAllowed(sslError, true);
                 nativeSslCertErrorProceed(handle);
             }
-
             @Override
             public void cancel() {
-                SslCertLookupTable.getInstance().Deny(ssl_error);
-                nativeSslCertErrorCancel(handle, cert_error);
+                SslCertLookupTable.getInstance().setIsAllowed(sslError, false);
+                nativeSslCertErrorCancel(handle, certError);
             }
         };
-
-        if (SslCertLookupTable.getInstance().IsAllowed(ssl_error)) {
-            nativeSslCertErrorProceed(handle);
-        } else {
-            mCallbackProxy.onReceivedSslError(handler, ssl_error);
-        }
+        mCallbackProxy.onReceivedSslError(handler, sslError);
     }
 
     /**
@@ -1416,7 +1414,7 @@
     private native void nativeAuthenticationCancel(int handle);
 
     private native void nativeSslCertErrorProceed(int handle);
-    private native void nativeSslCertErrorCancel(int handle, int cert_error);
+    private native void nativeSslCertErrorCancel(int handle, int certError);
 
     native void nativeSslClientCert(int handle,
                                     byte[] pkcs8EncodedPrivateKey,
diff --git a/core/java/android/webkit/CallbackProxy.java b/core/java/android/webkit/CallbackProxy.java
index 88583df..5ee90a4 100644
--- a/core/java/android/webkit/CallbackProxy.java
+++ b/core/java/android/webkit/CallbackProxy.java
@@ -165,8 +165,6 @@
     /**
      * Get the WebViewClient.
      * @return the current WebViewClient instance.
-     *
-     *@hide pending API council approval.
      */
     public WebViewClient getWebViewClient() {
        return mWebViewClient;
@@ -907,11 +905,9 @@
     */
 
     public void onPageStarted(String url, Bitmap favicon) {
-        // Do an unsynchronized quick check to avoid posting if no callback has
-        // been set.
-        if (mWebViewClient == null) {
-            return;
-        }
+        // We need to send the message even if no WebViewClient is set, because we need to call
+        // WebView.onPageStarted().
+
         // Performance probe
         if (PERF_PROBE) {
             mWebCoreThreadTime = SystemClock.currentThreadTimeMillis();
@@ -1013,10 +1009,6 @@
         sendMessage(msg);
     }
 
-    /**
-     * @hide - hide this because it contains a parameter of type SslError.
-     * SslError is located in a hidden package.
-     */
     public void onReceivedSslError(SslErrorHandler handler, SslError error) {
         // Do an unsynchronized quick check to avoid posting if no callback has
         // been set.
@@ -1031,9 +1023,7 @@
         msg.obj = map;
         sendMessage(msg);
     }
-    /**
-     * @hide
-     */
+
     public void onReceivedClientCertRequest(ClientCertRequestHandler handler, String host_and_port) {
         // Do an unsynchronized quick check to avoid posting if no callback has
         // been set.
@@ -1048,17 +1038,8 @@
         msg.obj = map;
         sendMessage(msg);
     }
-    /**
-     * @hide - hide this because it contains a parameter of type SslCertificate,
-     * which is located in a hidden package.
-     */
 
     public void onReceivedCertificate(SslCertificate certificate) {
-        // Do an unsynchronized quick check to avoid posting if no callback has
-        // been set.
-        if (mWebViewClient == null) {
-            return;
-        }
         // here, certificate can be null (if the site is not secure)
         sendMessage(obtainMessage(RECEIVED_CERTIFICATE, certificate));
     }
diff --git a/core/java/android/webkit/HTML5VideoInline.java b/core/java/android/webkit/HTML5VideoInline.java
index 97dc291..42581c2 100644
--- a/core/java/android/webkit/HTML5VideoInline.java
+++ b/core/java/android/webkit/HTML5VideoInline.java
@@ -1,6 +1,8 @@
 
 package android.webkit;
 
+import android.Manifest.permission;
+import android.content.pm.PackageManager;
 import android.graphics.SurfaceTexture;
 import android.media.MediaPlayer;
 import android.webkit.HTML5VideoView;
@@ -52,7 +54,12 @@
     public void prepareDataAndDisplayMode(HTML5VideoViewProxy proxy) {
         super.prepareDataAndDisplayMode(proxy);
         setFrameAvailableListener(proxy);
-        mPlayer.setWakeMode(proxy.getContext(), PowerManager.FULL_WAKE_LOCK);
+        // TODO: This is a workaround, after b/5375681 fixed, we should switch
+        // to the better way.
+        if (mProxy.getContext().checkCallingOrSelfPermission(permission.WAKE_LOCK)
+                == PackageManager.PERMISSION_GRANTED) {
+            mPlayer.setWakeMode(proxy.getContext(), PowerManager.FULL_WAKE_LOCK);
+        }
     }
 
     // Pause the play and update the play/pause button
diff --git a/core/java/android/webkit/SslCertLookupTable.java b/core/java/android/webkit/SslCertLookupTable.java
index faff110..052244f 100644
--- a/core/java/android/webkit/SslCertLookupTable.java
+++ b/core/java/android/webkit/SslCertLookupTable.java
@@ -20,14 +20,15 @@
 import android.net.http.SslError;
 
 /**
- * A simple class to store the wrong certificates that user is aware but
- * chose to proceed.
+ * Stores the user's decision of whether to allow or deny an invalid certificate.
+ *
+ * This class is not threadsafe. It is used only on the WebCore thread.
  */
 final class SslCertLookupTable {
     private static SslCertLookupTable sTable;
     private final Bundle table;
 
-    public static synchronized SslCertLookupTable getInstance() {
+    public static SslCertLookupTable getInstance() {
         if (sTable == null) {
             sTable = new SslCertLookupTable();
         }
@@ -38,15 +39,15 @@
         table = new Bundle();
     }
 
-    public void Allow(SslError ssl_error) {
-        table.putBoolean(ssl_error.toString(), true);
+    public void setIsAllowed(SslError sslError, boolean allow) {
+        table.putBoolean(sslError.toString(), allow);
     }
 
-    public void Deny(SslError ssl_error) {
-        table.putBoolean(ssl_error.toString(), false);
+    public boolean isAllowed(SslError sslError) {
+        return table.getBoolean(sslError.toString());
     }
 
-    public boolean IsAllowed(SslError ssl_error) {
-        return table.getBoolean(ssl_error.toString());
+    public void clear() {
+        table.clear();
     }
 }
diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java
index 470e843..deaf0f2 100644
--- a/core/java/android/webkit/WebViewCore.java
+++ b/core/java/android/webkit/WebViewCore.java
@@ -1349,8 +1349,14 @@
                         }
 
                         case CLEAR_SSL_PREF_TABLE:
-                            Network.getInstance(mContext)
-                                    .clearUserSslPrefTable();
+                            if (JniUtil.useChromiumHttpStack()) {
+                                // FIXME: This will not work for connections currently in use, as
+                                // they cache the certificate responses. See http://b/5324235.
+                                SslCertLookupTable.getInstance().clear();
+                                nativeCloseIdleConnections();
+                            } else {
+                                Network.getInstance(mContext).clearUserSslPrefTable();
+                            }
                             break;
 
                         case TOUCH_UP:
diff --git a/core/java/android/widget/BaseAdapter.java b/core/java/android/widget/BaseAdapter.java
index 532fd76..401fcb8 100644
--- a/core/java/android/widget/BaseAdapter.java
+++ b/core/java/android/widget/BaseAdapter.java
@@ -43,13 +43,18 @@
     }
     
     /**
-     * Notifies the attached View that the underlying data has been changed
-     * and it should refresh itself.
+     * Notifies the attached observers that the underlying data has been changed
+     * and any View reflecting the data set should refresh itself.
      */
     public void notifyDataSetChanged() {
         mDataSetObservable.notifyChanged();
     }
-    
+
+    /**
+     * Notifies the attached observers that the underlying data is no longer valid
+     * or available. Once invoked this adapter is no longer valid and should
+     * not report further data set changes.
+     */
     public void notifyDataSetInvalidated() {
         mDataSetObservable.notifyInvalidated();
     }
diff --git a/core/java/android/widget/MediaController.java b/core/java/android/widget/MediaController.java
index a63b8c8..90ece5d 100644
--- a/core/java/android/widget/MediaController.java
+++ b/core/java/android/widget/MediaController.java
@@ -75,6 +75,7 @@
     private WindowManager       mWindowManager;
     private Window              mWindow;
     private View                mDecor;
+    private WindowManager.LayoutParams mDecorLayoutParams;
     private ProgressBar         mProgress;
     private TextView            mEndTime, mCurrentTime;
     private boolean             mShowing;
@@ -120,6 +121,7 @@
         mContext = context;
         mUseFastForward = true;
         initFloatingWindow();
+        initFloatingWindowLayout();
     }
 
     private void initFloatingWindow() {
@@ -142,6 +144,48 @@
         requestFocus();
     }
 
+    // Allocate and initialize the static parts of mDecorLayoutParams. Must
+    // also call updateFloatingWindowLayout() to fill in the dynamic parts
+    // (y and width) before mDecorLayoutParams can be used.
+    private void initFloatingWindowLayout() {
+        mDecorLayoutParams = new WindowManager.LayoutParams();
+        WindowManager.LayoutParams p = mDecorLayoutParams;
+        p.gravity = Gravity.TOP;
+        p.height = LayoutParams.WRAP_CONTENT;
+        p.x = 0;
+        p.format = PixelFormat.TRANSLUCENT;
+        p.type = WindowManager.LayoutParams.TYPE_APPLICATION_PANEL;
+        p.flags |= WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM
+                | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
+                | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH;
+        p.token = null;
+        p.windowAnimations = 0; // android.R.style.DropDownAnimationDown;
+    }
+
+    // Update the dynamic parts of mDecorLayoutParams
+    // Must be called with mAnchor != NULL.
+    private void updateFloatingWindowLayout() {
+        int [] anchorPos = new int[2];
+        mAnchor.getLocationOnScreen(anchorPos);
+
+        WindowManager.LayoutParams p = mDecorLayoutParams;
+        p.width = mAnchor.getWidth();
+        p.y = anchorPos[1] + mAnchor.getHeight();
+    }
+
+    // This is called whenever mAnchor's layout bound changes
+    private OnLayoutChangeListener mLayoutChangeListener =
+            new OnLayoutChangeListener() {
+        public void onLayoutChange(View v, int left, int top, int right,
+                int bottom, int oldLeft, int oldTop, int oldRight,
+                int oldBottom) {
+            updateFloatingWindowLayout();
+            if (mShowing) {
+                mWindowManager.updateViewLayout(mDecor, mDecorLayoutParams);
+            }
+        }
+    };
+
     private OnTouchListener mTouchListener = new OnTouchListener() {
         public boolean onTouch(View v, MotionEvent event) {
             if (event.getAction() == MotionEvent.ACTION_DOWN) {
@@ -164,7 +208,13 @@
      * @param view The view to which to anchor the controller when it is visible.
      */
     public void setAnchorView(View view) {
+        if (mAnchor != null) {
+            mAnchor.removeOnLayoutChangeListener(mLayoutChangeListener);
+        }
         mAnchor = view;
+        if (mAnchor != null) {
+            mAnchor.addOnLayoutChangeListener(mLayoutChangeListener);
+        }
 
         FrameLayout.LayoutParams frameParams = new FrameLayout.LayoutParams(
                 ViewGroup.LayoutParams.MATCH_PARENT,
@@ -279,31 +329,14 @@
      * the controller until hide() is called.
      */
     public void show(int timeout) {
-
         if (!mShowing && mAnchor != null) {
             setProgress();
             if (mPauseButton != null) {
                 mPauseButton.requestFocus();
             }
             disableUnsupportedButtons();
-
-            int [] anchorpos = new int[2];
-            mAnchor.getLocationOnScreen(anchorpos);
-
-            WindowManager.LayoutParams p = new WindowManager.LayoutParams();
-            p.gravity = Gravity.TOP;
-            p.width = mAnchor.getWidth();
-            p.height = LayoutParams.WRAP_CONTENT;
-            p.x = 0;
-            p.y = anchorpos[1] + mAnchor.getHeight() - p.height;
-            p.format = PixelFormat.TRANSLUCENT;
-            p.type = WindowManager.LayoutParams.TYPE_APPLICATION_PANEL;
-            p.flags |= WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM
-                    | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
-                    | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH;
-            p.token = null;
-            p.windowAnimations = 0; // android.R.style.DropDownAnimationDown;
-            mWindowManager.addView(mDecor, p);
+            updateFloatingWindowLayout();
+            mWindowManager.addView(mDecor, mDecorLayoutParams);
             mShowing = true;
         }
         updatePausePlay();
diff --git a/core/java/android/widget/SpellChecker.java b/core/java/android/widget/SpellChecker.java
index 14cbf6f..6b2f3e4 100644
--- a/core/java/android/widget/SpellChecker.java
+++ b/core/java/android/widget/SpellChecker.java
@@ -75,6 +75,20 @@
         mLength = 0;
     }
 
+    /**
+     * @return true if a spell checker session has successfully been created. Returns false if not,
+     * for instance when spell checking has been disabled in settings.
+     */
+    public boolean isSessionActive() {
+        return mSpellCheckerSession != null;
+    }
+
+    public void closeSession() {
+        if (mSpellCheckerSession != null) {
+            mSpellCheckerSession.close();
+        }
+    }
+
     public void addSpellCheckSpan(SpellCheckSpan spellCheckSpan) {
         int length = mIds.length;
         if (mLength >= length) {
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 8db6592..8ea55c6 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -3250,7 +3250,8 @@
         sendOnTextChanged(text, 0, oldlen, textLength);
         onTextChanged(text, 0, oldlen, textLength);
 
-        if (startSpellCheck) {
+        if (startSpellCheck && mSpellChecker != null) {
+            // This view has to have been previously attached for mSpellChecker to exist  
             updateSpellCheckSpans(0, textLength);
         }
 
@@ -4412,6 +4413,8 @@
 
         // Resolve drawables as the layout direction has been resolved
         resolveDrawables();
+        
+        updateSpellCheckSpans(0, mText.length());
     }
 
     @Override
@@ -4443,6 +4446,14 @@
         hideControllers();
 
         resetResolvedDrawables();
+
+        if (mSpellChecker != null) {
+            mSpellChecker.closeSession();
+            removeMisspelledSpans();
+            // Forces the creation of a new SpellChecker next time this window is created.
+            // Will handle the cases where the settings has been changed in the meantime.
+            mSpellChecker = null;
+        }
     }
 
     @Override
@@ -6130,7 +6141,7 @@
         TruncateAt effectiveEllipsize = mEllipsize;
         if (mEllipsize == TruncateAt.MARQUEE &&
                 mMarqueeFadeMode == MARQUEE_FADE_SWITCH_SHOW_ELLIPSIS) {
-            effectiveEllipsize = TruncateAt.END;
+            effectiveEllipsize = TruncateAt.END_SMALL;
         }
 
         if (mTextDir == null) {
@@ -7595,7 +7606,7 @@
             }
             ims.mChangedDelta += after-before;
         }
-        
+
         sendOnTextChanged(buffer, start, before, after);
         onTextChanged(buffer, start, before, after);
 
@@ -7737,7 +7748,8 @@
      * Create new SpellCheckSpans on the modified region.
      */
     private void updateSpellCheckSpans(int start, int end) {
-        if (!(mText instanceof Editable) || !isSuggestionsEnabled()) return;
+        if (!isTextEditable() || !isSuggestionsEnabled() || !getSpellChecker().isSessionActive())
+            return;
         Editable text = (Editable) mText;
 
         WordIterator wordIterator = getWordIterator();
@@ -8427,13 +8439,31 @@
                 int flags = suggestionSpans[i].getFlags();
                 if ((flags & SuggestionSpan.FLAG_EASY_CORRECT) != 0
                         && (flags & SuggestionSpan.FLAG_MISSPELLED) == 0) {
-                    flags = flags & ~SuggestionSpan.FLAG_EASY_CORRECT;
+                    flags &= ~SuggestionSpan.FLAG_EASY_CORRECT;
                     suggestionSpans[i].setFlags(flags);
                 }
             }
         }
     }
 
+    /**
+     * Removes the suggestion spans for misspelled words.
+     */
+    private void removeMisspelledSpans() {
+        if (mText instanceof Spannable) {
+            Spannable spannable = (Spannable) mText;
+            SuggestionSpan[] suggestionSpans = spannable.getSpans(0,
+                    spannable.length(), SuggestionSpan.class);
+            for (int i = 0; i < suggestionSpans.length; i++) {
+                int flags = suggestionSpans[i].getFlags();
+                if ((flags & SuggestionSpan.FLAG_EASY_CORRECT) != 0
+                        && (flags & SuggestionSpan.FLAG_MISSPELLED) != 0) {
+                    spannable.removeSpan(suggestionSpans[i]);
+                }
+            }
+        }
+    }
+
     @Override
     public boolean onGenericMotionEvent(MotionEvent event) {
         if (mMovement != null && mText instanceof Spannable && mLayout != null) {
@@ -9573,7 +9603,6 @@
         private final Comparator<SuggestionSpan> mSuggestionSpanComparator;
         private final HashMap<SuggestionSpan, Integer> mSpansLengths;
 
-
         private class CustomPopupWindow extends PopupWindow {
             public CustomPopupWindow(Context context, int defStyle) {
                 super(context, null, defStyle);
@@ -9585,9 +9614,8 @@
 
                 TextView.this.getPositionListener().removeSubscriber(SuggestionsPopupWindow.this);
 
-                if ((mText instanceof Spannable)) {
-                    ((Spannable) mText).removeSpan(mSuggestionRangeSpan);
-                }
+                // Safe cast since show() checks that mText is an Editable
+                ((Spannable) mText).removeSpan(mSuggestionRangeSpan);
 
                 setCursorVisible(mCursorWasVisibleBeforeSuggestions);
                 if (hasInsertionController()) {
@@ -9637,8 +9665,8 @@
             void removeMisspelledFlag() {
                 int suggestionSpanFlags = suggestionSpan.getFlags();
                 if ((suggestionSpanFlags & SuggestionSpan.FLAG_MISSPELLED) > 0) {
-                    suggestionSpanFlags &= ~(SuggestionSpan.FLAG_MISSPELLED);
-                    suggestionSpanFlags &= ~(SuggestionSpan.FLAG_EASY_CORRECT);
+                    suggestionSpanFlags &= ~SuggestionSpan.FLAG_MISSPELLED;
+                    suggestionSpanFlags &= ~SuggestionSpan.FLAG_EASY_CORRECT;
                     suggestionSpan.setFlags(suggestionSpanFlags);
                 }
             }
@@ -9887,6 +9915,8 @@
 
         @Override
         public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+            hide();
+
             if (view instanceof TextView) {
                 TextView textView = (TextView) view;
                 Editable editable = (Editable) mText;
@@ -9894,6 +9924,7 @@
                 SuggestionInfo suggestionInfo = mSuggestionInfos[position];
                 final int spanStart = editable.getSpanStart(suggestionInfo.suggestionSpan);
                 final int spanEnd = editable.getSpanEnd(suggestionInfo.suggestionSpan);
+                if (spanStart < 0 || spanEnd < 0) return; // Span has been removed
                 final String originalText = mText.subSequence(spanStart, spanEnd).toString();
 
                 if (suggestionInfo.suggestionIndex < 0) {
@@ -9955,7 +9986,6 @@
                     Selection.setSelection(editable, spanEnd + lengthDifference);
                 }
             }
-            hide();
         }
     }
 
@@ -10520,9 +10550,7 @@
 
         public abstract int getCurrentCursorOffset();
 
-        protected void updateSelection(int offset) {
-            updateDrawable();
-        }
+        protected abstract void updateSelection(int offset);
 
         public abstract void updatePosition(float x, float y);
 
@@ -10796,8 +10824,8 @@
 
         @Override
         public void updateSelection(int offset) {
-            super.updateSelection(offset);
             Selection.setSelection((Spannable) mText, offset, getSelectionEnd());
+            updateDrawable();
         }
 
         @Override
@@ -10838,8 +10866,8 @@
 
         @Override
         public void updateSelection(int offset) {
-            super.updateSelection(offset);
             Selection.setSelection((Spannable) mText, getSelectionStart(), offset);
+            updateDrawable();
         }
 
         @Override
diff --git a/core/java/android/widget/VideoView.java b/core/java/android/widget/VideoView.java
index 88a0e01..8e438ff 100644
--- a/core/java/android/widget/VideoView.java
+++ b/core/java/android/widget/VideoView.java
@@ -456,13 +456,6 @@
                     seekTo(mSeekWhenPrepared);
                 }
                 start();
-                if (mMediaController != null) {
-                    if (mMediaController.isShowing()) {
-                        // ensure the controller will get repositioned later
-                        mMediaController.hide();
-                    }
-                    mMediaController.show();
-                }
             }
         }
 
diff --git a/core/java/com/android/internal/policy/IFaceLockCallback.aidl b/core/java/com/android/internal/policy/IFaceLockCallback.aidl
index 1eadc41..4f76c71 100644
--- a/core/java/com/android/internal/policy/IFaceLockCallback.aidl
+++ b/core/java/com/android/internal/policy/IFaceLockCallback.aidl
@@ -21,5 +21,4 @@
 oneway interface IFaceLockCallback {
     void unlock();
     void cancel();
-    void sleepDevice();
 }
diff --git a/core/java/com/android/internal/util/ArrayUtils.java b/core/java/com/android/internal/util/ArrayUtils.java
index 159929b..3d22929 100644
--- a/core/java/com/android/internal/util/ArrayUtils.java
+++ b/core/java/com/android/internal/util/ArrayUtils.java
@@ -133,4 +133,13 @@
         }
         return false;
     }
+
+    public static boolean contains(int[] array, int value) {
+        for (int element : array) {
+            if (element == value) {
+                return true;
+            }
+        }
+        return false;
+    }
 }
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index 19dc42b..81e7c34 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -947,10 +947,15 @@
      *
      * If there's currently a call in progress, the button will take them to the call
      * @param button the button to update
+     * @param the phone state:
+     *  {@link TelephonyManager#CALL_STATE_IDLE}
+     *  {@link TelephonyManager#CALL_STATE_RINGING}
+     *  {@link TelephonyManager#CALL_STATE_OFFHOOK}
      * @param showIfCapable indicates whether the button should be shown if emergency calls are
      *                      possible on the device
      */
-    public void updateEmergencyCallButtonState(Button button, boolean showIfCapable) {
+    public void updateEmergencyCallButtonState(Button button, int  phoneState,
+            boolean showIfCapable) {
         if (isEmergencyCallCapable() && showIfCapable) {
             button.setVisibility(View.VISIBLE);
         } else {
@@ -958,9 +963,8 @@
             return;
         }
 
-        int newState = TelephonyManager.getDefault().getCallState();
         int textId;
-        if (newState == TelephonyManager.CALL_STATE_OFFHOOK) {
+        if (phoneState == TelephonyManager.CALL_STATE_OFFHOOK) {
             // show "return to call" text and show phone icon
             textId = R.string.lockscreen_return_to_call;
             int phoneCallIcon = R.drawable.stat_sys_phone_call;
@@ -990,22 +994,4 @@
         }
         return false;
     }
-
-    /**
-     * Performs concentenation of PLMN/SPN
-     * @param plmn
-     * @param spn
-     * @return
-     */
-    public static CharSequence getCarrierString(CharSequence plmn, CharSequence spn) {
-        if (plmn != null && spn == null) {
-            return plmn;
-        } else if (plmn != null && spn != null) {
-            return plmn + "|" + spn;
-        } else if (plmn == null && spn != null) {
-            return spn;
-        } else {
-            return "";
-        }
-    }
 }
diff --git a/core/jni/android/graphics/TextLayoutCache.cpp b/core/jni/android/graphics/TextLayoutCache.cpp
index c045c07..86ae7d2 100644
--- a/core/jni/android/graphics/TextLayoutCache.cpp
+++ b/core/jni/android/graphics/TextLayoutCache.cpp
@@ -551,8 +551,7 @@
     // Get LogClusters
     if (outLogClusters) {
         size_t countLogClusters = outLogClusters->size();
-        size_t countGlyphs = shaperItem.num_glyphs;
-        for (size_t i = 0; i < countGlyphs; i++) {
+        for (size_t i = 0; i < count; i++) {
             // As there may be successive runs, we need to shift the log clusters
             unsigned short logCluster = shaperItem.log_clusters[i] + countLogClusters;
 #if DEBUG_GLYPHS
@@ -620,25 +619,15 @@
         *outGlyphsCount = 0;
         return;
     }
-    size_t endIndex = 0;
-    for(size_t i = 0; i < mGlyphs.size(); i++) {
-        if (mLogClusters[i] <= start) {
-            *outStartIndex = i;
-            endIndex = i;
-            continue;
-        }
-        if (mLogClusters[i] <= start + count) {
-            endIndex = i;
-        }
-    }
-    *outGlyphsCount = endIndex - *outStartIndex + 1;
+    *outStartIndex = mLogClusters[start];
+    *outGlyphsCount = mLogClusters[start + count - 1] - mLogClusters[start] + 1;
 #if DEBUG_GLYPHS
     LOGD("getGlyphsIndexes - start=%d count=%d - startIndex=%d count=%d", start, count,
             *outStartIndex, *outGlyphsCount);
     for(size_t i = 0; i < mGlyphs.size(); i++) {
         LOGD("getGlyphs - all - glyph[%d] = %d", i, mGlyphs[i]);
     }
-    for(size_t i = 0; i < mGlyphs.size(); i++) {
+    for(size_t i = 0; i < mAdvances.size(); i++) {
         LOGD("getGlyphs - all - logcl[%d] = %d", i, mLogClusters[i]);
     }
 #endif
diff --git a/core/jni/android_net_wifi_Wifi.cpp b/core/jni/android_net_wifi_Wifi.cpp
index 84a50f0..84c636b 100644
--- a/core/jni/android_net_wifi_Wifi.cpp
+++ b/core/jni/android_net_wifi_Wifi.cpp
@@ -402,30 +402,6 @@
     return (jint)rssi;
 }
 
-static jint android_net_wifi_getRssiCommand(JNIEnv* env, jobject)
-{
-    return android_net_wifi_getRssiHelper("DRIVER RSSI");
-}
-
-static jint android_net_wifi_getRssiApproxCommand(JNIEnv* env, jobject)
-{
-    return android_net_wifi_getRssiHelper("DRIVER RSSI-APPROX");
-}
-
-static jint android_net_wifi_getLinkSpeedCommand(JNIEnv* env, jobject)
-{
-    char reply[BUF_SIZE];
-    int linkspeed;
-
-    if (doCommand("DRIVER LINKSPEED", reply, sizeof(reply)) != 0) {
-        return (jint)-1;
-    }
-    // reply comes back in the form "LinkSpeed XX" where XX is the
-    // number we're interested in.
-    sscanf(reply, "%*s %u", &linkspeed);
-    return (jint)linkspeed;
-}
-
 static jstring android_net_wifi_getMacAddressCommand(JNIEnv* env, jobject)
 {
     char reply[BUF_SIZE];
@@ -625,10 +601,6 @@
     		(void*) android_net_wifi_setBluetoothCoexistenceModeCommand },
     { "setBluetoothCoexistenceScanModeCommand", "(Z)Z",
     		(void*) android_net_wifi_setBluetoothCoexistenceScanModeCommand },
-    { "getRssiCommand", "()I", (void*) android_net_wifi_getRssiCommand },
-    { "getRssiApproxCommand", "()I",
-            (void*) android_net_wifi_getRssiApproxCommand},
-    { "getLinkSpeedCommand", "()I", (void*) android_net_wifi_getLinkSpeedCommand },
     { "getMacAddressCommand", "()Ljava/lang/String;", (void*) android_net_wifi_getMacAddressCommand },
     { "saveConfigCommand", "()Z", (void*) android_net_wifi_saveConfigCommand },
     { "reloadConfigCommand", "()Z", (void*) android_net_wifi_reloadConfigCommand },
diff --git a/core/res/res/drawable-hdpi/btn_code_lock_default_holo.png b/core/res/res/drawable-hdpi/btn_code_lock_default_holo.png
index 9409890..28b2578 100644
--- a/core/res/res/drawable-hdpi/btn_code_lock_default_holo.png
+++ b/core/res/res/drawable-hdpi/btn_code_lock_default_holo.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_code_lock_touched_holo.png b/core/res/res/drawable-hdpi/btn_code_lock_touched_holo.png
index 55acc9a..66cb1ec 100644
--- a/core/res/res/drawable-hdpi/btn_code_lock_touched_holo.png
+++ b/core/res/res/drawable-hdpi/btn_code_lock_touched_holo.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_lockscreen_handle_normal.png b/core/res/res/drawable-hdpi/ic_lockscreen_handle_normal.png
index 1b7f499..5f8a7d1 100644
--- a/core/res/res/drawable-hdpi/ic_lockscreen_handle_normal.png
+++ b/core/res/res/drawable-hdpi/ic_lockscreen_handle_normal.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_lockscreen_unlock_focused.png b/core/res/res/drawable-hdpi/ic_lockscreen_unlock_focused.png
deleted file mode 100644
index da77340..0000000
--- a/core/res/res/drawable-hdpi/ic_lockscreen_unlock_focused.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/indicator_code_lock_drag_direction_green_up.png b/core/res/res/drawable-hdpi/indicator_code_lock_drag_direction_green_up.png
deleted file mode 100644
index 6560696..0000000
--- a/core/res/res/drawable-hdpi/indicator_code_lock_drag_direction_green_up.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/indicator_code_lock_point_area_default_holo.png b/core/res/res/drawable-hdpi/indicator_code_lock_point_area_default_holo.png
index 237011c..28b2578 100644
--- a/core/res/res/drawable-hdpi/indicator_code_lock_point_area_default_holo.png
+++ b/core/res/res/drawable-hdpi/indicator_code_lock_point_area_default_holo.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/indicator_code_lock_point_area_green_holo.png b/core/res/res/drawable-hdpi/indicator_code_lock_point_area_green_holo.png
index 2418017..545cc09 100644
--- a/core/res/res/drawable-hdpi/indicator_code_lock_point_area_green_holo.png
+++ b/core/res/res/drawable-hdpi/indicator_code_lock_point_area_green_holo.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/indicator_code_lock_point_area_red_holo.png b/core/res/res/drawable-hdpi/indicator_code_lock_point_area_red_holo.png
index 2120bad..9176b33 100644
--- a/core/res/res/drawable-hdpi/indicator_code_lock_point_area_red_holo.png
+++ b/core/res/res/drawable-hdpi/indicator_code_lock_point_area_red_holo.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_notify_wifi_in_range.png b/core/res/res/drawable-hdpi/stat_notify_wifi_in_range.png
index 716ba9d..f3aaa27 100644
--- a/core/res/res/drawable-hdpi/stat_notify_wifi_in_range.png
+++ b/core/res/res/drawable-hdpi/stat_notify_wifi_in_range.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/vpn_connected.png b/core/res/res/drawable-hdpi/vpn_connected.png
index 65fc6db..c3547e8 100644
--- a/core/res/res/drawable-hdpi/vpn_connected.png
+++ b/core/res/res/drawable-hdpi/vpn_connected.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/vpn_disconnected.png b/core/res/res/drawable-hdpi/vpn_disconnected.png
index 2440c69..10a9065 100644
--- a/core/res/res/drawable-hdpi/vpn_disconnected.png
+++ b/core/res/res/drawable-hdpi/vpn_disconnected.png
Binary files differ
diff --git a/core/res/res/drawable-large-mdpi/indicator_code_lock_drag_direction_green_up.png b/core/res/res/drawable-large-mdpi/indicator_code_lock_drag_direction_green_up.png
deleted file mode 100644
index 0bc86c3..0000000
--- a/core/res/res/drawable-large-mdpi/indicator_code_lock_drag_direction_green_up.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-ldpi/indicator_code_lock_drag_direction_green_up.png b/core/res/res/drawable-ldpi/indicator_code_lock_drag_direction_green_up.png
deleted file mode 100644
index 9c8610f..0000000
--- a/core/res/res/drawable-ldpi/indicator_code_lock_drag_direction_green_up.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_code_lock_default.png b/core/res/res/drawable-mdpi/btn_code_lock_default.png
old mode 100755
new mode 100644
index f524317..206f9b3
--- a/core/res/res/drawable-mdpi/btn_code_lock_default.png
+++ b/core/res/res/drawable-mdpi/btn_code_lock_default.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_code_lock_default_holo.png b/core/res/res/drawable-mdpi/btn_code_lock_default_holo.png
index 82fc3b2..4c4adf2 100644
--- a/core/res/res/drawable-mdpi/btn_code_lock_default_holo.png
+++ b/core/res/res/drawable-mdpi/btn_code_lock_default_holo.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_code_lock_touched.png b/core/res/res/drawable-mdpi/btn_code_lock_touched.png
old mode 100755
new mode 100644
index 5cd436c..98a3b6d
--- a/core/res/res/drawable-mdpi/btn_code_lock_touched.png
+++ b/core/res/res/drawable-mdpi/btn_code_lock_touched.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_code_lock_touched_holo.png b/core/res/res/drawable-mdpi/btn_code_lock_touched_holo.png
index d1fe1ad..ef701ed 100644
--- a/core/res/res/drawable-mdpi/btn_code_lock_touched_holo.png
+++ b/core/res/res/drawable-mdpi/btn_code_lock_touched_holo.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_lockscreen_handle_normal.png b/core/res/res/drawable-mdpi/ic_lockscreen_handle_normal.png
index 754d7bc..1d547e1 100644
--- a/core/res/res/drawable-mdpi/ic_lockscreen_handle_normal.png
+++ b/core/res/res/drawable-mdpi/ic_lockscreen_handle_normal.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_lockscreen_unlock_focused.png b/core/res/res/drawable-mdpi/ic_lockscreen_unlock_focused.png
deleted file mode 100644
index 6f51447..0000000
--- a/core/res/res/drawable-mdpi/ic_lockscreen_unlock_focused.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/indicator_code_lock_drag_direction_green_up.png b/core/res/res/drawable-mdpi/indicator_code_lock_drag_direction_green_up.png
deleted file mode 100644
index 7ddeba5..0000000
--- a/core/res/res/drawable-mdpi/indicator_code_lock_drag_direction_green_up.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/indicator_code_lock_point_area_default.png b/core/res/res/drawable-mdpi/indicator_code_lock_point_area_default.png
index f6d9f1b..05c194b 100644
--- a/core/res/res/drawable-mdpi/indicator_code_lock_point_area_default.png
+++ b/core/res/res/drawable-mdpi/indicator_code_lock_point_area_default.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/indicator_code_lock_point_area_default_holo.png b/core/res/res/drawable-mdpi/indicator_code_lock_point_area_default_holo.png
index a627cda..4c4adf2 100644
--- a/core/res/res/drawable-mdpi/indicator_code_lock_point_area_default_holo.png
+++ b/core/res/res/drawable-mdpi/indicator_code_lock_point_area_default_holo.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/indicator_code_lock_point_area_green.png b/core/res/res/drawable-mdpi/indicator_code_lock_point_area_green.png
index b7262d1..8f24832 100644
--- a/core/res/res/drawable-mdpi/indicator_code_lock_point_area_green.png
+++ b/core/res/res/drawable-mdpi/indicator_code_lock_point_area_green.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/indicator_code_lock_point_area_green_holo.png b/core/res/res/drawable-mdpi/indicator_code_lock_point_area_green_holo.png
index 308624b..cb5b31a 100644
--- a/core/res/res/drawable-mdpi/indicator_code_lock_point_area_green_holo.png
+++ b/core/res/res/drawable-mdpi/indicator_code_lock_point_area_green_holo.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/indicator_code_lock_point_area_red_holo.png b/core/res/res/drawable-mdpi/indicator_code_lock_point_area_red_holo.png
index 6c451ec..8434741 100644
--- a/core/res/res/drawable-mdpi/indicator_code_lock_point_area_red_holo.png
+++ b/core/res/res/drawable-mdpi/indicator_code_lock_point_area_red_holo.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_notify_wifi_in_range.png b/core/res/res/drawable-mdpi/stat_notify_wifi_in_range.png
index 3bf0d35..747cb97 100644
--- a/core/res/res/drawable-mdpi/stat_notify_wifi_in_range.png
+++ b/core/res/res/drawable-mdpi/stat_notify_wifi_in_range.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/vpn_connected.png b/core/res/res/drawable-mdpi/vpn_connected.png
index 0d1a026..7e167f8 100644
--- a/core/res/res/drawable-mdpi/vpn_connected.png
+++ b/core/res/res/drawable-mdpi/vpn_connected.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/vpn_disconnected.png b/core/res/res/drawable-mdpi/vpn_disconnected.png
index d16d7fb..a08c42a 100644
--- a/core/res/res/drawable-mdpi/vpn_disconnected.png
+++ b/core/res/res/drawable-mdpi/vpn_disconnected.png
Binary files differ
diff --git a/core/res/res/drawable-nodpi/indicator_code_lock_drag_direction_green_up.png b/core/res/res/drawable-nodpi/indicator_code_lock_drag_direction_green_up.png
new file mode 100644
index 0000000..cc46f19
--- /dev/null
+++ b/core/res/res/drawable-nodpi/indicator_code_lock_drag_direction_green_up.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_code_lock_default.png b/core/res/res/drawable-xhdpi/btn_code_lock_default.png
index a644014..c1358a2 100644
--- a/core/res/res/drawable-xhdpi/btn_code_lock_default.png
+++ b/core/res/res/drawable-xhdpi/btn_code_lock_default.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_code_lock_default_holo.png b/core/res/res/drawable-xhdpi/btn_code_lock_default_holo.png
index f607251..db1cbe6 100644
--- a/core/res/res/drawable-xhdpi/btn_code_lock_default_holo.png
+++ b/core/res/res/drawable-xhdpi/btn_code_lock_default_holo.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_code_lock_touched.png b/core/res/res/drawable-xhdpi/btn_code_lock_touched.png
index 67faad2..0fafc3e 100644
--- a/core/res/res/drawable-xhdpi/btn_code_lock_touched.png
+++ b/core/res/res/drawable-xhdpi/btn_code_lock_touched.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_code_lock_touched_holo.png b/core/res/res/drawable-xhdpi/btn_code_lock_touched_holo.png
index e057cdd..073c3ac 100644
--- a/core/res/res/drawable-xhdpi/btn_code_lock_touched_holo.png
+++ b/core/res/res/drawable-xhdpi/btn_code_lock_touched_holo.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_lockscreen_handle_normal.png b/core/res/res/drawable-xhdpi/ic_lockscreen_handle_normal.png
index 544924e..b09071b 100644
--- a/core/res/res/drawable-xhdpi/ic_lockscreen_handle_normal.png
+++ b/core/res/res/drawable-xhdpi/ic_lockscreen_handle_normal.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_lockscreen_unlock_focused.png b/core/res/res/drawable-xhdpi/ic_lockscreen_unlock_focused.png
deleted file mode 100644
index d067ab8..0000000
--- a/core/res/res/drawable-xhdpi/ic_lockscreen_unlock_focused.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/indicator_code_lock_drag_direction_green_up.png b/core/res/res/drawable-xhdpi/indicator_code_lock_drag_direction_green_up.png
deleted file mode 100644
index a89b8d5..0000000
--- a/core/res/res/drawable-xhdpi/indicator_code_lock_drag_direction_green_up.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/indicator_code_lock_point_area_default.png b/core/res/res/drawable-xhdpi/indicator_code_lock_point_area_default.png
index 997d6a5..0812cb5 100644
--- a/core/res/res/drawable-xhdpi/indicator_code_lock_point_area_default.png
+++ b/core/res/res/drawable-xhdpi/indicator_code_lock_point_area_default.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/indicator_code_lock_point_area_default_holo.png b/core/res/res/drawable-xhdpi/indicator_code_lock_point_area_default_holo.png
index d98a126..db1cbe6 100644
--- a/core/res/res/drawable-xhdpi/indicator_code_lock_point_area_default_holo.png
+++ b/core/res/res/drawable-xhdpi/indicator_code_lock_point_area_default_holo.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/indicator_code_lock_point_area_green.png b/core/res/res/drawable-xhdpi/indicator_code_lock_point_area_green.png
index 2eb69f6..3ab2e99 100644
--- a/core/res/res/drawable-xhdpi/indicator_code_lock_point_area_green.png
+++ b/core/res/res/drawable-xhdpi/indicator_code_lock_point_area_green.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/indicator_code_lock_point_area_green_holo.png b/core/res/res/drawable-xhdpi/indicator_code_lock_point_area_green_holo.png
index 4491f02..de4ca91 100644
--- a/core/res/res/drawable-xhdpi/indicator_code_lock_point_area_green_holo.png
+++ b/core/res/res/drawable-xhdpi/indicator_code_lock_point_area_green_holo.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/indicator_code_lock_point_area_red_holo.png b/core/res/res/drawable-xhdpi/indicator_code_lock_point_area_red_holo.png
index 6e91fbc..853b0f0 100644
--- a/core/res/res/drawable-xhdpi/indicator_code_lock_point_area_red_holo.png
+++ b/core/res/res/drawable-xhdpi/indicator_code_lock_point_area_red_holo.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/stat_notify_wifi_in_range.png b/core/res/res/drawable-xhdpi/stat_notify_wifi_in_range.png
index 1909183..6bb7512 100644
--- a/core/res/res/drawable-xhdpi/stat_notify_wifi_in_range.png
+++ b/core/res/res/drawable-xhdpi/stat_notify_wifi_in_range.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/vpn_connected.png b/core/res/res/drawable-xhdpi/vpn_connected.png
index 5d37ffc..1f46be2 100644
--- a/core/res/res/drawable-xhdpi/vpn_connected.png
+++ b/core/res/res/drawable-xhdpi/vpn_connected.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/vpn_disconnected.png b/core/res/res/drawable-xhdpi/vpn_disconnected.png
index dd9ba92..847d3f5 100644
--- a/core/res/res/drawable-xhdpi/vpn_disconnected.png
+++ b/core/res/res/drawable-xhdpi/vpn_disconnected.png
Binary files differ
diff --git a/core/res/res/drawable-xlarge-hdpi/indicator_code_lock_drag_direction_green_up.png b/core/res/res/drawable-xlarge-hdpi/indicator_code_lock_drag_direction_green_up.png
deleted file mode 100644
index c605607..0000000
--- a/core/res/res/drawable-xlarge-hdpi/indicator_code_lock_drag_direction_green_up.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/layout/keyguard_screen_password_landscape.xml b/core/res/res/layout/keyguard_screen_password_landscape.xml
index 3343d8b..8bc5f34 100644
--- a/core/res/res/layout/keyguard_screen_password_landscape.xml
+++ b/core/res/res/layout/keyguard_screen_password_landscape.xml
@@ -191,4 +191,17 @@
         android:layout_height="0dip"
         />
 
+    <!-- Area to overlay FaceLock -->
+    <TextView android:id="@+id/faceLockAreaView"
+        android:visibility="gone"
+        android:layout_row="0"
+        android:layout_column="2"
+        android:layout_rowSpan="8"
+        android:layout_columnSpan="1"
+        android:layout_gravity="fill"
+        android:layout_width="0dip"
+        android:layout_height="0dip"
+        android:background="@color/facelock_color_background"
+    />
+
 </GridLayout>
diff --git a/core/res/res/layout/keyguard_screen_unlock_landscape.xml b/core/res/res/layout/keyguard_screen_unlock_landscape.xml
index d71dbff..2778f4e 100644
--- a/core/res/res/layout/keyguard_screen_unlock_landscape.xml
+++ b/core/res/res/layout/keyguard_screen_unlock_landscape.xml
@@ -160,4 +160,18 @@
         android:layout_height="0dip"
         />
 
+    <!-- Area to overlay FaceLock -->
+    <TextView android:id="@+id/faceLockAreaView"
+        android:visibility="gone"
+        android:layout_row="0"
+        android:layout_column="1"
+        android:layout_rowSpan="7"
+        android:layout_columnSpan="1"
+        android:layout_gravity="fill"
+        android:layout_marginLeft="8dip"
+        android:layout_width="0dip"
+        android:layout_height="0dip"
+        android:background="@color/facelock_color_background"
+    />
+
 </GridLayout>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 5eb3e5a..ae39760 100755
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -138,6 +138,18 @@
         <item>"0,1"</item>
     </string-array>
 
+    <!-- Set of NetworkInfo.getType() that reflect data usage. -->
+    <integer-array translatable="false" name="config_data_usage_network_types">
+        <item>0</item> <!-- TYPE_MOBILE -->
+        <item>2</item> <!-- TYPE_MOBILE_MMS -->
+        <item>3</item> <!-- TYPE_MOBILE_SUPL -->
+        <item>4</item> <!-- TYPE_MOBILE_DUN -->
+        <item>5</item> <!-- TYPE_MOBILE_HIPRI -->
+        <item>10</item> <!-- TYPE_MOBILE_FOTA -->
+        <item>11</item> <!-- TYPE_MOBILE_IMS -->
+        <item>12</item> <!-- TYPE_MOBILE_CBS -->
+    </integer-array>
+
     <!-- The maximum duration (in milliseconds) we expect a network transition to take -->
     <integer name="config_networkTransitionTimeout">60000</integer>
 
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index e093fa9..2d5d4cc 100755
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -41,9 +41,13 @@
     <string name="untitled">&lt;untitled&gt;</string>
 
     <!-- Used to replace a range of characters in text that is too wide
-         for the space allocated to it. -->
+         for the space allocated to it (three dots). -->
     <string name="ellipsis">\u2026</string>
 
+    <!-- Used to replace a range of characters in text that is too wide
+         for the space allocated to it (two dots). -->
+    <string name="ellipsis_two_dots">\u2025</string>
+
     <!-- How to display the lack of a phone number -->
     <string name="emptyPhoneNumber">(No phone number)</string>
 
diff --git a/core/tests/coretests/apks/install_verifier_bad/Android.mk b/core/tests/coretests/apks/install_verifier_bad/Android.mk
new file mode 100644
index 0000000..b50cfd04
--- /dev/null
+++ b/core/tests/coretests/apks/install_verifier_bad/Android.mk
@@ -0,0 +1,11 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+LOCAL_PACKAGE_NAME := FrameworkCoreTests_install_verifier_bad
+
+include $(BUILD_PACKAGE)
+
diff --git a/core/tests/coretests/apks/install_verifier_bad/AndroidManifest.xml b/core/tests/coretests/apks/install_verifier_bad/AndroidManifest.xml
new file mode 100644
index 0000000..0170cdd
--- /dev/null
+++ b/core/tests/coretests/apks/install_verifier_bad/AndroidManifest.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+        package="com.android.frameworks.coretests.install_verifier_bad">
+
+    <package-verifier android:name="com.android.frameworks.coretests.nonexistent" android:publicKey="Zm9vYmFy" />
+        
+    <application android:hasCode="false">
+    </application>
+</manifest>
diff --git a/core/tests/coretests/apks/install_verifier_bad/res/values/strings.xml b/core/tests/coretests/apks/install_verifier_bad/res/values/strings.xml
new file mode 100644
index 0000000..3b8b3b1
--- /dev/null
+++ b/core/tests/coretests/apks/install_verifier_bad/res/values/strings.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!-- Just need this dummy file to have something to build. -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string name="dummy">dummy</string>
+</resources>
diff --git a/core/tests/coretests/apks/install_verifier_good/Android.mk b/core/tests/coretests/apks/install_verifier_good/Android.mk
new file mode 100644
index 0000000..a48a80e
--- /dev/null
+++ b/core/tests/coretests/apks/install_verifier_good/Android.mk
@@ -0,0 +1,10 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+LOCAL_PACKAGE_NAME := FrameworkCoreTests_install_verifier_good
+
+include $(BUILD_PACKAGE)
diff --git a/core/tests/coretests/apks/install_verifier_good/AndroidManifest.xml b/core/tests/coretests/apks/install_verifier_good/AndroidManifest.xml
new file mode 100644
index 0000000..90135a5
--- /dev/null
+++ b/core/tests/coretests/apks/install_verifier_good/AndroidManifest.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+        package="com.android.frameworks.coretests.install_verifier_bad">
+
+        <package-verifier android:name="com.android.frameworks.coretests" android:publicKey="MIIBIDANBgkqhkiG9w0BAQEFAAOCAQ0AMIIBCAKCAQEAnHgFkqwNXTgc3qpl7MimAG42SAxtcgexIBG+UIY6q+K1XQCa33FG1vIgIoDHzU172yYkO4qAbCazSxN1I6SSaCJJBNwBST58Cs8aBch09psDe2AwnZB00kKA4WutKoc0NhlR6vcqSC0JsgSxh14SrJjBqnc9aAC56v3lbVi+2OjaFvmjYAmcN6g0pt/tt7a0SgSeB6Jp/M8sVJbyzzbWTfkKO42PNKO6q0z1M3GrJ3GbO6WHVK0MU/wU4dtF1R4jT7vpPJuk7fnOVCYTUOxTVge/aaL/SqB9tffqIA0JpsG0niFAL4ntEZCJOqtakYDxUugvhaRXU89fwZBxxe7IJwIBAw==" />
+
+    <application android:hasCode="false">
+    </application>
+</manifest>
diff --git a/core/tests/coretests/apks/install_verifier_good/res/values/strings.xml b/core/tests/coretests/apks/install_verifier_good/res/values/strings.xml
new file mode 100644
index 0000000..3b8b3b1
--- /dev/null
+++ b/core/tests/coretests/apks/install_verifier_good/res/values/strings.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!-- Just need this dummy file to have something to build. -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+  <string name="dummy">dummy</string>
+</resources>
diff --git a/core/tests/coretests/src/android/net/http/AbstractProxyTest.java b/core/tests/coretests/src/android/net/http/AbstractProxyTest.java
index ee4ce95..4891232 100644
--- a/core/tests/coretests/src/android/net/http/AbstractProxyTest.java
+++ b/core/tests/coretests/src/android/net/http/AbstractProxyTest.java
@@ -219,6 +219,23 @@
         assertEquals("GET /bar HTTP/1.1", recordedRequest.getRequestLine());
     }
 
+    // http://b/5372438
+    public void testRetryWithProxy() throws Exception {
+        server.enqueue(new MockResponse()
+                .setSocketPolicy(SocketPolicy.DISCONNECT_AT_START));
+        server.play();
+
+        HttpClient httpProxyClient = newHttpClient();
+        HttpGet request = new HttpGet("http://android.com/foo");
+        ProxyConfig.REQUEST_PARAMETER.configure(server, httpProxyClient, request);
+
+        try {
+            httpProxyClient.execute(request);
+            fail();
+        } catch (IOException expected) {
+        }
+    }
+
     enum ProxyConfig {
         PROXY_SYSTEM_PROPERTY() {
             @Override void configure(MockWebServer server, HttpClient client, HttpRequest request) {
diff --git a/data/sounds/effects/ogg/Effect_Tick.ogg b/data/sounds/effects/ogg/Effect_Tick.ogg
index b379019..c8a5c36 100644
--- a/data/sounds/effects/ogg/Effect_Tick.ogg
+++ b/data/sounds/effects/ogg/Effect_Tick.ogg
Binary files differ
diff --git a/data/sounds/effects/ogg/KeypressDelete_14.ogg b/data/sounds/effects/ogg/KeypressDelete_14.ogg
index aa4349d..0baea25 100644
--- a/data/sounds/effects/ogg/KeypressDelete_14.ogg
+++ b/data/sounds/effects/ogg/KeypressDelete_14.ogg
Binary files differ
diff --git a/data/sounds/effects/ogg/KeypressDelete_49.ogg b/data/sounds/effects/ogg/KeypressDelete_49.ogg
index aa4349d..f5e9deb 100644
--- a/data/sounds/effects/ogg/KeypressDelete_49.ogg
+++ b/data/sounds/effects/ogg/KeypressDelete_49.ogg
Binary files differ
diff --git a/data/sounds/effects/ogg/KeypressReturn_14.ogg b/data/sounds/effects/ogg/KeypressReturn_14.ogg
index 2244a42..86a5a0e 100644
--- a/data/sounds/effects/ogg/KeypressReturn_14.ogg
+++ b/data/sounds/effects/ogg/KeypressReturn_14.ogg
Binary files differ
diff --git a/data/sounds/effects/ogg/KeypressReturn_49.ogg b/data/sounds/effects/ogg/KeypressReturn_49.ogg
index 2244a42..b0ddee5 100644
--- a/data/sounds/effects/ogg/KeypressReturn_49.ogg
+++ b/data/sounds/effects/ogg/KeypressReturn_49.ogg
Binary files differ
diff --git a/data/sounds/effects/ogg/KeypressSpacebar_14.ogg b/data/sounds/effects/ogg/KeypressSpacebar_14.ogg
index 56ea15e..058534a 100644
--- a/data/sounds/effects/ogg/KeypressSpacebar_14.ogg
+++ b/data/sounds/effects/ogg/KeypressSpacebar_14.ogg
Binary files differ
diff --git a/data/sounds/effects/ogg/KeypressSpacebar_49.ogg b/data/sounds/effects/ogg/KeypressSpacebar_49.ogg
index 56ea15e..3866e0e9 100644
--- a/data/sounds/effects/ogg/KeypressSpacebar_49.ogg
+++ b/data/sounds/effects/ogg/KeypressSpacebar_49.ogg
Binary files differ
diff --git a/data/sounds/effects/ogg/KeypressStandard_14.ogg b/data/sounds/effects/ogg/KeypressStandard_14.ogg
index 8df7214..317c8f3 100644
--- a/data/sounds/effects/ogg/KeypressStandard_14.ogg
+++ b/data/sounds/effects/ogg/KeypressStandard_14.ogg
Binary files differ
diff --git a/data/sounds/effects/ogg/KeypressStandard_49.ogg b/data/sounds/effects/ogg/KeypressStandard_49.ogg
index 8df7214..893bb52 100644
--- a/data/sounds/effects/ogg/KeypressStandard_49.ogg
+++ b/data/sounds/effects/ogg/KeypressStandard_49.ogg
Binary files differ
diff --git a/docs/html/guide/practices/design/jni.jd b/docs/html/guide/practices/design/jni.jd
index 6e984b0..9980efd 100644
--- a/docs/html/guide/practices/design/jni.jd
+++ b/docs/html/guide/practices/design/jni.jd
@@ -26,9 +26,9 @@
 </div>
 </div>
 
-<p>JNI is the Java Native Interface.  It defines a way for code written in the
-Java programming language to interact with native
-code: functions written in C/C++.  It's VM-neutral, has support for loading code from
+<p>JNI is the Java Native Interface.  It defines a way for managed code
+(written in the Java programming language) to interact with native
+code (written in C/C++).  It's vendor-neutral, has support for loading code from
 dynamic shared libraries, and while cumbersome at times is reasonably efficient.</p>
 
 <p>You really should read through the
@@ -46,13 +46,13 @@
 pointers to pointers to function tables.  (In the C++ version, they're classes with a
 pointer to a function table and a member function for each JNI function that indirects through
 the table.)  The JavaVM provides the "invocation interface" functions,
-which allow you to create and destroy the VM.  In theory you can have multiple VMs per process,
-but Android's VM only allows one.</p>
+which allow you to create and destroy a JavaVM.  In theory you can have multiple JavaVMs per process,
+but Android only allows one.</p>
 
 <p>The JNIEnv provides most of the JNI functions.  Your native functions all receive a JNIEnv as
 the first argument.</p>
 
-<p>On some VMs, the JNIEnv is used for thread-local storage.  For this reason, <strong>you cannot share a JNIEnv between threads</strong>.
+<p>The JNIEnv is used for thread-local storage.  For this reason, <strong>you cannot share a JNIEnv between threads</strong>.
 If a piece of code has no other way to get its JNIEnv, you should share
 the JavaVM, and use <code>GetEnv</code> to discover the thread's JNIEnv. (Assuming it has one; see <code>AttachCurrentThread</code> below.)</p>
 
@@ -66,23 +66,22 @@
 <a name="threads" id="threads"></a>
 <h2>Threads</h2>
 
-<p>All VM threads are Linux threads, scheduled by the kernel.  They're usually
-started using Java language features (notably <code>Thread.start</code>),
-but they can also be created elsewhere and then attached to the VM.  For
+<p>All threads are Linux threads, scheduled by the kernel.  They're usually
+started from managed code (using <code>Thread.start</code>),
+but they can also be created elsewhere and then attached to the JavaVM.  For
 example, a thread started with <code>pthread_create</code> can be attached
 with the JNI <code>AttachCurrentThread</code> or
 <code>AttachCurrentThreadAsDaemon</code> functions.  Until a thread is
-attached to the VM, it has no JNIEnv, and
-<strong>cannot make JNI calls</strong>.</p>
+attached, it has no JNIEnv, and <strong>cannot make JNI calls</strong>.</p>
 
-<p>Attaching a natively-created thread causes the VM to allocate and initialize
-a <code>Thread</code> object, add it to the "main" <code>ThreadGroup</code>,
-and add the thread to the set that is visible to the debugger.  Calling
-<code>AttachCurrentThread</code> on an already-attached thread is a no-op.</p>
+<p>Attaching a natively-created thread causes a <code>java.lang.Thread</code>
+object to be constructed and added to the "main" <code>ThreadGroup</code>,
+making it visible to the debugger.  Calling <code>AttachCurrentThread</code>
+on an already-attached thread is a no-op.</p>
 
-<p>The Dalvik VM does not suspend threads executing native code.  If
+<p>Android does not suspend threads executing native code.  If
 garbage collection is in progress, or the debugger has issued a suspend
-request, the VM will pause the thread the next time it makes a JNI call.</p>
+request, Android will pause the thread the next time it makes a JNI call.</p>
 
 <p>Threads attached through JNI <strong>must call
 <code>DetachCurrentThread</code> before they exit</strong>.
@@ -108,12 +107,12 @@
 </ul>
 
 <p>Similarly, to call a method, you'd first get a class object reference and then a method ID.  The IDs are often just
-pointers to internal VM data structures.  Looking them up may require several string
+pointers to internal runtime data structures.  Looking them up may require several string
 comparisons, but once you have them the actual call to get the field or invoke the method
 is very quick.</p>
 
 <p>If performance is important, it's useful to look the values up once and cache the results
-in your native code.  Because there is a limit of one VM per process, it's reasonable
+in your native code.  Because there is a limit of one JavaVM per process, it's reasonable
 to store this data in a static local structure.</p>
 
 <p>The class references, field IDs, and method IDs are guaranteed valid until the class is unloaded.  Classes
@@ -145,13 +144,17 @@
 <a name="local_and_global_references" id="local_and_global_references"></a>
 <h2>Local and Global References</h2>
 
-<p>Every object that JNI returns is a "local reference".  This means that it's valid for the
+<p>Every argument passed to a native method, and almost every object returned
+by a JNI function is a "local reference".  This means that it's valid for the
 duration of the current native method in the current thread.
-<strong>Even if the object itself continues to live on after the native method returns, the reference is not valid.</strong>
-This applies to all sub-classes of <code>jobject</code>, including
+<strong>Even if the object itself continues to live on after the native method
+returns, the reference is not valid.</strong>
+<p>This applies to all sub-classes of <code>jobject</code>, including
 <code>jclass</code>, <code>jstring</code>, and <code>jarray</code>.
-(Dalvik VM will warn you about most reference mis-uses when extended JNI
+(The runtime will warn you about most reference mis-uses when extended JNI
 checks are enabled.)</p>
+<p>The only way to get non-local references is via the functions
+<code>NewGlobalRef</code> and <code>NewWeakGlobalRef</code>.
 
 <p>If you want to hold on to a reference for a longer period, you must use
 a "global" reference.  The <code>NewGlobalRef</code> function takes the
@@ -159,7 +162,7 @@
 The global reference is guaranteed to be valid until you call
 <code>DeleteGlobalRef</code>.</p>
 
-<p>This pattern is commonly used when caching copies of class objects obtained
+<p>This pattern is commonly used when caching a jclass returned
 from <code>FindClass</code>, e.g.:</p>
 <pre>jclass localClass = env-&gt;FindClass("MyClass");
 jclass globalClass = reinterpret_cast&lt;jclass&gt;(env-&gt;NewGlobalRef(localClass));</pre>
@@ -181,22 +184,25 @@
 
 <p>Programmers are required to "not excessively allocate" local references.  In practical terms this means
 that if you're creating large numbers of local references, perhaps while running through an array of
-Objects, you should free them manually with
+objects, you should free them manually with
 <code>DeleteLocalRef</code> instead of letting JNI do it for you.  The
-VM is only required to reserve slots for
+implementation is only required to reserve slots for
 16 local references, so if you need more than that you should either delete as you go or use
-<code>EnsureLocalCapacity</code> to reserve more.</p>
+<code>EnsureLocalCapacity</code>/<code>PushLocalFrame</code> to reserve more.</p>
 
-<p>Note that <code>jfieldID</code>s and <code>jmethodID</code>s are just integers, not object
-references, and should not be passed to <code>NewGlobalRef</code>.  The raw data
+<p>Note that <code>jfieldID</code>s and <code>jmethodID</code>s are opaque
+types, not object references, and should not be passed to
+<code>NewGlobalRef</code>.  The raw data
 pointers returned by functions like <code>GetStringUTFChars</code>
-and <code>GetByteArrayElements</code> are also not objects.</p>
+and <code>GetByteArrayElements</code> are also not objects. (They may be passed
+between threads, and are valid until the matching Release call.)</p>
 
 <p>One unusual case deserves separate mention.  If you attach a native
-thread to the VM with <code>AttachCurrentThread</code>, the code you are running will
-never "return" to the VM until the thread detaches from the VM.  Any local
-references you create will have to be deleted manually unless you're going
-to detach the thread soon.</p>
+thread with <code>AttachCurrentThread</code>, the code you are running will
+never automatically free local references until the thread detaches.  Any local
+references you create will have to be deleted manually. In general, any native
+code that creates local references in a loop probably needs to do some manual
+deletion.</p>
 
 <a name="UTF_8_and_UTF_16_strings" id="UTF_8_and_UTF_16_strings"></a>
 <h2>UTF-8 and UTF-16 Strings</h2>
@@ -205,14 +211,15 @@
 modified encoding is useful for C code because it encodes \u0000 as 0xc0 0x80 instead of 0x00.
 The nice thing about this is that you can count on having C-style zero-terminated strings,
 suitable for use with standard libc string functions.  The down side is that you cannot pass
-arbitrary UTF-8 data into the VM and expect it to work correctly.</p>
+arbitrary UTF-8 data to JNI and expect it to work correctly.</p>
 
-<p>It's usually best to operate with UTF-16 strings.  With Android's current VMs, the
-<code>GetStringChars</code> method
-does not require a copy, whereas <code>GetStringUTFChars</code> requires a malloc and a UTF conversion.  Note that
+<p>If possible, it's usually faster to operate with UTF-16 strings. Android
+currently does not require a copy in <code>GetStringChars</code>, whereas
+<code>GetStringUTFChars</code> requires an allocation and a conversion to
+UTF-8.  Note that
 <strong>UTF-16 strings are not zero-terminated</strong>, and \u0000 is allowed,
 so you need to hang on to the string length as well as
-the string pointer.</p>
+the jchar pointer.</p>
 
 <p><strong>Don't forget to <code>Release</code> the strings you <code>Get</code></strong>.  The
 string functions return <code>jchar*</code> or <code>jbyte*</code>, which
@@ -237,9 +244,8 @@
 primitives can be read and written directly as if they were declared in C.</p>
 
 <p>To make the interface as efficient as possible without constraining
-the VM implementation,
-the <code>Get&lt;PrimitiveType&gt;ArrayElements</code> family of calls
-allows the VM to either return a pointer to the actual elements, or
+the VM implementation, the <code>Get&lt;PrimitiveType&gt;ArrayElements</code>
+family of calls allows the runtime to either return a pointer to the actual elements, or
 allocate some memory and make a copy.  Either way, the raw pointer returned
 is guaranteed to be valid until the corresponding <code>Release</code> call
 is issued (which implies that, if the data wasn't copied, the array object
@@ -253,7 +259,7 @@
 useful.</p>
 
 <p>The <code>Release</code> call takes a <code>mode</code> argument that can
-have one of three values.  The actions performed by the VM depend upon
+have one of three values.  The actions performed by the runtime depend upon
 whether it returned a pointer to the actual data or a copy of it:</p>
 
 <ul>
@@ -312,8 +318,9 @@
     }</pre>
 
 <p>This grabs the array, copies the first <code>len</code> byte
-elements out of it, and then releases the array.  Depending upon the VM
-policies the <code>Get</code> call will either pin or copy the array contents.
+elements out of it, and then releases the array.  Depending upon the
+implementation, the <code>Get</code> call will either pin or copy the array
+contents.
 The code copies the data (for perhaps a second time), then calls <code>Release</code>; in this case
 <code>JNI_ABORT</code> ensures there's no chance of a third copy.</p>
 
@@ -335,7 +342,7 @@
 
 
 <a name="exceptions" id="exceptions"></a>
-<h2>Exception</h2>
+<h2>Exceptions</h2>
 
 <p><strong>You must not call most JNI functions while an exception is pending.</strong>
 Your code is expected to notice the exception (via the function's return value,
@@ -369,11 +376,11 @@
 you must always check for an exception, because the return value is not
 going to be valid if an exception was thrown.</p>
 
-<p>Note that exceptions thrown by interpreted code do not "leap over" native code,
-and C++ exceptions thrown by native code are not handled by Dalvik.
+<p>Note that exceptions thrown by interpreted code do not unwind native stack
+frames, and Android does not yet support C++ exceptions.
 The JNI <code>Throw</code> and <code>ThrowNew</code> instructions just
-set an exception pointer in the current thread.  Upon returning to the VM from
-native code, the exception will be noted and handled appropriately.</p>
+set an exception pointer in the current thread.  Upon returning to managed
+from native code, the exception will be noted and handled appropriately.</p>
 
 <p>Native code can "catch" an exception by calling <code>ExceptionCheck</code> or
 <code>ExceptionOccurred</code>, and clear it with
@@ -476,23 +483,19 @@
 shared library.  For Android apps, you may find it useful to get the full
 path to the application's private data storage area from the context object.</p>
 
-<p>This is the recommended approach, but not the only approach.  The VM does
-not require explicit registration, nor that you provide a
+<p>This is the recommended approach, but not the only approach.  Explicit
+registration is not required, nor is it necessary that you provide a
 <code>JNI_OnLoad</code> function.
 You can instead use "discovery" of native methods that are named in a
-specific way (see <a href="http://java.sun.com/javase/6/docs/technotes/guides/jni/spec/design.html#wp615">
-    the JNI spec</a> for details), though this is less desirable.
-It requires more space in the shared object symbol table,
-loading is slower because it requires string searches through all of the
-loaded shared libraries, and if a method signature is wrong you won't know
+specific way (see <a href="http://java.sun.com/javase/6/docs/technotes/guides/jni/spec/design.html#wp615">the JNI spec</a> for details), though this is less desirable because if a method signature is wrong you won't know
 about it until the first time the method is actually used.</p>
 
 <p>One other note about <code>JNI_OnLoad</code>: any <code>FindClass</code>
 calls you make from there will happen in the context of the class loader
 that was used to load the shared library.  Normally <code>FindClass</code>
 uses the loader associated with the method at the top of the interpreted
-stack, or if there isn't one (because the thread was just attached to
-the VM) it uses the "system" class loader.  This makes
+stack, or if there isn't one (because the thread was just attached) it uses
+the "system" class loader.  This makes
 <code>JNI_OnLoad</code> a convenient place to look up and cache class
 object references.</p>
 
@@ -515,10 +518,9 @@
 
 <p>All JNI 1.6 features are supported, with the following exceptions:</p>
 <ul>
-    <li><code>DefineClass</code> is not implemented.  Dalvik does not use
+    <li><code>DefineClass</code> is not implemented.  Android does not use
     Java bytecodes or class files, so passing in binary class data
-    doesn't work.  Translation facilities may be added in a future
-    version of the VM.</li>
+    doesn't work.</li>
     <li>"Weak global" references are implemented, but may only be passed
     to <code>NewLocalRef</code>, <code>NewGlobalRef</code>, and
     <code>DeleteWeakGlobalRef</code>.  (The spec strongly encourages
@@ -536,12 +538,16 @@
     around this requires using explicit registration or moving the
     native methods out of inner classes.
     <li>Until Android 2.0 (Eclair), it was not possible to use a <code>pthread_key_create</code>
-    destructor function to avoid the VM's "thread must be detached before
-    exit" check.  (The VM also uses a pthread key destructor function,
+    destructor function to avoid the "thread must be detached before
+    exit" check.  (The runtime also uses a pthread key destructor function,
     so it'd be a race to see which gets called first.)
     <li>Until Android 2.2 (Froyo), weak global references were not implemented.
-    Older VMs will vigorously reject attempts to use them.  You can use
+    Older versions will vigorously reject attempts to use them.  You can use
     the Android platform version constants to test for support.
+    <li>Until Android 4.0 (Ice Cream Sandwich), JNI local references were
+    actually direct pointers. Ice Cream Sandwich added the indirection
+    necessary to support better garbage collectors, but this means that lots
+    of JNI bugs are undetectable on older releases.
 </ul>
 
 
@@ -572,8 +578,8 @@
 <p>In logcat, you'll see:</p>
 <pre>W/dalvikvm(  880): No implementation found for native LFoo;.myfunc ()V</pre>
 
-<p>This means that the VM tried to find a matching method but was unsuccessful.
-Some common reasons for this are:</p>
+<p>This means that the runtime tried to find a matching method but was
+unsuccessful.  Some common reasons for this are:</p>
 <ul>
     <li>The library isn't getting loaded.  Check the logcat output for
     messages about library loading.
@@ -581,10 +587,15 @@
     is commonly caused by:
     <ul>
         <li>For lazy method lookup, failing to declare C++ functions
-        with <code>extern "C"</code>.  You can use <code>arm-eabi-nm</code>
+        with <code>extern "C"</code> and appropriate
+        visibility (<code>JNIEXPORT</code>). Note that prior to Ice Cream
+        Sandwich, the JNIEXPORT macro was incorrect, so using a new GCC with
+        an old <code>jni.h</code> won't work.
+        You can use <code>arm-eabi-nm</code>
         to see the symbols as they appear in the library; if they look
         mangled (something like <code>_Z15Java_Foo_myfuncP7_JNIEnvP7_jclass</code>
-        rather than <code>Java_Foo_myfunc</code>) then you need to
+        rather than <code>Java_Foo_myfunc</code>), or if the symbol type is
+        a lowercase 't' rather than an uppercase 'T', then you need to
         adjust the declaration.
         <li>For explicit registration, minor errors when entering the
         method signature.  Make sure that what you're passing to the
@@ -612,7 +623,7 @@
 
 <p>If the class name looks right, you could be running into a class loader
 issue.  <code>FindClass</code> wants to start the class search in the
-class loader associated with your code.  It examines the VM call stack,
+class loader associated with your code.  It examines the call stack,
 which will look something like:
 <pre>    Foo.myfunc(Native Method)
     Foo.main(Foo.java:10)
@@ -623,14 +634,14 @@
 class and uses that.</p>
 
 <p>This usually does what you want.  You can get into trouble if you
-create a thread outside the VM (perhaps by calling <code>pthread_create</code>
-and then attaching it to the VM with <code>AttachCurrentThread</code>).
+create a thread yourself (perhaps by calling <code>pthread_create</code>
+and then attaching it with <code>AttachCurrentThread</code>).
 Now the stack trace looks like this:</p>
 <pre>    dalvik.system.NativeStart.run(Native Method)</pre>
 
 <p>The topmost method is <code>NativeStart.run</code>, which isn't part of
 your application.  If you call <code>FindClass</code> from this thread, the
-VM will start in the "system" class loader instead of the one associated
+JavaVM will start in the "system" class loader instead of the one associated
 with your application, so attempts to find app-specific classes will fail.</p>
 
 <p>There are a few ways to work around this:</p>
@@ -656,12 +667,12 @@
 <h2>FAQ: How do I share raw data with native code?</h2>
 
 <p>You may find yourself in a situation where you need to access a large
-buffer of raw data from code written in Java and C/C++.  Common examples
+buffer of raw data from both managed and native code.  Common examples
 include manipulation of bitmaps or sound samples.  There are two
 basic approaches.</p>
 
 <p>You can store the data in a <code>byte[]</code>.  This allows very fast
-access from code written in Java.  On the native side, however, you're
+access from managed code.  On the native side, however, you're
 not guaranteed to be able to access the data without having to copy it.  In
 some implementations, <code>GetByteArrayElements</code> and
 <code>GetPrimitiveArrayCritical</code> will return actual pointers to the
@@ -674,8 +685,8 @@
 byte buffers, the storage is not allocated on the managed heap, and can
 always be accessed directly from native code (get the address
 with <code>GetDirectBufferAddress</code>).  Depending on how direct
-byte buffer access is implemented in the VM, accessing the data from code
-written in Java can be very slow.</p>
+byte buffer access is implemented, accessing the data from managed code
+can be very slow.</p>
 
 <p>The choice of which to use depends on two factors:</p>
 <ol>
@@ -688,5 +699,4 @@
 </ol>
 
 <p>If there's no clear winner, use a direct byte buffer.  Support for them
-is built directly into JNI, and access to them from code written in
-Java can be made faster with VM improvements.</p>
+is built directly into JNI, and performance should improve in future releases.</p>
diff --git a/graphics/java/android/renderscript/ProgramRaster.java b/graphics/java/android/renderscript/ProgramRaster.java
index bc0d928..60d9698 100644
--- a/graphics/java/android/renderscript/ProgramRaster.java
+++ b/graphics/java/android/renderscript/ProgramRaster.java
@@ -84,14 +84,10 @@
     public static class Builder {
         RenderScript mRS;
         boolean mPointSprite;
-        boolean mPointSmooth;
-        boolean mLineSmooth;
         CullMode mCullMode;
 
         public Builder(RenderScript rs) {
             mRS = rs;
-            mPointSmooth = false;
-            mLineSmooth = false;
             mPointSprite = false;
             mCullMode = CullMode.BACK;
         }
@@ -108,8 +104,7 @@
 
         public ProgramRaster create() {
             mRS.validate();
-            int id = mRS.nProgramRasterCreate(mPointSmooth, mLineSmooth, mPointSprite,
-                                             1.f, mCullMode.mID);
+            int id = mRS.nProgramRasterCreate(mPointSprite, mCullMode.mID);
             return new ProgramRaster(id, mRS);
         }
     }
diff --git a/graphics/java/android/renderscript/RenderScript.java b/graphics/java/android/renderscript/RenderScript.java
index 571b895..e2950d5e 100644
--- a/graphics/java/android/renderscript/RenderScript.java
+++ b/graphics/java/android/renderscript/RenderScript.java
@@ -522,13 +522,10 @@
                                      dstMode, depthFunc);
     }
 
-    native int  rsnProgramRasterCreate(int con, boolean pointSmooth, boolean lineSmooth,
-                                       boolean pointSprite, float lineWidth, int cullMode);
-    synchronized int nProgramRasterCreate(boolean pointSmooth, boolean lineSmooth,
-                                          boolean pointSprite, float lineWidth, int cullMode) {
+    native int  rsnProgramRasterCreate(int con, boolean pointSprite, int cullMode);
+    synchronized int nProgramRasterCreate(boolean pointSprite, int cullMode) {
         validate();
-        return rsnProgramRasterCreate(mContext, pointSmooth, lineSmooth, pointSprite, lineWidth,
-                                      cullMode);
+        return rsnProgramRasterCreate(mContext, pointSprite, cullMode);
     }
 
     native void rsnProgramBindConstants(int con, int pv, int slot, int mID);
diff --git a/graphics/jni/android_renderscript_RenderScript.cpp b/graphics/jni/android_renderscript_RenderScript.cpp
index d7ac5d8..ec1f8de 100644
--- a/graphics/jni/android_renderscript_RenderScript.cpp
+++ b/graphics/jni/android_renderscript_RenderScript.cpp
@@ -1053,12 +1053,10 @@
 // ---------------------------------------------------------------------------
 
 static jint
-nProgramRasterCreate(JNIEnv *_env, jobject _this, RsContext con, jboolean pointSmooth,
-                     jboolean lineSmooth, jboolean pointSprite, jfloat lineWidth, jint cull)
+nProgramRasterCreate(JNIEnv *_env, jobject _this, RsContext con, jboolean pointSprite, jint cull)
 {
-    LOG_API("nProgramRasterCreate, con(%p), pointSmooth(%i), lineSmooth(%i), pointSprite(%i)",
-            con, pointSmooth, lineSmooth, pointSprite);
-    return (jint)rsProgramRasterCreate(con, pointSmooth, lineSmooth, pointSprite, lineWidth, (RsCullMode)cull);
+    LOG_API("nProgramRasterCreate, con(%p), pointSprite(%i), cull(%i)", con, pointSprite, cull);
+    return (jint)rsProgramRasterCreate(con, pointSprite, (RsCullMode)cull);
 }
 
 
@@ -1295,7 +1293,7 @@
 {"rsnProgramBindSampler",            "(IIII)V",                               (void*)nProgramBindSampler },
 
 {"rsnProgramFragmentCreate",         "(ILjava/lang/String;[I)I",              (void*)nProgramFragmentCreate },
-{"rsnProgramRasterCreate",           "(IZZZFI)I",                             (void*)nProgramRasterCreate },
+{"rsnProgramRasterCreate",           "(IZI)I",                                (void*)nProgramRasterCreate },
 {"rsnProgramVertexCreate",           "(ILjava/lang/String;[I)I",              (void*)nProgramVertexCreate },
 
 {"rsnContextBindRootScript",         "(II)V",                                 (void*)nContextBindRootScript },
diff --git a/include/gui/SurfaceTexture.h b/include/gui/SurfaceTexture.h
index 493993d..926eb9a 100644
--- a/include/gui/SurfaceTexture.h
+++ b/include/gui/SurfaceTexture.h
@@ -25,8 +25,9 @@
 
 #include <ui/GraphicBuffer.h>
 
-#include <utils/threads.h>
+#include <utils/String8.h>
 #include <utils/Vector.h>
+#include <utils/threads.h>
 
 #define ANDROID_GRAPHICS_SURFACETEXTURE_JNI_ID "mSurfaceTexture"
 
@@ -202,6 +203,10 @@
     // by OpenGL ES as a texture) then those buffer will remain allocated.
     void abandon();
 
+    // set the name of the SurfaceTexture that will be used to identify it in
+    // log messages.
+    void setName(const String8& name);
+
     // dump our state in a String
     void dump(String8& result) const;
     void dump(String8& result, const char* prefix, char* buffer, size_t SIZE) const;
@@ -444,6 +449,10 @@
     // all ISurfaceTexture methods capable of returning an error.
     bool mAbandoned;
 
+    // mName is a string used to identify the SurfaceTexture in log messages.
+    // It is set by the setName method.
+    String8 mName;
+
     // mMutex is the mutex used to prevent concurrent access to the member
     // variables of SurfaceTexture objects. It must be locked whenever the
     // member variables are accessed.
diff --git a/include/media/stagefright/ACodec.h b/include/media/stagefright/ACodec.h
index b7286e5..9da9907 100644
--- a/include/media/stagefright/ACodec.h
+++ b/include/media/stagefright/ACodec.h
@@ -113,6 +113,7 @@
 
     Vector<BufferInfo> mBuffers[2];
     bool mPortEOS[2];
+    status_t mInputEOSResult;
 
     List<sp<AMessage> > mDeferredQueue;
 
diff --git a/libs/gui/SurfaceTexture.cpp b/libs/gui/SurfaceTexture.cpp
index f2bc81e..dac9418 100644
--- a/libs/gui/SurfaceTexture.cpp
+++ b/libs/gui/SurfaceTexture.cpp
@@ -39,6 +39,12 @@
 
 #define ALLOW_DEQUEUE_CURRENT_BUFFER    false
 
+// Macros for including the SurfaceTexture name in log messages
+#define ST_LOGV(x, ...) LOGV("[%s] "x, mName.string(), ##__VA_ARGS__)
+#define ST_LOGD(x, ...) LOGD("[%s] "x, mName.string(), ##__VA_ARGS__)
+#define ST_LOGI(x, ...) LOGI("[%s] "x, mName.string(), ##__VA_ARGS__)
+#define ST_LOGW(x, ...) LOGW("[%s] "x, mName.string(), ##__VA_ARGS__)
+#define ST_LOGE(x, ...) LOGE("[%s] "x, mName.string(), ##__VA_ARGS__)
 
 namespace android {
 
@@ -82,6 +88,12 @@
 
 static void mtxMul(float out[16], const float a[16], const float b[16]);
 
+// Get an ID that's unique within this process.
+static int32_t createProcessUniqueId() {
+    static volatile int32_t globalCounter = 0;
+    return android_atomic_inc(&globalCounter);
+}
+
 SurfaceTexture::SurfaceTexture(GLuint tex, bool allowSynchronousMode) :
     mDefaultWidth(1),
     mDefaultHeight(1),
@@ -99,15 +111,19 @@
     mAllowSynchronousMode(allowSynchronousMode),
     mConnectedApi(NO_CONNECTED_API),
     mAbandoned(false) {
-    LOGV("SurfaceTexture::SurfaceTexture");
+    // Choose a name using the PID and a process-unique ID.
+    mName = String8::format("unnamed-%d-%d", getpid(), createProcessUniqueId());
+
+    ST_LOGV("SurfaceTexture::SurfaceTexture");
     sp<ISurfaceComposer> composer(ComposerService::getComposerService());
     mGraphicBufferAlloc = composer->createGraphicBufferAlloc();
     mNextCrop.makeInvalid();
-    memcpy(mCurrentTransformMatrix, mtxIdentity, sizeof(mCurrentTransformMatrix));
+    memcpy(mCurrentTransformMatrix, mtxIdentity,
+            sizeof(mCurrentTransformMatrix));
 }
 
 SurfaceTexture::~SurfaceTexture() {
-    LOGV("SurfaceTexture::~SurfaceTexture");
+    ST_LOGV("SurfaceTexture::~SurfaceTexture");
     freeAllBuffersLocked();
 }
 
@@ -151,22 +167,22 @@
 }
 
 status_t SurfaceTexture::setBufferCount(int bufferCount) {
-    LOGV("SurfaceTexture::setBufferCount");
+    ST_LOGV("SurfaceTexture::setBufferCount");
     Mutex::Autolock lock(mMutex);
 
     if (mAbandoned) {
-        LOGE("setBufferCount: SurfaceTexture has been abandoned!");
+        ST_LOGE("setBufferCount: SurfaceTexture has been abandoned!");
         return NO_INIT;
     }
     if (bufferCount > NUM_BUFFER_SLOTS) {
-        LOGE("setBufferCount: bufferCount larger than slots available");
+        ST_LOGE("setBufferCount: bufferCount larger than slots available");
         return BAD_VALUE;
     }
 
     // Error out if the user has dequeued buffers
     for (int i=0 ; i<mBufferCount ; i++) {
         if (mSlots[i].mBufferState == BufferSlot::DEQUEUED) {
-            LOGE("setBufferCount: client owns some buffers");
+            ST_LOGE("setBufferCount: client owns some buffers");
             return -EINVAL;
         }
     }
@@ -181,7 +197,7 @@
     }
 
     if (bufferCount < minBufferSlots) {
-        LOGE("setBufferCount: requested buffer count (%d) is less than "
+        ST_LOGE("setBufferCount: requested buffer count (%d) is less than "
                 "minimum (%d)", bufferCount, minBufferSlots);
         return BAD_VALUE;
     }
@@ -200,7 +216,8 @@
 status_t SurfaceTexture::setDefaultBufferSize(uint32_t w, uint32_t h)
 {
     if (!w || !h) {
-        LOGE("setDefaultBufferSize: dimensions cannot be 0 (w=%d, h=%d)", w, h);
+        ST_LOGE("setDefaultBufferSize: dimensions cannot be 0 (w=%d, h=%d)",
+                w, h);
         return BAD_VALUE;
     }
 
@@ -211,14 +228,14 @@
 }
 
 status_t SurfaceTexture::requestBuffer(int slot, sp<GraphicBuffer>* buf) {
-    LOGV("SurfaceTexture::requestBuffer");
+    ST_LOGV("SurfaceTexture::requestBuffer");
     Mutex::Autolock lock(mMutex);
     if (mAbandoned) {
-        LOGE("requestBuffer: SurfaceTexture has been abandoned!");
+        ST_LOGE("requestBuffer: SurfaceTexture has been abandoned!");
         return NO_INIT;
     }
     if (slot < 0 || mBufferCount <= slot) {
-        LOGE("requestBuffer: slot index out of range [0, %d]: %d",
+        ST_LOGE("requestBuffer: slot index out of range [0, %d]: %d",
                 mBufferCount, slot);
         return BAD_VALUE;
     }
@@ -229,10 +246,10 @@
 
 status_t SurfaceTexture::dequeueBuffer(int *outBuf, uint32_t w, uint32_t h,
         uint32_t format, uint32_t usage) {
-    LOGV("SurfaceTexture::dequeueBuffer");
+    ST_LOGV("SurfaceTexture::dequeueBuffer");
 
     if ((w && !h) || (!w && h)) {
-        LOGE("dequeueBuffer: invalid size: w=%u, h=%u", w, h);
+        ST_LOGE("dequeueBuffer: invalid size: w=%u, h=%u", w, h);
         return BAD_VALUE;
     }
 
@@ -245,7 +262,7 @@
     bool tryAgain = true;
     while (tryAgain) {
         if (mAbandoned) {
-            LOGE("dequeueBuffer: SurfaceTexture has been abandoned!");
+            ST_LOGE("dequeueBuffer: SurfaceTexture has been abandoned!");
             return NO_INIT;
         }
 
@@ -334,7 +351,8 @@
             // than allowed.
             const int avail = mBufferCount - (dequeuedCount+1);
             if (avail < (MIN_UNDEQUEUED_BUFFERS-int(mSynchronousMode))) {
-                LOGE("dequeueBuffer: MIN_UNDEQUEUED_BUFFERS=%d exceeded (dequeued=%d)",
+                ST_LOGE("dequeueBuffer: MIN_UNDEQUEUED_BUFFERS=%d exceeded "
+                        "(dequeued=%d)",
                         MIN_UNDEQUEUED_BUFFERS-int(mSynchronousMode),
                         dequeuedCount);
                 return -EBUSY;
@@ -391,7 +409,8 @@
                 mGraphicBufferAlloc->createGraphicBuffer(
                         w, h, format, usage, &error));
         if (graphicBuffer == 0) {
-            LOGE("dequeueBuffer: SurfaceComposer::createGraphicBuffer failed");
+            ST_LOGE("dequeueBuffer: SurfaceComposer::createGraphicBuffer "
+                    "failed");
             return error;
         }
         if (updateFormat) {
@@ -413,7 +432,7 @@
     Mutex::Autolock lock(mMutex);
 
     if (mAbandoned) {
-        LOGE("setSynchronousMode: SurfaceTexture has been abandoned!");
+        ST_LOGE("setSynchronousMode: SurfaceTexture has been abandoned!");
         return NO_INIT;
     }
 
@@ -441,29 +460,29 @@
 
 status_t SurfaceTexture::queueBuffer(int buf, int64_t timestamp,
         uint32_t* outWidth, uint32_t* outHeight, uint32_t* outTransform) {
-    LOGV("SurfaceTexture::queueBuffer");
+    ST_LOGV("SurfaceTexture::queueBuffer");
 
     sp<FrameAvailableListener> listener;
 
     { // scope for the lock
         Mutex::Autolock lock(mMutex);
         if (mAbandoned) {
-            LOGE("queueBuffer: SurfaceTexture has been abandoned!");
+            ST_LOGE("queueBuffer: SurfaceTexture has been abandoned!");
             return NO_INIT;
         }
         if (buf < 0 || buf >= mBufferCount) {
-            LOGE("queueBuffer: slot index out of range [0, %d]: %d",
+            ST_LOGE("queueBuffer: slot index out of range [0, %d]: %d",
                     mBufferCount, buf);
             return -EINVAL;
         } else if (mSlots[buf].mBufferState != BufferSlot::DEQUEUED) {
-            LOGE("queueBuffer: slot %d is not owned by the client (state=%d)",
-                    buf, mSlots[buf].mBufferState);
+            ST_LOGE("queueBuffer: slot %d is not owned by the client "
+                    "(state=%d)", buf, mSlots[buf].mBufferState);
             return -EINVAL;
         } else if (buf == mCurrentTexture) {
-            LOGE("queueBuffer: slot %d is current!", buf);
+            ST_LOGE("queueBuffer: slot %d is current!", buf);
             return -EINVAL;
         } else if (!mSlots[buf].mRequestBufferCalled) {
-            LOGE("queueBuffer: slot %d was enqueued without requesting a "
+            ST_LOGE("queueBuffer: slot %d was enqueued without requesting a "
                     "buffer", buf);
             return -EINVAL;
         }
@@ -513,20 +532,20 @@
 }
 
 void SurfaceTexture::cancelBuffer(int buf) {
-    LOGV("SurfaceTexture::cancelBuffer");
+    ST_LOGV("SurfaceTexture::cancelBuffer");
     Mutex::Autolock lock(mMutex);
 
     if (mAbandoned) {
-        LOGW("cancelBuffer: SurfaceTexture has been abandoned!");
+        ST_LOGW("cancelBuffer: SurfaceTexture has been abandoned!");
         return;
     }
 
     if (buf < 0 || buf >= mBufferCount) {
-        LOGE("cancelBuffer: slot index out of range [0, %d]: %d",
+        ST_LOGE("cancelBuffer: slot index out of range [0, %d]: %d",
                 mBufferCount, buf);
         return;
     } else if (mSlots[buf].mBufferState != BufferSlot::DEQUEUED) {
-        LOGE("cancelBuffer: slot %d is not owned by the client (state=%d)",
+        ST_LOGE("cancelBuffer: slot %d is not owned by the client (state=%d)",
                 buf, mSlots[buf].mBufferState);
         return;
     }
@@ -535,10 +554,10 @@
 }
 
 status_t SurfaceTexture::setCrop(const Rect& crop) {
-    LOGV("SurfaceTexture::setCrop");
+    ST_LOGV("SurfaceTexture::setCrop");
     Mutex::Autolock lock(mMutex);
     if (mAbandoned) {
-        LOGE("setCrop: SurfaceTexture has been abandoned!");
+        ST_LOGE("setCrop: SurfaceTexture has been abandoned!");
         return NO_INIT;
     }
     mNextCrop = crop;
@@ -546,10 +565,10 @@
 }
 
 status_t SurfaceTexture::setTransform(uint32_t transform) {
-    LOGV("SurfaceTexture::setTransform");
+    ST_LOGV("SurfaceTexture::setTransform");
     Mutex::Autolock lock(mMutex);
     if (mAbandoned) {
-        LOGE("setTransform: SurfaceTexture has been abandoned!");
+        ST_LOGE("setTransform: SurfaceTexture has been abandoned!");
         return NO_INIT;
     }
     mNextTransform = transform;
@@ -558,11 +577,11 @@
 
 status_t SurfaceTexture::connect(int api,
         uint32_t* outWidth, uint32_t* outHeight, uint32_t* outTransform) {
-    LOGV("SurfaceTexture::connect(this=%p, %d)", this, api);
+    ST_LOGV("SurfaceTexture::connect(this=%p, %d)", this, api);
     Mutex::Autolock lock(mMutex);
 
     if (mAbandoned) {
-        LOGE("connect: SurfaceTexture has been abandoned!");
+        ST_LOGE("connect: SurfaceTexture has been abandoned!");
         return NO_INIT;
     }
 
@@ -573,7 +592,7 @@
         case NATIVE_WINDOW_API_MEDIA:
         case NATIVE_WINDOW_API_CAMERA:
             if (mConnectedApi != NO_CONNECTED_API) {
-                LOGE("connect: already connected (cur=%d, req=%d)",
+                ST_LOGE("connect: already connected (cur=%d, req=%d)",
                         mConnectedApi, api);
                 err = -EINVAL;
             } else {
@@ -591,11 +610,11 @@
 }
 
 status_t SurfaceTexture::disconnect(int api) {
-    LOGV("SurfaceTexture::disconnect(this=%p, %d)", this, api);
+    ST_LOGV("SurfaceTexture::disconnect(this=%p, %d)", this, api);
     Mutex::Autolock lock(mMutex);
 
     if (mAbandoned) {
-        LOGE("disconnect: SurfaceTexture has been abandoned!");
+        ST_LOGE("disconnect: SurfaceTexture has been abandoned!");
         return NO_INIT;
     }
 
@@ -613,7 +632,7 @@
                 mNextTransform = 0;
                 mDequeueCondition.signal();
             } else {
-                LOGE("disconnect: connected to another api (cur=%d, req=%d)",
+                ST_LOGE("disconnect: connected to another api (cur=%d, req=%d)",
                         mConnectedApi, api);
                 err = -EINVAL;
             }
@@ -626,7 +645,7 @@
 }
 
 status_t SurfaceTexture::setScalingMode(int mode) {
-    LOGV("SurfaceTexture::setScalingMode(%d)", mode);
+    ST_LOGV("SurfaceTexture::setScalingMode(%d)", mode);
 
     switch (mode) {
         case NATIVE_WINDOW_SCALING_MODE_FREEZE:
@@ -642,11 +661,11 @@
 }
 
 status_t SurfaceTexture::updateTexImage() {
-    LOGV("SurfaceTexture::updateTexImage");
+    ST_LOGV("SurfaceTexture::updateTexImage");
     Mutex::Autolock lock(mMutex);
 
     if (mAbandoned) {
-        LOGE("calling updateTexImage() on an abandoned SurfaceTexture");
+        ST_LOGE("calling updateTexImage() on an abandoned SurfaceTexture");
         return NO_INIT;
     }
 
@@ -661,7 +680,7 @@
         if (image == EGL_NO_IMAGE_KHR) {
             EGLDisplay dpy = eglGetCurrentDisplay();
             if (mSlots[buf].mGraphicBuffer == 0) {
-                LOGE("buffer at slot %d is null", buf);
+                ST_LOGE("buffer at slot %d is null", buf);
                 return BAD_VALUE;
             }
             image = createImage(dpy, mSlots[buf].mGraphicBuffer);
@@ -676,15 +695,16 @@
 
         GLint error;
         while ((error = glGetError()) != GL_NO_ERROR) {
-            LOGW("updateTexImage: clearing GL error: %#04x", error);
+            ST_LOGW("updateTexImage: clearing GL error: %#04x", error);
         }
 
         glBindTexture(GL_TEXTURE_EXTERNAL_OES, mTexName);
-        glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, (GLeglImageOES)image);
+        glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES,
+                (GLeglImageOES)image);
 
         bool failed = false;
         while ((error = glGetError()) != GL_NO_ERROR) {
-            LOGE("error binding external texture image %p (slot %d): %#04x",
+            ST_LOGE("error binding external texture image %p (slot %d): %#04x",
                     image, buf, error);
             failed = true;
         }
@@ -750,7 +770,7 @@
 }
 
 void SurfaceTexture::computeCurrentTransformMatrix() {
-    LOGV("SurfaceTexture::computeCurrentTransformMatrix");
+    ST_LOGV("SurfaceTexture::computeCurrentTransformMatrix");
 
     float xform[16];
     for (int i = 0; i < 16; i++) {
@@ -841,14 +861,14 @@
 }
 
 nsecs_t SurfaceTexture::getTimestamp() {
-    LOGV("SurfaceTexture::getTimestamp");
+    ST_LOGV("SurfaceTexture::getTimestamp");
     Mutex::Autolock lock(mMutex);
     return mCurrentTimestamp;
 }
 
 void SurfaceTexture::setFrameAvailableListener(
         const sp<FrameAvailableListener>& listener) {
-    LOGV("SurfaceTexture::setFrameAvailableListener");
+    ST_LOGV("SurfaceTexture::setFrameAvailableListener");
     Mutex::Autolock lock(mMutex);
     mFrameAvailableListener = listener;
 }
@@ -892,11 +912,11 @@
     while (mSynchronousMode && !mQueue.isEmpty()) {
         mDequeueCondition.wait(mMutex);
         if (mAbandoned) {
-            LOGE("drainQueueLocked: SurfaceTexture has been abandoned!");
+            ST_LOGE("drainQueueLocked: SurfaceTexture has been abandoned!");
             return NO_INIT;
         }
         if (mConnectedApi == NO_CONNECTED_API) {
-            LOGE("drainQueueLocked: SurfaceTexture is not connected!");
+            ST_LOGE("drainQueueLocked: SurfaceTexture is not connected!");
             return NO_INIT;
         }
     }
@@ -926,7 +946,7 @@
             EGL_NATIVE_BUFFER_ANDROID, cbuf, attrs);
     if (image == EGL_NO_IMAGE_KHR) {
         EGLint error = eglGetError();
-        LOGE("error creating EGLImage: %#x", error);
+        ST_LOGE("error creating EGLImage: %#x", error);
     }
     return image;
 }
@@ -956,7 +976,7 @@
     Mutex::Autolock lock(mMutex);
 
     if (mAbandoned) {
-        LOGE("query: SurfaceTexture has been abandoned!");
+        ST_LOGE("query: SurfaceTexture has been abandoned!");
         return NO_INIT;
     }
 
@@ -991,6 +1011,10 @@
     mDequeueCondition.signal();
 }
 
+void SurfaceTexture::setName(const String8& name) {
+    mName = name;
+}
+
 void SurfaceTexture::dump(String8& result) const
 {
     char buffer[1024];
@@ -1004,8 +1028,8 @@
     snprintf(buffer, SIZE,
             "%smBufferCount=%d, mSynchronousMode=%d, default-size=[%dx%d], "
             "mPixelFormat=%d, mTexName=%d\n",
-            prefix, mBufferCount, mSynchronousMode, mDefaultWidth, mDefaultHeight,
-            mPixelFormat, mTexName);
+            prefix, mBufferCount, mSynchronousMode, mDefaultWidth,
+            mDefaultHeight, mPixelFormat, mTexName);
     result.append(buffer);
 
     String8 fifo;
@@ -1024,8 +1048,8 @@
             prefix, mCurrentCrop.left,
             mCurrentCrop.top, mCurrentCrop.right, mCurrentCrop.bottom,
             mCurrentTransform, mCurrentTexture,
-            prefix, mNextCrop.left, mNextCrop.top, mNextCrop.right, mNextCrop.bottom,
-            mNextTransform, fifoSize, fifo.string()
+            prefix, mNextCrop.left, mNextCrop.top, mNextCrop.right,
+            mNextCrop.bottom, mNextTransform, fifoSize, fifo.string()
     );
     result.append(buffer);
 
@@ -1048,8 +1072,8 @@
                 "transform=0x%02x, timestamp=%lld",
                 prefix, (i==mCurrentTexture)?">":" ", i,
                 stateName(slot.mBufferState),
-                slot.mCrop.left, slot.mCrop.top, slot.mCrop.right, slot.mCrop.bottom,
-                slot.mTransform, slot.mTimestamp
+                slot.mCrop.left, slot.mCrop.top, slot.mCrop.right,
+                slot.mCrop.bottom, slot.mTransform, slot.mTimestamp
         );
         result.append(buffer);
 
@@ -1057,7 +1081,8 @@
         if (buf != NULL) {
             snprintf(buffer, SIZE,
                     ", %p [%4ux%4u:%4u,%3X]",
-                    buf->handle, buf->width, buf->height, buf->stride, buf->format);
+                    buf->handle, buf->width, buf->height, buf->stride,
+                    buf->format);
             result.append(buffer);
         }
         result.append("\n");
diff --git a/libs/rs/rs.spec b/libs/rs/rs.spec
index f277582..20b1f52 100644
--- a/libs/rs/rs.spec
+++ b/libs/rs/rs.spec
@@ -329,10 +329,7 @@
 
 ProgramRasterCreate {
 	direct
-	param bool pointSmooth
-	param bool lineSmooth
 	param bool pointSprite
-	param float lineWidth
 	param RsCullMode cull
 	ret RsProgramRaster
 }
diff --git a/libs/rs/rsProgramRaster.cpp b/libs/rs/rsProgramRaster.cpp
index 945b5ec..94bfe42 100644
--- a/libs/rs/rsProgramRaster.cpp
+++ b/libs/rs/rsProgramRaster.cpp
@@ -21,19 +21,12 @@
 using namespace android::renderscript;
 
 
-ProgramRaster::ProgramRaster(Context *rsc, bool pointSmooth,
-                             bool lineSmooth, bool pointSprite,
-                             float lineWidth, RsCullMode cull)
+ProgramRaster::ProgramRaster(Context *rsc, bool pointSprite, RsCullMode cull)
     : ProgramBase(rsc) {
 
     memset(&mHal, 0, sizeof(mHal));
-
-    mHal.state.pointSmooth = pointSmooth;
-    mHal.state.lineSmooth = lineSmooth;
     mHal.state.pointSprite = pointSprite;
-    mHal.state.lineWidth = lineWidth;
     mHal.state.cull = cull;
-
     rsc->mHal.funcs.raster.init(rsc, this);
 }
 
@@ -74,8 +67,7 @@
 }
 
 void ProgramRasterState::init(Context *rsc) {
-    mDefault.set(ProgramRaster::getProgramRaster(rsc, false, false,
-                                                 false, 1.f, RS_CULL_BACK).get());
+    mDefault.set(ProgramRaster::getProgramRaster(rsc, false, RS_CULL_BACK).get());
 }
 
 void ProgramRasterState::deinit(Context *rsc) {
@@ -84,19 +76,13 @@
 }
 
 ObjectBaseRef<ProgramRaster> ProgramRaster::getProgramRaster(Context *rsc,
-                                                             bool pointSmooth,
-                                                             bool lineSmooth,
                                                              bool pointSprite,
-                                                             float lineWidth,
                                                              RsCullMode cull) {
     ObjectBaseRef<ProgramRaster> returnRef;
     ObjectBase::asyncLock();
     for (uint32_t ct = 0; ct < rsc->mStateRaster.mRasterPrograms.size(); ct++) {
         ProgramRaster *existing = rsc->mStateRaster.mRasterPrograms[ct];
-        if (existing->mHal.state.pointSmooth != pointSmooth) continue;
-        if (existing->mHal.state.lineSmooth != lineSmooth) continue;
         if (existing->mHal.state.pointSprite != pointSprite) continue;
-        if (existing->mHal.state.lineWidth != lineWidth) continue;
         if (existing->mHal.state.cull != cull) continue;
         returnRef.set(existing);
         ObjectBase::asyncUnlock();
@@ -104,8 +90,7 @@
     }
     ObjectBase::asyncUnlock();
 
-    ProgramRaster *pr = new ProgramRaster(rsc, pointSmooth,
-                                          lineSmooth, pointSprite, lineWidth, cull);
+    ProgramRaster *pr = new ProgramRaster(rsc, pointSprite, cull);
     returnRef.set(pr);
 
     ObjectBase::asyncLock();
@@ -118,10 +103,8 @@
 namespace android {
 namespace renderscript {
 
-RsProgramRaster rsi_ProgramRasterCreate(Context * rsc, bool pointSmooth, bool lineSmooth,
-                                        bool pointSprite, float lineWidth, RsCullMode cull) {
-    ObjectBaseRef<ProgramRaster> pr = ProgramRaster::getProgramRaster(rsc, pointSmooth, lineSmooth,
-                                                                      pointSprite, lineWidth, cull);
+RsProgramRaster rsi_ProgramRasterCreate(Context * rsc, bool pointSprite, RsCullMode cull) {
+    ObjectBaseRef<ProgramRaster> pr = ProgramRaster::getProgramRaster(rsc, pointSprite, cull);
     pr->incUserRef();
     return pr.get();
 }
diff --git a/libs/rs/rsProgramRaster.h b/libs/rs/rsProgramRaster.h
index 09d7d54..20af30a 100644
--- a/libs/rs/rsProgramRaster.h
+++ b/libs/rs/rsProgramRaster.h
@@ -33,19 +33,13 @@
     static ProgramRaster *createFromStream(Context *rsc, IStream *stream);
 
     static ObjectBaseRef<ProgramRaster> getProgramRaster(Context *rsc,
-                                                         bool pointSmooth,
-                                                         bool lineSmooth,
                                                          bool pointSprite,
-                                                         float lineWidth,
                                                          RsCullMode cull);
     struct Hal {
         mutable void *drv;
 
         struct State {
-            bool pointSmooth;
-            bool lineSmooth;
             bool pointSprite;
-            float lineWidth;
             RsCullMode cull;
         };
         State state;
@@ -58,10 +52,7 @@
 
 private:
     ProgramRaster(Context *rsc,
-                  bool pointSmooth,
-                  bool lineSmooth,
                   bool pointSprite,
-                  float lineWidth,
                   RsCullMode cull);
 
 };
diff --git a/libs/ui/Region.cpp b/libs/ui/Region.cpp
index 8dab291..5656088 100644
--- a/libs/ui/Region.cpp
+++ b/libs/ui/Region.cpp
@@ -482,6 +482,7 @@
     if (!rhs.isValid()) {
         LOGE("Region::boolean_operation(op=%d) invalid Rect={%d,%d,%d,%d}",
                 op, rhs.left, rhs.top, rhs.right, rhs.bottom);
+        return;
     }
 
 #if VALIDATE_WITH_CORECG || VALIDATE_REGIONS
diff --git a/media/jni/android_media_MediaPlayer.cpp b/media/jni/android_media_MediaPlayer.cpp
index c270f21..f3174fe 100644
--- a/media/jni/android_media_MediaPlayer.cpp
+++ b/media/jni/android_media_MediaPlayer.cpp
@@ -651,6 +651,10 @@
 android_media_MediaPlayer_native_finalize(JNIEnv *env, jobject thiz)
 {
     LOGV("native_finalize");
+    sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
+    if (mp != NULL) {
+        LOGW("MediaPlayer finalized without being released");
+    }
     android_media_MediaPlayer_release(env, thiz);
 }
 
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index 0386d4b..b5eef94 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -52,6 +52,7 @@
 #include <media/Metadata.h>
 #include <media/AudioTrack.h>
 #include <media/MemoryLeakTrackUtil.h>
+#include <media/stagefright/MediaErrors.h>
 
 #include <system/audio.h>
 
@@ -1132,7 +1133,11 @@
     player->start();
 
     LOGV("wait for playback complete");
-    if (cache->wait() != NO_ERROR) goto Exit;
+    cache->wait();
+    // in case of error, return what was successfully decoded.
+    if (cache->size() == 0) {
+        goto Exit;
+    }
 
     mem = new MemoryBase(cache->getHeap(), 0, cache->size());
     *pSampleRate = cache->sampleRate();
@@ -1175,7 +1180,11 @@
     player->start();
 
     LOGV("wait for playback complete");
-    if (cache->wait() != NO_ERROR) goto Exit;
+    cache->wait();
+    // in case of error, return what was successfully decoded.
+    if (cache->size() == 0) {
+        goto Exit;
+    }
 
     mem = new MemoryBase(cache->getHeap(), 0, cache->size());
     *pSampleRate = cache->sampleRate();
diff --git a/media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp b/media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp
index 605d056..079f6fa 100644
--- a/media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp
@@ -41,7 +41,7 @@
       mUIDValid(uidValid),
       mUID(uid),
       mFlags(0),
-      mEOS(false),
+      mFinalResult(OK),
       mOffset(0) {
     if (headers) {
         mExtraHeaders = *headers;
@@ -95,9 +95,9 @@
     return source->getFormat();
 }
 
-bool NuPlayer::HTTPLiveSource::feedMoreTSData() {
-    if (mEOS) {
-        return false;
+status_t NuPlayer::HTTPLiveSource::feedMoreTSData() {
+    if (mFinalResult != OK) {
+        return mFinalResult;
     }
 
     sp<LiveDataSource> source =
@@ -110,9 +110,13 @@
         if (n == -EWOULDBLOCK) {
             break;
         } else if (n < 0) {
-            LOGI("input data EOS reached.");
+            if (n != ERROR_END_OF_STREAM) {
+                LOGI("input data EOS reached, error %ld", n);
+            } else {
+                LOGI("input data EOS reached.");
+            }
             mTSParser->signalEOS(n);
-            mEOS = true;
+            mFinalResult = n;
             break;
         } else {
             if (buffer[0] == 0x00) {
@@ -129,7 +133,7 @@
                 if (err != OK) {
                     LOGE("TS Parser returned error %d", err);
                     mTSParser->signalEOS(err);
-                    mEOS = true;
+                    mFinalResult = err;
                     break;
                 }
             }
@@ -138,7 +142,7 @@
         }
     }
 
-    return true;
+    return OK;
 }
 
 status_t NuPlayer::HTTPLiveSource::dequeueAccessUnit(
@@ -168,7 +172,7 @@
 status_t NuPlayer::HTTPLiveSource::seekTo(int64_t seekTimeUs) {
     // We need to make sure we're not seeking until we have seen the very first
     // PTS timestamp in the whole stream (from the beginning of the stream).
-    while (!mTSParser->PTSTimeDeltaEstablished() && feedMoreTSData()) {
+    while (!mTSParser->PTSTimeDeltaEstablished() && feedMoreTSData() == OK) {
         usleep(100000);
     }
 
diff --git a/media/libmediaplayerservice/nuplayer/HTTPLiveSource.h b/media/libmediaplayerservice/nuplayer/HTTPLiveSource.h
index 36c67c5..f22af5b 100644
--- a/media/libmediaplayerservice/nuplayer/HTTPLiveSource.h
+++ b/media/libmediaplayerservice/nuplayer/HTTPLiveSource.h
@@ -35,8 +35,7 @@
 
     virtual void start();
 
-    // Returns true iff more data was available, false on EOS.
-    virtual bool feedMoreTSData();
+    virtual status_t feedMoreTSData();
 
     virtual sp<MetaData> getFormat(bool audio);
     virtual status_t dequeueAccessUnit(bool audio, sp<ABuffer> *accessUnit);
@@ -59,7 +58,7 @@
     bool mUIDValid;
     uid_t mUID;
     uint32_t mFlags;
-    bool mEOS;
+    status_t mFinalResult;
     off64_t mOffset;
     sp<ALooper> mLiveLooper;
     sp<LiveSession> mLiveSession;
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
index 7218faf..6b40528 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
@@ -235,11 +235,17 @@
                 instantiateDecoder(true, &mAudioDecoder);
             }
 
-            if (!mSource->feedMoreTSData()) {
+            status_t err;
+            if ((err = mSource->feedMoreTSData()) != OK) {
                 if (mAudioDecoder == NULL && mVideoDecoder == NULL) {
                     // We're not currently decoding anything (no audio or
                     // video tracks found) and we just ran out of input data.
-                    notifyListener(MEDIA_PLAYBACK_COMPLETE, 0, 0);
+
+                    if (err == ERROR_END_OF_STREAM) {
+                        notifyListener(MEDIA_PLAYBACK_COMPLETE, 0, 0);
+                    } else {
+                        notifyListener(MEDIA_ERROR, MEDIA_ERROR_UNKNOWN, err);
+                    }
                 }
                 break;
             }
@@ -267,12 +273,23 @@
                         audio, codecRequest);
 
                 if (err == -EWOULDBLOCK) {
-                    if (mSource->feedMoreTSData()) {
+                    if (mSource->feedMoreTSData() == OK) {
                         msg->post();
                     }
                 }
             } else if (what == ACodec::kWhatEOS) {
-                mRenderer->queueEOS(audio, ERROR_END_OF_STREAM);
+                int32_t err;
+                CHECK(codecRequest->findInt32("err", &err));
+
+                if (err == ERROR_END_OF_STREAM) {
+                    LOGV("got %s decoder EOS", audio ? "audio" : "video");
+                } else {
+                    LOGV("got %s decoder EOS w/ error %d",
+                         audio ? "audio" : "video",
+                         err);
+                }
+
+                mRenderer->queueEOS(audio, err);
             } else if (what == ACodec::kWhatFlushCompleted) {
                 bool needShutdown;
 
@@ -397,7 +414,7 @@
                 if (finalResult == ERROR_END_OF_STREAM) {
                     LOGV("reached %s EOS", audio ? "audio" : "video");
                 } else {
-                    LOGE("%s track encountered an error (0x%08x)",
+                    LOGE("%s track encountered an error (%d)",
                          audio ? "audio" : "video", finalResult);
 
                     notifyListener(
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerSource.h b/media/libmediaplayerservice/nuplayer/NuPlayerSource.h
index 5e55487..8a7eece 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerSource.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerSource.h
@@ -29,8 +29,9 @@
 
     virtual void start() = 0;
 
-    // Returns true iff more data was available, false on EOS.
-    virtual bool feedMoreTSData() = 0;
+    // Returns OK iff more data was available,
+    // an error or ERROR_END_OF_STREAM if not.
+    virtual status_t feedMoreTSData() = 0;
 
     virtual sp<MetaData> getFormat(bool audio) = 0;
 
diff --git a/media/libmediaplayerservice/nuplayer/StreamingSource.cpp b/media/libmediaplayerservice/nuplayer/StreamingSource.cpp
index 7319e4c..f795654 100644
--- a/media/libmediaplayerservice/nuplayer/StreamingSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/StreamingSource.cpp
@@ -34,7 +34,7 @@
 
 NuPlayer::StreamingSource::StreamingSource(const sp<IStreamSource> &source)
     : mSource(source),
-      mEOS(false) {
+      mFinalResult(OK) {
 }
 
 NuPlayer::StreamingSource::~StreamingSource() {
@@ -47,9 +47,9 @@
     mStreamListener->start();
 }
 
-bool NuPlayer::StreamingSource::feedMoreTSData() {
-    if (mEOS) {
-        return false;
+status_t NuPlayer::StreamingSource::feedMoreTSData() {
+    if (mFinalResult != OK) {
+        return mFinalResult;
     }
 
     for (int32_t i = 0; i < 50; ++i) {
@@ -60,7 +60,7 @@
         if (n == 0) {
             LOGI("input data EOS reached.");
             mTSParser->signalEOS(ERROR_END_OF_STREAM);
-            mEOS = true;
+            mFinalResult = ERROR_END_OF_STREAM;
             break;
         } else if (n == INFO_DISCONTINUITY) {
             ATSParser::DiscontinuityType type = ATSParser::DISCONTINUITY_SEEK;
@@ -92,14 +92,14 @@
                     LOGE("TS Parser returned error %d", err);
 
                     mTSParser->signalEOS(err);
-                    mEOS = true;
+                    mFinalResult = err;
                     break;
                 }
             }
         }
     }
 
-    return true;
+    return OK;
 }
 
 sp<MetaData> NuPlayer::StreamingSource::getFormat(bool audio) {
diff --git a/media/libmediaplayerservice/nuplayer/StreamingSource.h b/media/libmediaplayerservice/nuplayer/StreamingSource.h
index 7abce84..ca00ef9 100644
--- a/media/libmediaplayerservice/nuplayer/StreamingSource.h
+++ b/media/libmediaplayerservice/nuplayer/StreamingSource.h
@@ -31,8 +31,7 @@
 
     virtual void start();
 
-    // Returns true iff more data was available, false on EOS.
-    virtual bool feedMoreTSData();
+    virtual status_t feedMoreTSData();
 
     virtual sp<MetaData> getFormat(bool audio);
     virtual status_t dequeueAccessUnit(bool audio, sp<ABuffer> *accessUnit);
@@ -42,7 +41,7 @@
 
 private:
     sp<IStreamSource> mSource;
-    bool mEOS;
+    status_t mFinalResult;
     sp<NuPlayerStreamListener> mStreamListener;
     sp<ATSParser> mTSParser;
 
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index a2d9e59..a3746cd 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -323,6 +323,7 @@
     mFlushingState = new FlushingState(this);
 
     mPortEOS[kPortIndexInput] = mPortEOS[kPortIndexOutput] = false;
+    mInputEOSResult = OK;
 
     changeState(mUninitializedState);
 }
@@ -1347,7 +1348,10 @@
         case KEEP_BUFFERS:
         {
             if (buffer == NULL) {
-                mCodec->mPortEOS[kPortIndexInput] = true;
+                if (!mCodec->mPortEOS[kPortIndexInput]) {
+                    mCodec->mPortEOS[kPortIndexInput] = true;
+                    mCodec->mInputEOSResult = err;
+                }
             }
             break;
         }
@@ -1398,8 +1402,14 @@
 
                 getMoreInputDataIfPossible();
             } else if (!mCodec->mPortEOS[kPortIndexInput]) {
-                LOGV("[%s] Signalling EOS on the input port",
-                     mCodec->mComponentName.c_str());
+                if (err != ERROR_END_OF_STREAM) {
+                    LOGV("[%s] Signalling EOS on the input port "
+                         "due to error %d",
+                         mCodec->mComponentName.c_str(), err);
+                } else {
+                    LOGV("[%s] Signalling EOS on the input port",
+                         mCodec->mComponentName.c_str());
+                }
 
                 LOGV("[%s] calling emptyBuffer %p signalling EOS",
                      mCodec->mComponentName.c_str(), bufferID);
@@ -1416,6 +1426,7 @@
                 info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
 
                 mCodec->mPortEOS[kPortIndexInput] = true;
+                mCodec->mInputEOSResult = err;
             }
             break;
 
@@ -1523,6 +1534,7 @@
             if (flags & OMX_BUFFERFLAG_EOS) {
                 sp<AMessage> notify = mCodec->mNotify->dup();
                 notify->setInt32("what", ACodec::kWhatEOS);
+                notify->setInt32("err", mCodec->mInputEOSResult);
                 notify->post();
 
                 mCodec->mPortEOS[kPortIndexOutput] = true;
@@ -1721,6 +1733,8 @@
     mCodec->mPortEOS[kPortIndexInput] =
         mCodec->mPortEOS[kPortIndexOutput] = false;
 
+    mCodec->mInputEOSResult = OK;
+
     mCodec->configureCodec(mime.c_str(), msg);
 
     sp<RefBase> obj;
@@ -2371,6 +2385,8 @@
         mCodec->mPortEOS[kPortIndexInput] =
             mCodec->mPortEOS[kPortIndexOutput] = false;
 
+        mCodec->mInputEOSResult = OK;
+
         mCodec->changeState(mCodec->mExecutingState);
     }
 }
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index 07a46bd..fa9417a 100644
--- a/media/libstagefright/AwesomePlayer.cpp
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -249,7 +249,7 @@
 }
 
 void AwesomePlayer::setUID(uid_t uid) {
-    LOGI("AwesomePlayer running on behalf of uid %d", uid);
+    LOGV("AwesomePlayer running on behalf of uid %d", uid);
 
     mUID = uid;
     mUIDValid = true;
@@ -362,7 +362,7 @@
         if (!meta->findInt32(kKeyBitRate, &bitrate)) {
             const char *mime;
             CHECK(meta->findCString(kKeyMIMEType, &mime));
-            LOGW("track of type '%s' does not publish bitrate", mime);
+            LOGV("track of type '%s' does not publish bitrate", mime);
 
             totalBitRate = -1;
             break;
@@ -1192,7 +1192,7 @@
         usleep(1000);
     }
     IPCThreadState::self()->flushCommands();
-    LOGI("video decoder shutdown completed");
+    LOGV("video decoder shutdown completed");
 }
 
 status_t AwesomePlayer::setNativeWindow_l(const sp<ANativeWindow> &native) {
@@ -1202,7 +1202,7 @@
         return OK;
     }
 
-    LOGI("attempting to reconfigure to use new surface");
+    LOGV("attempting to reconfigure to use new surface");
 
     bool wasPlaying = (mFlags & PLAYING) != 0;
 
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index 6280f51..9eb1469 100755
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -1635,7 +1635,7 @@
         return err;
     }
 
-    CODEC_LOGI("allocating %lu buffers of size %lu on %s port",
+    CODEC_LOGV("allocating %lu buffers of size %lu on %s port",
             def.nBufferCountActual, def.nBufferSize,
             portIndex == kPortIndexInput ? "input" : "output");
 
@@ -1876,7 +1876,7 @@
         return err;
     }
 
-    CODEC_LOGI("allocating %lu buffers from a native window of size %lu on "
+    CODEC_LOGV("allocating %lu buffers from a native window of size %lu on "
             "output port", def.nBufferCountActual, def.nBufferSize);
 
     // Dequeue buffers and send them to OMX
@@ -3654,7 +3654,7 @@
 
     mSource->stop();
 
-    CODEC_LOGI("stopped in state %d", mState);
+    CODEC_LOGV("stopped in state %d", mState);
 
     return OK;
 }
@@ -4219,14 +4219,14 @@
                 inputFormat->findInt32(kKeySampleRate, &sampleRate);
 
                 if ((OMX_U32)numChannels != params.nChannels) {
-                    LOGW("Codec outputs a different number of channels than "
+                    LOGV("Codec outputs a different number of channels than "
                          "the input stream contains (contains %d channels, "
                          "codec outputs %ld channels).",
                          numChannels, params.nChannels);
                 }
 
                 if (sampleRate != (int32_t)params.nSamplingRate) {
-                    LOGW("Codec outputs at different sampling rate than "
+                    LOGV("Codec outputs at different sampling rate than "
                          "what the input stream contains (contains data at "
                          "%d Hz, codec outputs %lu Hz)",
                          sampleRate, params.nSamplingRate);
diff --git a/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java b/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
index 6e5f856..113f0f7 100644
--- a/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
+++ b/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
@@ -156,6 +156,7 @@
             }
             ret.packageName = pkg.packageName;
             ret.installLocation = pkg.installLocation;
+            ret.verifiers = pkg.verifiers;
 
             ret.recommendedInstallLocation = recommendAppInstallLocation(pkg.installLocation,
                     archiveFilePath, flags, threshold);
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_home.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_home.png
index 3137e7e..908056f 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_home.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_home.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_alarm.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_alarm.png
index ffffb2d..fc8dee1 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_alarm.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_alarm.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_bluetooth.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_bluetooth.png
index 2117705..4a5d001 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_bluetooth.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_bluetooth.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_sync.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_sync.png
index ba2d78a..ed31e8e 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_sync.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_sync.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_sync_error.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_sync_error.png
index 1102846..6583878 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_sync_error.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_sync_error.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home.png
index 5c98614..9820a79 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_alarm.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_alarm.png
index 4931b66..4b0a74f 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_alarm.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_alarm.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_bluetooth.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_bluetooth.png
index f288d9f..53a7364 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_data_bluetooth.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_data_bluetooth.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_sync.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_sync.png
index 6649031..06b3913 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_sync.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_sync.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_sync_error.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_sync_error.png
index 1b57936..4f23dae 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_sync_error.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_sync_error.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home.png
index 7c6b8e5..0b41317 100644
--- a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home.png
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_alarm.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_alarm.png
index 6abc7c8..19ad300 100644
--- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_alarm.png
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_alarm.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_bluetooth.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_bluetooth.png
index 738bd21..524b31b 100644
--- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_bluetooth.png
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_data_bluetooth.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_sync.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_sync.png
index fb691fc..fdd640c 100644
--- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_sync.png
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_sync.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_sync_error.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_sync_error.png
index 0c7ba35..a1a0646 100644
--- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_sync_error.png
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_sync_error.png
Binary files differ
diff --git a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
index 492f3c2..bf1ec25 100644
--- a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
+++ b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
@@ -26,6 +26,7 @@
 import android.graphics.Rect;
 import android.graphics.Region.Op;
 import android.opengl.GLUtils;
+import android.os.SystemProperties;
 import android.renderscript.Matrix4f;
 import android.service.wallpaper.WallpaperService;
 import android.util.Log;
@@ -56,6 +57,7 @@
     private static final String TAG = "ImageWallpaper";
     private static final String GL_LOG_TAG = "ImageWallpaperGL";
     private static final boolean DEBUG = false;
+    private static final String PROPERTY_KERNEL_QEMU = "ro.kernel.qemu";
 
     static final boolean FIXED_SIZED_SURFACE = true;
     static final boolean USE_OPENGL = true;
@@ -71,12 +73,19 @@
 
         //noinspection PointlessBooleanExpression,ConstantConditions
         if (FIXED_SIZED_SURFACE && USE_OPENGL) {
-            WindowManager windowManager = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
-            Display display = windowManager.getDefaultDisplay();
-            mIsHwAccelerated = ActivityManager.isHighEndGfx(display);
+            if (!isEmulator()) {
+                WindowManager windowManager =
+                        (WindowManager) getSystemService(Context.WINDOW_SERVICE);
+                Display display = windowManager.getDefaultDisplay();
+                mIsHwAccelerated = ActivityManager.isHighEndGfx(display);
+            }
         }
     }
 
+    private static boolean isEmulator() {
+        return "1".equals(SystemProperties.get(PROPERTY_KERNEL_QEMU, "0"));
+    }
+
     public Engine onCreateEngine() {
         return new DrawableEngine();
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBar.java
index 37c77f6..5959537 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBar.java
@@ -118,7 +118,7 @@
                 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                     | WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING
                     | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
-                PixelFormat.RGBX_8888);
+                PixelFormat.OPAQUE);
         
         // the status bar should be in an overlay if possible
         final Display defaultDisplay 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
index a90eb3f..6997837 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
@@ -29,6 +29,7 @@
 import android.util.Log;
 import android.view.ViewDebug;
 import android.view.accessibility.AccessibilityEvent;
+import android.widget.ImageView;
 
 import java.text.NumberFormat;
 
@@ -70,6 +71,8 @@
             final float alpha = res.getFraction(R.dimen.status_bar_icon_drawing_alpha, 1, 1);
             setAlpha(alpha);
         }
+
+        setScaleType(ImageView.ScaleType.CENTER);
     }
 
     private static boolean streq(String a, String b) {
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 25b1bc1..e5d4d22 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -316,12 +316,7 @@
         }
 
         // figure out which pixel-format to use for the status bar.
-        mPixelFormat = PixelFormat.TRANSLUCENT;
-        Drawable bg = sb.getBackground();
-        if (bg != null) {
-            mPixelFormat = bg.getOpacity();
-        }
-
+        mPixelFormat = PixelFormat.OPAQUE;
         mStatusIcons = (LinearLayout)sb.findViewById(R.id.statusIcons);
         mNotificationIcons = (IconMerger)sb.findViewById(R.id.notificationIcons);
         mIcons = (LinearLayout)sb.findViewById(R.id.icons);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
index 05e171c..9bee5df 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
@@ -64,6 +64,8 @@
 
     private static final int INET_CONDITION_THRESHOLD = 50;
 
+    private static final boolean SHOW_SYNC_ICON = false;
+
     private final Context mContext;
     private final StatusBarManager mService;
     private final Handler mHandler = new Handler();
@@ -195,6 +197,7 @@
     }
 
     private final void updateSyncState(Intent intent) {
+        if (!SHOW_SYNC_ICON) return;
         boolean isActive = intent.getBooleanExtra("active", false);
         boolean isFailing = intent.getBooleanExtra("failing", false);
         mService.setIconVisibility("sync_active", isActive);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
index 0dfc4f7..c83c470 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
@@ -720,28 +720,19 @@
             Slog.d(TAG, "updateConnectivity: connectionStatus=" + connectionStatus);
         }
 
-        int inetCondition = (connectionStatus > INET_CONDITION_THRESHOLD ? 1 : 0);
+        mInetCondition = (connectionStatus > INET_CONDITION_THRESHOLD ? 1 : 0);
 
-        switch (info.getType()) {
-            case ConnectivityManager.TYPE_MOBILE:
-                mInetCondition = inetCondition;
-                updateDataNetType();
-                updateDataIcon();
-                updateTelephonySignalStrength(); // apply any change in connectionStatus
-                break;
-            case ConnectivityManager.TYPE_WIFI:
-                mInetCondition = inetCondition;
-                updateWifiIcons();
-                break;
-            case ConnectivityManager.TYPE_BLUETOOTH:
-                mInetCondition = inetCondition;
-                if (info != null) {
-                    mBluetoothTethered = info.isConnected() ? true: false;
-                } else {
-                    mBluetoothTethered = false;
-                }
-                break;
+        if (info != null && info.getType() == ConnectivityManager.TYPE_BLUETOOTH) {
+            mBluetoothTethered = info.isConnected() ? true: false;
+        } else {
+            mBluetoothTethered = false;
         }
+
+        // We want to update all the icons, all at once, for any condition change
+        updateDataNetType();
+        updateDataIcon();
+        updateTelephonySignalStrength();
+        updateWifiIcons();
     }
 
 
@@ -1035,8 +1026,8 @@
         pw.println(mWifiLevel);
         pw.print("  mWifiSsid=");
         pw.println(mWifiSsid);
-        pw.print("  mWifiIconId=");
-        pw.println(mWifiIconId);
+        pw.print(String.format("  mWifiIconId=0x%08x/%s",
+                    mWifiIconId, getResourceName(mWifiIconId)));
         pw.print("  mWifiActivity=");
         pw.println(mWifiActivity);
 
diff --git a/packages/VpnDialogs/res/layout/confirm.xml b/packages/VpnDialogs/res/layout/confirm.xml
index 11a247a..fef00c2 100644
--- a/packages/VpnDialogs/res/layout/confirm.xml
+++ b/packages/VpnDialogs/res/layout/confirm.xml
@@ -15,46 +15,43 @@
      limitations under the License.
 -->
 
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:padding="3mm">
-
-    <ImageView android:id="@+id/icon"
-            android:layout_width="@android:dimen/app_icon_size"
-            android:layout_height="@android:dimen/app_icon_size"
-            android:layout_alignParentTop="true"
-            android:layout_alignParentLeft="true"
-            android:layout_marginRight="1mm"/>
-
-    <TextView android:id="@+id/warning"
-            android:layout_width="fill_parent"
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content">
+    <LinearLayout android:layout_width="match_parent"
             android:layout_height="wrap_content"
-            android:layout_alignParentLeft="true"
-            android:layout_alignParentRight="true"
-            android:layout_below="@id/icon"
-            android:padding="3mm"
-            android:text="@string/warning"
-            android:textSize="18sp"/>
+            android:orientation="vertical"
+            android:padding="3mm">
 
-    <TextView android:id="@+id/prompt"
-            android:layout_width="fill_parent"
-            android:layout_height="wrap_content"
-            android:layout_alignParentTop="true"
-            android:layout_alignParentRight="true"
-            android:layout_toRightOf="@id/icon"
-            android:layout_above="@id/warning"
-            android:gravity="center_vertical"
-            android:textSize="20sp"/>
+        <LinearLayout android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:orientation="horizontal"
+                android:gravity="center_vertical">
 
-    <CheckBox android:id="@+id/check"
-            android:layout_width="fill_parent"
-            android:layout_height="wrap_content"
-            android:layout_alignParentLeft="true"
-            android:layout_alignParentRight="true"
-            android:layout_below="@id/warning"
-            android:text="@string/accept"
-            android:textSize="20sp"
-            android:checked="false"/>
+            <ImageView android:id="@+id/icon"
+                    android:layout_width="@android:dimen/app_icon_size"
+                    android:layout_height="@android:dimen/app_icon_size"
+                    android:paddingRight="1mm"/>
 
-</RelativeLayout>
+            <TextView android:id="@+id/prompt"
+                    android:layout_width="fill_parent"
+                    android:layout_height="wrap_content"
+                    android:textSize="18sp"/>
+        </LinearLayout>
+
+        <TextView android:id="@+id/warning"
+                android:layout_width="fill_parent"
+                android:layout_height="wrap_content"
+                android:paddingTop="1mm"
+                android:paddingBottom="1mm"
+                android:text="@string/warning"
+                android:textSize="18sp"/>
+
+        <CheckBox android:id="@+id/check"
+                android:layout_width="fill_parent"
+                android:layout_height="wrap_content"
+                android:text="@string/accept"
+                android:textSize="20sp"
+                android:checked="false"/>
+    </LinearLayout>
+</ScrollView>
diff --git a/packages/VpnDialogs/src/com/android/vpndialogs/ManageDialog.java b/packages/VpnDialogs/src/com/android/vpndialogs/ManageDialog.java
index d668e98..7fb1417 100644
--- a/packages/VpnDialogs/src/com/android/vpndialogs/ManageDialog.java
+++ b/packages/VpnDialogs/src/com/android/vpndialogs/ManageDialog.java
@@ -181,8 +181,10 @@
                 String line = in.readLine().trim();
                 if (line.startsWith(prefix)) {
                     String[] numbers = line.substring(prefix.length()).split(" +");
-                    if (numbers.length == 17) {
-                        return numbers;
+                    for (int i = 1; i < 17; ++i) {
+                        if (!numbers[i].equals("0")) {
+                            return numbers;
+                        }
                     }
                     break;
                 }
diff --git a/policy/src/com/android/internal/policy/impl/KeyguardStatusViewManager.java b/policy/src/com/android/internal/policy/impl/KeyguardStatusViewManager.java
index 61e30bf..24dce1a 100644
--- a/policy/src/com/android/internal/policy/impl/KeyguardStatusViewManager.java
+++ b/policy/src/com/android/internal/policy/impl/KeyguardStatusViewManager.java
@@ -58,6 +58,7 @@
     private static final int CARRIER_HELP_TEXT = 12;
     private static final int HELP_MESSAGE_TEXT = 13;
     private static final int OWNER_INFO = 14;
+    private static final int BATTERY_INFO = 15;
 
     private StatusMode mStatus;
     private String mDateFormatString;
@@ -84,6 +85,9 @@
     // last known battery level
     private int mBatteryLevel = 100;
 
+    // last known SIM state
+    protected State mSimState;
+
     private LockPatternUtils mLockPatternUtils;
     private KeyguardUpdateMonitor mUpdateMonitor;
     private Button mEmergencyCallButton;
@@ -98,6 +102,8 @@
     private boolean mShowingStatus;
     private KeyguardScreenCallback mCallback;
     private final boolean mShowEmergencyButtonByDefault;
+    private CharSequence mPlmn;
+    private CharSequence mSpn;
 
     private class TransientTextManager {
         private TextView mTextView;
@@ -151,6 +157,7 @@
     public KeyguardStatusViewManager(View view, KeyguardUpdateMonitor updateMonitor,
                 LockPatternUtils lockPatternUtils, KeyguardScreenCallback callback,
                 boolean showEmergencyButtonByDefault) {
+        if (DEBUG) Log.v(TAG, "KeyguardStatusViewManager()");
         mContainer = view;
         mDateFormatString = getContext().getString(R.string.full_wday_month_day_no_year);
         mLockPatternUtils = lockPatternUtils;
@@ -165,6 +172,12 @@
         mTransportView = (TransportControlView) findViewById(R.id.transport);
         mEmergencyCallButton = (Button) findViewById(R.id.emergencyCallButton);
         mShowEmergencyButtonByDefault = showEmergencyButtonByDefault;
+
+        // Hide transport control view until we know we need to show it.
+        if (mTransportView != null) {
+            mTransportView.setVisibility(View.GONE);
+        }
+
         if (mEmergencyCallButton != null) {
             mEmergencyCallButton.setText(R.string.lockscreen_emergency_call);
             mEmergencyCallButton.setOnClickListener(this);
@@ -173,8 +186,6 @@
 
         mTransientTextManager = new TransientTextManager(mCarrierView);
 
-        updateEmergencyCallButtonState();
-
         resetStatusInfo();
         refreshDate();
         updateOwnerInfo();
@@ -187,10 +198,6 @@
                 v.setSelected(true);
             }
         }
-
-        // until we get an update...
-        setCarrierText(LockPatternUtils.getCarrierString(
-                mUpdateMonitor.getTelephonyPlmn(), mUpdateMonitor.getTelephonySpn()));
     }
 
     private boolean inWidgetMode() {
@@ -248,6 +255,7 @@
                 case INSTRUCTION_TEXT:
                 case CARRIER_HELP_TEXT:
                 case HELP_MESSAGE_TEXT:
+                case BATTERY_INFO:
                     mTransientTextManager.post(string, 0, INSTRUCTION_RESET_DELAY);
                     break;
 
@@ -262,15 +270,16 @@
     }
 
     public void onPause() {
+        if (DEBUG) Log.v(TAG, "onPause()");
         mUpdateMonitor.removeCallback(mInfoCallback);
         mUpdateMonitor.removeCallback(mSimStateCallback);
     }
 
     /** {@inheritDoc} */
     public void onResume() {
+        if (DEBUG) Log.v(TAG, "onResume()");
         mUpdateMonitor.registerInfoCallback(mInfoCallback);
         mUpdateMonitor.registerSimStateCallback(mSimStateCallback);
-        updateEmergencyCallButtonState();
         resetStatusInfo();
     }
 
@@ -399,7 +408,12 @@
      * Determine the current status of the lock screen given the sim state and other stuff.
      */
     public StatusMode getStatusForIccState(IccCard.State simState) {
-        boolean missingAndNotProvisioned = (!mUpdateMonitor.isDeviceProvisioned()
+        // Since reading the SIM may take a while, we assume it is present until told otherwise.
+        if (simState == null) {
+            return StatusMode.Normal;
+        }
+
+        final boolean missingAndNotProvisioned = (!mUpdateMonitor.isDeviceProvisioned()
                 && (simState == IccCard.State.ABSENT || simState == IccCard.State.PERM_DISABLED));
 
         // Assume we're NETWORK_LOCKED if not provisioned
@@ -435,22 +449,21 @@
      *
      * @param simState
      */
-    private void updateWithSimStatus(State simState) {
-        // The emergency call button no longer appears on this screen.
-        if (DEBUG) Log.d(TAG, "updateLayout: status=" + mStatus);
+    private void updateCarrierTextWithSimStatus(State simState) {
+        if (DEBUG) Log.d(TAG, "updateCarrierTextWithSimStatus(), simState = " + simState);
 
         CharSequence carrierText = null;
         int carrierHelpTextId = 0;
         mUnlockDisabledDueToSimState = false;
         mStatus = getStatusForIccState(simState);
+        mSimState = simState;
         switch (mStatus) {
             case Normal:
-                carrierText = LockPatternUtils.getCarrierString(mUpdateMonitor.getTelephonyPlmn(),
-                        mUpdateMonitor.getTelephonySpn());
+                carrierText = makeCarierString(mPlmn, mSpn);
                 break;
 
             case NetworkLocked:
-                carrierText = LockPatternUtils.getCarrierString(mUpdateMonitor.getTelephonyPlmn(),
+                carrierText = makeCarierString(mPlmn,
                         getContext().getText(R.string.lockscreen_network_locked_message));
                 carrierHelpTextId = R.string.lockscreen_instructions_when_pattern_disabled;
                 break;
@@ -467,19 +480,19 @@
                 break;
 
             case SimMissingLocked:
-                carrierText = LockPatternUtils.getCarrierString(mUpdateMonitor.getTelephonyPlmn(),
+                carrierText = makeCarierString(mPlmn,
                         getContext().getText(R.string.lockscreen_missing_sim_message_short));
                 carrierHelpTextId = R.string.lockscreen_missing_sim_instructions;
                 mUnlockDisabledDueToSimState = true;
                 break;
 
             case SimLocked:
-                carrierText = LockPatternUtils.getCarrierString(mUpdateMonitor.getTelephonyPlmn(),
+                carrierText = makeCarierString(mPlmn,
                         getContext().getText(R.string.lockscreen_sim_locked_message));
                 break;
 
             case SimPukLocked:
-                carrierText = LockPatternUtils.getCarrierString(mUpdateMonitor.getTelephonyPlmn(),
+                carrierText = makeCarierString(mPlmn,
                         getContext().getText(R.string.lockscreen_sim_puk_locked_message));
                 if (!mLockPatternUtils.isPukUnlockScreenEnable()) {
                     mUnlockDisabledDueToSimState = true;
@@ -489,7 +502,6 @@
 
         setCarrierText(carrierText);
         setCarrierHelpText(carrierHelpTextId);
-        updateEmergencyCallButtonState();
     }
 
     private View findViewById(int id) {
@@ -552,10 +564,11 @@
         }
     }
 
-    private void updateEmergencyCallButtonState() {
+    private void updateEmergencyCallButtonState(int phoneState) {
         if (mEmergencyCallButton != null) {
             boolean showIfCapable = mShowEmergencyButtonByDefault || mUnlockDisabledDueToSimState;
-            mLockPatternUtils.updateEmergencyCallButtonState(mEmergencyCallButton, showIfCapable);
+            mLockPatternUtils.updateEmergencyCallButtonState(mEmergencyCallButton,
+                    phoneState, showIfCapable);
         }
     }
 
@@ -567,7 +580,8 @@
             mShowingBatteryInfo = showBatteryInfo;
             mPluggedIn = pluggedIn;
             mBatteryLevel = batteryLevel;
-            updateStatusLines(true);
+            final MutableInt tmpIcon = new MutableInt(0);
+            update(BATTERY_INFO, getAltTextMessage(tmpIcon));
         }
 
         public void onTimeChanged() {
@@ -575,15 +589,17 @@
         }
 
         public void onRefreshCarrierInfo(CharSequence plmn, CharSequence spn) {
-            setCarrierText(LockPatternUtils.getCarrierString(plmn, spn));
+            mPlmn = plmn;
+            mSpn = spn;
+            updateCarrierTextWithSimStatus(mSimState);
         }
 
         public void onRingerModeChanged(int state) {
 
         }
 
-        public void onPhoneStateChanged(String newState) {
-            updateEmergencyCallButtonState();
+        public void onPhoneStateChanged(int phoneState) {
+            updateEmergencyCallButtonState(phoneState);
         }
 
         /** {@inheritDoc} */
@@ -595,7 +611,7 @@
     private SimStateCallback mSimStateCallback = new SimStateCallback() {
 
         public void onSimStateChanged(State simState) {
-            updateWithSimStatus(simState);
+            updateCarrierTextWithSimStatus(simState);
         }
     };
 
@@ -604,4 +620,22 @@
             mCallback.takeEmergencyCallAction();
         }
     }
+
+    /**
+     * Performs concentenation of PLMN/SPN
+     * @param plmn
+     * @param spn
+     * @return
+     */
+    private static CharSequence makeCarierString(CharSequence plmn, CharSequence spn) {
+        if (plmn != null && spn == null) {
+            return plmn;
+        } else if (plmn != null && spn != null) {
+            return plmn + "|" + spn;
+        } else if (plmn == null && spn != null) {
+            return spn;
+        } else {
+            return "";
+        }
+    }
 }
diff --git a/policy/src/com/android/internal/policy/impl/KeyguardUpdateMonitor.java b/policy/src/com/android/internal/policy/impl/KeyguardUpdateMonitor.java
index 2a23709..10cf3aa 100644
--- a/policy/src/com/android/internal/policy/impl/KeyguardUpdateMonitor.java
+++ b/policy/src/com/android/internal/policy/impl/KeyguardUpdateMonitor.java
@@ -88,6 +88,8 @@
     private ArrayList<InfoCallback> mInfoCallbacks = Lists.newArrayList();
     private ArrayList<SimStateCallback> mSimStateCallbacks = Lists.newArrayList();
     private ContentObserver mContentObserver;
+    private int mRingMode;
+    private int mPhoneState;
 
     // messages for the handler
     private static final int MSG_TIME_UPDATE = 301;
@@ -271,13 +273,21 @@
 
     protected void handlePhoneStateChanged(String newState) {
         if (DEBUG) Log.d(TAG, "handlePhoneStateChanged(" + newState + ")");
+        if (TelephonyManager.EXTRA_STATE_IDLE.equals(newState)) {
+            mPhoneState = TelephonyManager.CALL_STATE_IDLE;
+        } else if (TelephonyManager.EXTRA_STATE_OFFHOOK.equals(newState)) {
+            mPhoneState = TelephonyManager.CALL_STATE_OFFHOOK;
+        } else if (TelephonyManager.EXTRA_STATE_RINGING.equals(newState)) {
+            mPhoneState = TelephonyManager.CALL_STATE_RINGING;
+        }
         for (int i = 0; i < mInfoCallbacks.size(); i++) {
-            mInfoCallbacks.get(i).onPhoneStateChanged(newState);
+            mInfoCallbacks.get(i).onPhoneStateChanged(mPhoneState);
         }
     }
 
     protected void handleRingerModeChange(int mode) {
         if (DEBUG) Log.d(TAG, "handleRingerModeChange(" + mode + ")");
+        mRingMode = mode;
         for (int i = 0; i < mInfoCallbacks.size(); i++) {
             mInfoCallbacks.get(i).onRingerModeChanged(mode);
         }
@@ -459,7 +469,7 @@
          * {@link TelephonyManager@EXTRA_STATE_RINGING}
          * {@link TelephonyManager#EXTRA_STATE_OFFHOOK
          */
-        void onPhoneStateChanged(String newState);
+        void onPhoneStateChanged(int phoneState);
 
         /**
          * Called when visibility of lockscreen clock changes, such as when
@@ -484,8 +494,12 @@
     public void registerInfoCallback(InfoCallback callback) {
         if (!mInfoCallbacks.contains(callback)) {
             mInfoCallbacks.add(callback);
-            // notify the register the current state right away
-            // TODO: need call other callback methods
+            // Notify listener of the current state
+            callback.onRefreshBatteryInfo(shouldShowBatteryInfo(), isPluggedIn(mBatteryStatus),
+                    mBatteryLevel);
+            callback.onTimeChanged();
+            callback.onRingerModeChanged(mRingMode);
+            callback.onPhoneStateChanged(mPhoneState);
             callback.onRefreshCarrierInfo(mTelephonyPlmn, mTelephonySpn);
         } else {
             if (DEBUG) Log.e(TAG, "Object tried to add another INFO callback",
@@ -500,9 +514,7 @@
     public void registerSimStateCallback(SimStateCallback callback) {
         if (!mSimStateCallbacks.contains(callback)) {
             mSimStateCallbacks.add(callback);
-            // notify the register the current sim state right away,
-            // otherwise the register won't receive any state until
-            // sim state gets changed again.
+            // Notify listener of the current state
             callback.onSimStateChanged(mSimState);
         } else {
             if (DEBUG) Log.e(TAG, "Object tried to add another SIM callback",
@@ -581,4 +593,7 @@
         return mClockVisible;
     }
 
+    public int getPhoneState() {
+        return mPhoneState;
+    }
 }
diff --git a/policy/src/com/android/internal/policy/impl/KeyguardViewBase.java b/policy/src/com/android/internal/policy/impl/KeyguardViewBase.java
index 2fcf1dc3..74dde9c 100644
--- a/policy/src/com/android/internal/policy/impl/KeyguardViewBase.java
+++ b/policy/src/com/android/internal/policy/impl/KeyguardViewBase.java
@@ -127,15 +127,6 @@
      */
     abstract public void cleanUp();
 
-    /**
-     * These were added to support FaceLock because the KeyguardViewManager needs to tell the 
-     * LockPatternKeyguardView when to bind and and unbind with FaceLock service.  Although
-     * implemented in LockPatternKeyguardView, these are not implemented in anything else
-     * derived from KeyguardViewBase
-     */
-    abstract public void bindToFaceLock();
-    abstract public void stopAndUnbindFromFaceLock();
-
     @Override
     public boolean dispatchKeyEvent(KeyEvent event) {
         if (shouldEventKeepScreenOnWhileKeyguardShowing(event)) {
diff --git a/policy/src/com/android/internal/policy/impl/KeyguardViewManager.java b/policy/src/com/android/internal/policy/impl/KeyguardViewManager.java
index 91f1527..f15812b 100644
--- a/policy/src/com/android/internal/policy/impl/KeyguardViewManager.java
+++ b/policy/src/com/android/internal/policy/impl/KeyguardViewManager.java
@@ -205,9 +205,6 @@
         mScreenOn = false;
         if (mKeyguardView != null) {
             mKeyguardView.onScreenTurnedOff();
-
-            // When screen is turned off, need to unbind from FaceLock service if using FaceLock
-            mKeyguardView.stopAndUnbindFromFaceLock();
         }
     }
 
@@ -218,9 +215,6 @@
         if (mKeyguardView != null) {
             mKeyguardView.onScreenTurnedOn();
 
-            // When screen is turned on, need to bind to FaceLock service if we are using FaceLock
-            mKeyguardView.bindToFaceLock();
-
             // Caller should wait for this window to be shown before turning
             // on the screen.
             if (mKeyguardHost.getVisibility() == View.VISIBLE) {
@@ -277,12 +271,6 @@
     public synchronized void hide() {
         if (DEBUG) Log.d(TAG, "hide()");
 
-        if (mKeyguardView != null) {
-            // When view is hidden, need to unbind from FaceLock service if we are using FaceLock
-            // e.g., when device becomes unlocked
-            mKeyguardView.stopAndUnbindFromFaceLock();
-        }
-
         if (mKeyguardHost != null) {
             mKeyguardHost.setVisibility(View.GONE);
             // Don't do this right away, so we can let the view continue to animate
diff --git a/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java b/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java
index 0f1d633..3dae5ad 100644
--- a/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java
+++ b/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java
@@ -766,7 +766,7 @@
                         // Don't play lockscreen SFX if the screen went off due to
                         // timeout.
                         mSuppressNextLockSound = true;
-    
+
                         doKeyguardLocked();
                     }
                 }
@@ -777,7 +777,7 @@
                     if (TelephonyManager.EXTRA_STATE_IDLE.equals(mPhoneState)  // call ending
                             && !mScreenOn                           // screen off
                             && mExternallyEnabled) {                // not disabled by any app
-    
+
                         // note: this is a way to gracefully reenable the keyguard when the call
                         // ends and the screen is off without always reenabling the keyguard
                         // each time the screen turns off while in call (and having an occasional ugly
@@ -1270,7 +1270,7 @@
     }
 
     /** {@inheritDoc} */
-    public void onPhoneStateChanged(String newState) {
+    public void onPhoneStateChanged(int phoneState) {
         // ignored
     }
 
diff --git a/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java b/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java
index ffb4838..f24991c 100644
--- a/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java
+++ b/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java
@@ -504,6 +504,9 @@
         } else {
             ((KeyguardScreen) mUnlockScreen).onPause();
         }
+
+        // When screen is turned off, need to unbind from FaceLock service if using FaceLock
+        stopAndUnbindFromFaceLock();
     }
 
     @Override
@@ -514,6 +517,14 @@
         } else {
             ((KeyguardScreen) mUnlockScreen).onResume();
         }
+
+        // When screen is turned on, need to bind to FaceLock service if we are using FaceLock
+        // But only if not dealing with a call
+        if (mUpdateMonitor.getPhoneState() == TelephonyManager.CALL_STATE_IDLE) {
+            bindToFaceLock();
+        } else {
+            mHandler.sendEmptyMessage(MSG_HIDE_FACELOCK_AREA_VIEW);
+        }
     }
 
     private void recreateLockScreen() {
@@ -543,6 +554,11 @@
     @Override
     protected void onDetachedFromWindow() {
         removeCallbacks(mRecreateRunnable);
+
+        // When view is hidden, need to unbind from FaceLock service if we are using FaceLock
+        // e.g., when device becomes unlocked
+        stopAndUnbindFromFaceLock();
+
         super.onDetachedFromWindow();
     }
 
@@ -952,8 +968,9 @@
     // Everything below pertains to FaceLock - might want to separate this out
 
     // Only pattern and pin unlock screens actually have a view for the FaceLock area, so it's not
-    // uncommon for it to not exist.  But if it does exist, we need to make sure it's showing if
-    // FaceLock is enabled, and make sure it's not showing if FaceLock is disabled
+    // uncommon for it to not exist.  But if it does exist, we need to make sure it's shown (hiding
+    // the fallback) if FaceLock is enabled, and make sure it's hidden (showing the unlock) if
+    // FaceLock is disabled
     private void initializeFaceLockAreaView(View view) {
         mFaceLockAreaView = view.findViewById(R.id.faceLockAreaView);
         if (mFaceLockAreaView == null) {
@@ -997,9 +1014,7 @@
                 if (DEBUG) Log.d(TAG, "after bind to FaceLock service");
                 mBoundToFaceLockService = true;
             } else {
-                // On startup I've seen onScreenTurnedOn() get called twice without
-                // onScreenTurnedOff() being called in between, which can cause this (bcolonna)
-                if (DEBUG) Log.w(TAG, "Attempt to bind to FaceLock when already bound");
+                Log.w(TAG, "Attempt to bind to FaceLock when already bound");
             }
         }
     }
@@ -1017,7 +1032,7 @@
             } else {
                 // This could probably happen after the session when someone activates FaceLock
                 // because it wasn't active when the phone was turned on
-                if (DEBUG) Log.w(TAG, "Attempt to unbind from FaceLock when not bound");
+                Log.w(TAG, "Attempt to unbind from FaceLock when not bound");
             }
         }
     }
@@ -1048,7 +1063,7 @@
                 mFaceLockService = null;
                 mFaceLockServiceRunning = false;
             }
-            if (DEBUG) Log.w(TAG, "Unexpected disconnect from FaceLock service");
+            Log.w(TAG, "Unexpected disconnect from FaceLock service");
         }
     };
 
@@ -1099,36 +1114,21 @@
         // Stops the FaceLock UI and indicates that the phone should be unlocked
         @Override
         public void unlock() {
-            if (DEBUG) Log.d(TAG, "FaceLock unlock");
-            // Note that we don't hide the client FaceLockAreaView because we want to keep the
-            // lock screen covered while the phone is unlocked
-
+            if (DEBUG) Log.d(TAG, "FaceLock unlock()");
+            mHandler.sendEmptyMessage(MSG_SHOW_FACELOCK_AREA_VIEW); // Keep fallback covered
             stopFaceLock();
+
             mKeyguardScreenCallback.keyguardDone(true);
             mKeyguardScreenCallback.reportSuccessfulUnlockAttempt();
         }
 
         // Stops the FaceLock UI and exposes the backup method without unlocking
+        // This means either the user has cancelled out or FaceLock failed to recognize them
         @Override
         public void cancel() {
-            // In this case, either the user has cancelled out, or FaceLock failed to recognize them
-            if (DEBUG) Log.d(TAG, "FaceLock cancel");
-            // Here we hide the client FaceLockViewArea to expose the underlying backup method
-            mHandler.sendEmptyMessage(MSG_HIDE_FACELOCK_AREA_VIEW);
+            if (DEBUG) Log.d(TAG, "FaceLock cancel()");
+            mHandler.sendEmptyMessage(MSG_HIDE_FACELOCK_AREA_VIEW); // Expose fallback
             stopFaceLock();
         }
-
-        // Stops the FaceLock UI and puts the phone to sleep
-        @Override
-        public void sleepDevice() {
-            // In this case, it appears the phone has been turned on accidentally
-            if (DEBUG) Log.d(TAG, "FaceLock accidental turn on");
-            // Here we hide the client FaceLockViewArea to expose the underlying backup method
-            mHandler.sendEmptyMessage(MSG_HIDE_FACELOCK_AREA_VIEW);
-            stopFaceLock();
-            // TODO(bcolonna): how do we put the phone back to sleep (i.e., turn off the screen)
-            // TODO(bcolonna): this should be removed once the service is no longer calling it
-            // because we are just going to let the lockscreen timeout
-        }
     };
 }
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 88a05b2..01f5a6f 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -985,6 +985,10 @@
     mNewParameters.clear();
     // do not lock the mutex in destructor
     releaseWakeLock_l();
+    if (mPowerManager != 0) {
+        sp<IBinder> binder = mPowerManager->asBinder();
+        binder->unlinkToDeath(mDeathRecipient);
+    }
 }
 
 void AudioFlinger::ThreadBase::exit()
diff --git a/services/java/com/android/server/BackupManagerService.java b/services/java/com/android/server/BackupManagerService.java
index 6ac6c98..e30ce72 100644
--- a/services/java/com/android/server/BackupManagerService.java
+++ b/services/java/com/android/server/BackupManagerService.java
@@ -3380,7 +3380,8 @@
                 Uri packageUri = Uri.fromFile(apkFile);
                 mInstallObserver.reset();
                 mPackageManager.installPackage(packageUri, mInstallObserver,
-                        PackageManager.INSTALL_REPLACE_EXISTING, installerPackage);
+                        PackageManager.INSTALL_REPLACE_EXISTING | PackageManager.INSTALL_FROM_ADB,
+                        installerPackage);
                 mInstallObserver.waitForCompletion();
 
                 if (mInstallObserver.getResult() != PackageManager.INSTALL_SUCCEEDED) {
@@ -4373,8 +4374,13 @@
                             ParcelFileDescriptor.MODE_TRUNCATE);
 
                 if (mTransport.getRestoreData(mBackupData) != BackupConstants.TRANSPORT_OK) {
+                    // Transport-level failure, so we wind everything up and
+                    // terminate the restore operation.
                     Slog.e(TAG, "Error getting restore data for " + packageName);
                     EventLog.writeEvent(EventLogTags.RESTORE_TRANSPORT_FAILURE);
+                    mBackupData.close();
+                    mBackupDataName.delete();
+                    executeNextState(RestoreState.FINAL);
                     return;
                 }
 
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 72d1917..5006de7 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -65,6 +65,7 @@
 class ServerThread extends Thread {
     private static final String TAG = "SystemServer";
     private static final String ENCRYPTING_STATE = "trigger_restart_min_framework";
+    private static final String ENCRYPTED_STATE = "1";
 
     ContentResolver mContentResolver;
 
@@ -150,10 +151,15 @@
             Slog.i(TAG, "Package Manager");
             // Only run "core" apps if we're encrypting the device.
             String cryptState = SystemProperties.get("vold.decrypt");
-            boolean onlyCore = ENCRYPTING_STATE.equals(cryptState);
-            if (onlyCore) {
+            boolean onlyCore = false;
+            if (ENCRYPTING_STATE.equals(cryptState)) {
                 Slog.w(TAG, "Detected encryption in progress - only parsing core apps");
+                onlyCore = true;
+            } else if (ENCRYPTED_STATE.equals(cryptState)) {
+                Slog.w(TAG, "Device encrypted - only parsing core apps");
+                onlyCore = true;
             }
+
             pm = PackageManagerService.main(context,
                     factoryTest != SystemServer.FACTORY_TEST_OFF,
                     onlyCore);
diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java
index 05f7cf0..eb135b7 100644
--- a/services/java/com/android/server/pm/PackageManagerService.java
+++ b/services/java/com/android/server/pm/PackageManagerService.java
@@ -72,6 +72,7 @@
 import android.content.pm.UserInfo;
 import android.content.pm.ManifestDigest;
 import android.content.pm.VerifierDeviceIdentity;
+import android.content.pm.VerifierInfo;
 import android.net.Uri;
 import android.os.Binder;
 import android.os.Build;
@@ -113,6 +114,8 @@
 import java.io.InputStream;
 import java.io.PrintWriter;
 import java.security.NoSuchAlgorithmException;
+import java.security.PublicKey;
+import java.security.cert.CertificateException;
 import java.text.SimpleDateFormat;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -158,6 +161,7 @@
     private static final boolean DEBUG_INTENT_MATCHING = false;
     private static final boolean DEBUG_PACKAGE_SCANNING = false;
     private static final boolean DEBUG_APP_DIR_OBSERVER = false;
+    private static final boolean DEBUG_VERIFY = false;
 
     static final boolean MULTIPLE_APPLICATION_UIDS = true;
     private static final int RADIO_UID = Process.PHONE_UID;
@@ -208,6 +212,8 @@
             DEFAULT_CONTAINER_PACKAGE,
             "com.android.defcontainer.DefaultContainerService");
 
+    private static final String PACKAGE_MIME_TYPE = "application/vnd.android.package-archive";
+
     private static final String LIB_DIR_NAME = "lib";
 
     static final String mTempContainerPrefix = "smdl2tmp";
@@ -349,7 +355,8 @@
     final HashSet<String> mProtectedBroadcasts = new HashSet<String>();
 
     /** List of packages waiting for verification. */
-    final SparseArray<InstallArgs> mPendingVerification = new SparseArray<InstallArgs>();
+    final SparseArray<PackageVerificationState> mPendingVerification
+            = new SparseArray<PackageVerificationState>();
 
     final ArrayList<PackageParser.Package> mDeferredDexOpt =
             new ArrayList<PackageParser.Package>();
@@ -427,6 +434,8 @@
     final SparseArray<PostInstallData> mRunningInstalls = new SparseArray<PostInstallData>();
     int mNextInstallToken = 1;  // nonzero; will be wrapped back to 1 when ++ overflows
 
+    private final String mRequiredVerifierPackage;
+
     class PackageHandler extends Handler {
         private boolean mBound = false;
         final ArrayList<HandlerParams> mPendingInstalls =
@@ -740,9 +749,10 @@
                 } break;
                 case CHECK_PENDING_VERIFICATION: {
                     final int verificationId = msg.arg1;
-                    final InstallArgs args = mPendingVerification.get(verificationId);
+                    final PackageVerificationState state = mPendingVerification.get(verificationId);
 
-                    if (args != null) {
+                    if (state != null) {
+                        final InstallArgs args = state.getInstallArgs();
                         Slog.i(TAG, "Validation timed out for " + args.packageURI.toString());
                         mPendingVerification.remove(verificationId);
 
@@ -756,32 +766,39 @@
                 }
                 case PACKAGE_VERIFIED: {
                     final int verificationId = msg.arg1;
-                    final boolean verified = msg.arg2 == 1 ? true : false;
 
-                    final InstallArgs args = mPendingVerification.get(verificationId);
-                    if (args == null) {
+                    final PackageVerificationState state = mPendingVerification.get(verificationId);
+                    if (state == null) {
                         Slog.w(TAG, "Invalid validation token " + verificationId + " received");
                         break;
                     }
 
-                    mPendingVerification.remove(verificationId);
+                    final PackageVerificationResponse response = (PackageVerificationResponse) msg.obj;
 
-                    int ret;
-                    if (verified) {
-                        ret = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
-                        try {
-                            ret = args.copyApk(mContainerService, true);
-                        } catch (RemoteException e) {
-                            Slog.e(TAG, "Could not contact the ContainerService");
+                    state.setVerifierResponse(response.callerUid, response.code);
+
+                    if (state.isVerificationComplete()) {
+                        mPendingVerification.remove(verificationId);
+
+                        final InstallArgs args = state.getInstallArgs();
+
+                        int ret;
+                        if (state.isInstallAllowed()) {
+                            ret = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
+                            try {
+                                ret = args.copyApk(mContainerService, true);
+                            } catch (RemoteException e) {
+                                Slog.e(TAG, "Could not contact the ContainerService");
+                            }
+                        } else {
+                            ret = PackageManager.INSTALL_FAILED_VERIFICATION_FAILURE;
                         }
-                    } else {
-                        ret = PackageManager.INSTALL_FAILED_VERIFICATION_FAILURE;
+
+                        processPendingInstall(args, ret);
+
+                        mHandler.sendEmptyMessage(MCS_UNBIND);
                     }
 
-                    processPendingInstall(args, ret);
-
-                    mHandler.sendEmptyMessage(MCS_UNBIND);
-
                     break;
                 }
             }
@@ -1134,10 +1151,49 @@
             // are all flushed.  Not really needed, but keeps things nice and
             // tidy.
             Runtime.getRuntime().gc();
+
+            mRequiredVerifierPackage = getRequiredVerifierLPr();
         } // synchronized (mPackages)
         } // synchronized (mInstallLock)
     }
 
+    private String getRequiredVerifierLPr() {
+        final Intent verification = new Intent(Intent.ACTION_PACKAGE_NEEDS_VERIFICATION);
+        final List<ResolveInfo> receivers = queryIntentReceivers(verification, PACKAGE_MIME_TYPE,
+                PackageManager.GET_DISABLED_COMPONENTS);
+
+        String requiredVerifier = null;
+
+        final int N = receivers.size();
+        for (int i = 0; i < N; i++) {
+            final ResolveInfo info = receivers.get(i);
+
+            if (info.activityInfo == null) {
+                continue;
+            }
+
+            final String packageName = info.activityInfo.packageName;
+
+            final PackageSetting ps = mSettings.mPackages.get(packageName);
+            if (ps == null) {
+                continue;
+            }
+
+            if (!ps.grantedPermissions
+                    .contains(android.Manifest.permission.PACKAGE_VERIFICATION_AGENT)) {
+                continue;
+            }
+
+            if (requiredVerifier != null) {
+                throw new RuntimeException("There can be only one required verifier");
+            }
+
+            requiredVerifier = packageName;
+        }
+
+        return requiredVerifier;
+    }
+
     @Override
     public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
             throws RemoteException {
@@ -4857,17 +4913,110 @@
     }
 
     @Override
-    public void verifyPendingInstall(int id, int verificationCode)
-            throws RemoteException {
-        mContext.enforceCallingOrSelfPermission(
-                android.Manifest.permission.PACKAGE_VERIFICATION_AGENT, null);
-
+    public void verifyPendingInstall(int id, int verificationCode) throws RemoteException {
         final Message msg = mHandler.obtainMessage(PACKAGE_VERIFIED);
+        final PackageVerificationResponse response = new PackageVerificationResponse(
+                verificationCode, Binder.getCallingUid());
         msg.arg1 = id;
-        msg.arg2 = verificationCode;
+        msg.obj = response;
         mHandler.sendMessage(msg);
     }
 
+    private ComponentName matchComponentForVerifier(String packageName,
+            List<ResolveInfo> receivers) {
+        ActivityInfo targetReceiver = null;
+
+        final int NR = receivers.size();
+        for (int i = 0; i < NR; i++) {
+            final ResolveInfo info = receivers.get(i);
+            if (info.activityInfo == null) {
+                continue;
+            }
+
+            if (packageName.equals(info.activityInfo.packageName)) {
+                targetReceiver = info.activityInfo;
+                break;
+            }
+        }
+
+        if (targetReceiver == null) {
+            return null;
+        }
+
+        return new ComponentName(targetReceiver.packageName, targetReceiver.name);
+    }
+
+    private List<ComponentName> matchVerifiers(PackageInfoLite pkgInfo,
+            List<ResolveInfo> receivers, final PackageVerificationState verificationState) {
+        if (pkgInfo.verifiers.length == 0) {
+            return null;
+        }
+
+        final int N = pkgInfo.verifiers.length;
+        final List<ComponentName> sufficientVerifiers = new ArrayList<ComponentName>(N + 1);
+        for (int i = 0; i < N; i++) {
+            final VerifierInfo verifierInfo = pkgInfo.verifiers[i];
+
+            final ComponentName comp = matchComponentForVerifier(verifierInfo.packageName,
+                    receivers);
+            if (comp == null) {
+                continue;
+            }
+
+            final int verifierUid = getUidForVerifier(verifierInfo);
+            if (verifierUid == -1) {
+                continue;
+            }
+
+            if (DEBUG_VERIFY) {
+                Slog.d(TAG, "Added sufficient verifier " + verifierInfo.packageName
+                        + " with the correct signature");
+            }
+            sufficientVerifiers.add(comp);
+            verificationState.addSufficientVerifier(verifierUid);
+        }
+
+        return sufficientVerifiers;
+    }
+
+    private int getUidForVerifier(VerifierInfo verifierInfo) {
+        synchronized (mPackages) {
+            final PackageParser.Package pkg = mPackages.get(verifierInfo.packageName);
+            if (pkg == null) {
+                return -1;
+            } else if (pkg.mSignatures.length != 1) {
+                Slog.i(TAG, "Verifier package " + verifierInfo.packageName
+                        + " has more than one signature; ignoring");
+                return -1;
+            }
+
+            /*
+             * If the public key of the package's signature does not match
+             * our expected public key, then this is a different package and
+             * we should skip.
+             */
+
+            final byte[] expectedPublicKey;
+            try {
+                final Signature verifierSig = pkg.mSignatures[0];
+                final PublicKey publicKey = verifierSig.getPublicKey();
+                expectedPublicKey = publicKey.getEncoded();
+            } catch (CertificateException e) {
+                return -1;
+            }
+
+            final byte[] actualPublicKey = verifierInfo.publicKey.getEncoded();
+
+            if (!Arrays.equals(actualPublicKey, expectedPublicKey)) {
+                Slog.i(TAG, "Verifier package " + verifierInfo.packageName
+                        + " does not have the expected public key; ignoring");
+                return -1;
+            }
+
+            return pkg.applicationInfo.uid;
+        }
+    }
+
     public void finishPackageInstall(int token) {
         enforceSystemOrRoot("Only the system is allowed to finish installs");
 
@@ -5237,9 +5386,11 @@
          */
         public void handleStartCopy() throws RemoteException {
             int ret = PackageManager.INSTALL_SUCCEEDED;
-            boolean fwdLocked = (flags & PackageManager.INSTALL_FORWARD_LOCK) != 0;
-            boolean onSd = (flags & PackageManager.INSTALL_EXTERNAL) != 0;
-            boolean onInt = (flags & PackageManager.INSTALL_INTERNAL) != 0;
+            final boolean fwdLocked = (flags & PackageManager.INSTALL_FORWARD_LOCK) != 0;
+            final boolean onSd = (flags & PackageManager.INSTALL_EXTERNAL) != 0;
+            final boolean onInt = (flags & PackageManager.INSTALL_INTERNAL) != 0;
+            PackageInfoLite pkgLite = null;
+
             if (onInt && onSd) {
                 // Check if both bits are set.
                 Slog.w(TAG, "Conflicting flags specified for installing on both internal and external");
@@ -5261,7 +5412,6 @@
                 }
 
                 // Remote call to find out default install location
-                final PackageInfoLite pkgLite;
                 try {
                     mContext.grantUriPermission(DEFAULT_CONTAINER_PACKAGE, packageURI,
                             Intent.FLAG_GRANT_READ_URI_PERMISSION);
@@ -5304,21 +5454,27 @@
             }
 
             final InstallArgs args = createInstallArgs(this);
+            mArgs = args;
+
             if (ret == PackageManager.INSTALL_SUCCEEDED) {
                 /*
                  * Determine if we have any installed package verifiers. If we
                  * do, then we'll defer to them to verify the packages.
                  */
-                final Intent verification = new Intent(Intent.ACTION_PACKAGE_NEEDS_VERIFICATION,
-                        packageURI);
-                verification.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+                final int requiredUid = mRequiredVerifierPackage == null ? -1
+                        : getPackageUid(mRequiredVerifierPackage);
+                if (requiredUid != -1 && isVerificationEnabled()) {
+                    final Intent verification = new Intent(
+                            Intent.ACTION_PACKAGE_NEEDS_VERIFICATION, packageURI);
+                    verification.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
 
-                final List<ResolveInfo> receivers = queryIntentReceivers(verification, null,
-                        PackageManager.GET_DISABLED_COMPONENTS);
-                if (isVerificationEnabled() && receivers.size() > 0) {
-                    if (DEBUG_INSTALL) {
+                    final List<ResolveInfo> receivers = queryIntentReceivers(verification, null,
+                            PackageManager.GET_DISABLED_COMPONENTS);
+
+                    if (DEBUG_VERIFY) {
                         Slog.d(TAG, "Found " + receivers.size() + " verifiers for intent "
-                                + verification.toString());
+                                + verification.toString() + " with " + pkgLite.verifiers.length
+                                + " optional verifiers");
                     }
 
                     final int verificationId = mPendingVerificationToken++;
@@ -5335,35 +5491,70 @@
                                 verificationURI);
                     }
 
-                    mPendingVerification.append(verificationId, args);
+                    final PackageVerificationState verificationState = new PackageVerificationState(
+                            requiredUid, args);
+
+                    mPendingVerification.append(verificationId, verificationState);
+
+                    final List<ComponentName> sufficientVerifiers = matchVerifiers(pkgLite,
+                            receivers, verificationState);
 
                     /*
-                     * Send the intent to the registered verification agents,
-                     * but only start the verification timeout after the target
-                     * BroadcastReceivers have run.
+                     * If any sufficient verifiers were listed in the package
+                     * manifest, attempt to ask them.
                      */
-                    mContext.sendOrderedBroadcast(verification,
-                            android.Manifest.permission.PACKAGE_VERIFICATION_AGENT,
-                            new BroadcastReceiver() {
-                                @Override
-                                public void onReceive(Context context, Intent intent) {
-                                    final Message msg = mHandler
-                                            .obtainMessage(CHECK_PENDING_VERIFICATION);
-                                    msg.arg1 = verificationId;
-                                    mHandler.sendMessageDelayed(msg, getVerificationTimeout());
-                                }
-                            },
-                            null, 0, null, null);
+                    if (sufficientVerifiers != null) {
+                        final int N = sufficientVerifiers.size();
+                        if (N == 0) {
+                            Slog.i(TAG, "Additional verifiers required, but none installed.");
+                            ret = PackageManager.INSTALL_FAILED_VERIFICATION_FAILURE;
+                        } else {
+                            for (int i = 0; i < N; i++) {
+                                final ComponentName verifierComponent = sufficientVerifiers.get(i);
+
+                                final Intent sufficientIntent = new Intent(verification);
+                                sufficientIntent.setComponent(verifierComponent);
+
+                                mContext.sendBroadcast(sufficientIntent);
+                            }
+                        }
+                    }
+
+                    final ComponentName requiredVerifierComponent = matchComponentForVerifier(
+                            mRequiredVerifierPackage, receivers);
+                    if (ret == PackageManager.INSTALL_SUCCEEDED
+                            && mRequiredVerifierPackage != null) {
+                        /*
+                         * Send the intent to the required verification agent,
+                         * but only start the verification timeout after the
+                         * target BroadcastReceivers have run.
+                         */
+                        verification.setComponent(requiredVerifierComponent);
+                        mContext.sendOrderedBroadcast(verification,
+                                android.Manifest.permission.PACKAGE_VERIFICATION_AGENT,
+                                new BroadcastReceiver() {
+                                    @Override
+                                    public void onReceive(Context context, Intent intent) {
+                                        final Message msg = mHandler
+                                                .obtainMessage(CHECK_PENDING_VERIFICATION);
+                                        msg.arg1 = verificationId;
+                                        mHandler.sendMessageDelayed(msg, getVerificationTimeout());
+                                    }
+                                }, null, 0, null, null);
+
+                        /*
+                         * We don't want the copy to proceed until verification
+                         * succeeds, so null out this field.
+                         */
+                        mArgs = null;
+                    }
                 } else {
-                    // Create copy only if we are not in an erroneous state.
-                    // Remote call to initiate copy using temporary file
-                    mArgs = args;
+                    /*
+                     * No package verification is enabled, so immediately start
+                     * the remote call to initiate copy using temporary file.
+                     */
                     ret = args.copyApk(mContainerService, true);
                 }
-            } else {
-                // There was an error, so let the processPendingInstall() break
-                // the bad news... uh, through a call in handleReturnCode()
-                mArgs = args;
             }
 
             mRet = ret;
@@ -7549,6 +7740,8 @@
 
         public static final int DUMP_PROVIDERS = 1 << 7;
 
+        public static final int DUMP_VERIFIERS = 1 << 8;
+
         public static final int OPTION_SHOW_FILTERS = 1 << 0;
 
         private int mTypes;
@@ -7641,6 +7834,7 @@
                 pw.println("    p[ackages]: dump installed packages");
                 pw.println("    s[hared-users]: dump shared user IDs");
                 pw.println("    m[essages]: print collected runtime messages");
+                pw.println("    v[erifiers]: print package verifier info");
                 pw.println("    <package.name>: info about given package");
                 return;
             } else if ("-f".equals(opt)) {
@@ -7673,11 +7867,24 @@
                 dumpState.setDump(DumpState.DUMP_PROVIDERS);
             } else if ("m".equals(cmd) || "messages".equals(cmd)) {
                 dumpState.setDump(DumpState.DUMP_MESSAGES);
+            } else if ("v".equals(cmd) || "verifiers".equals(cmd)) {
+                dumpState.setDump(DumpState.DUMP_VERIFIERS);
             }
         }
 
         // reader
         synchronized (mPackages) {
+            if (dumpState.isDumping(DumpState.DUMP_VERIFIERS) && packageName == null) {
+                if (dumpState.onTitlePrinted())
+                    pw.println(" ");
+                pw.println("Verifiers:");
+                pw.print("  Required: ");
+                pw.print(mRequiredVerifierPackage);
+                pw.print(" (uid=");
+                pw.print(getPackageUid(mRequiredVerifierPackage));
+                pw.println(")");
+            }
+
             if (dumpState.isDumping(DumpState.DUMP_LIBS) && packageName == null) {
                 if (dumpState.onTitlePrinted())
                     pw.println(" ");
diff --git a/services/java/com/android/server/pm/PackageVerificationResponse.java b/services/java/com/android/server/pm/PackageVerificationResponse.java
new file mode 100644
index 0000000..b2ae0dd
--- /dev/null
+++ b/services/java/com/android/server/pm/PackageVerificationResponse.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.pm;
+
+public class PackageVerificationResponse {
+    public final int code;
+
+    public final int callerUid;
+
+    public PackageVerificationResponse(int code, int callerUid) {
+        this.code = code;
+        this.callerUid = callerUid;
+    }
+}
diff --git a/services/java/com/android/server/pm/PackageVerificationState.java b/services/java/com/android/server/pm/PackageVerificationState.java
new file mode 100644
index 0000000..e5b89c1
--- /dev/null
+++ b/services/java/com/android/server/pm/PackageVerificationState.java
@@ -0,0 +1,149 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.pm;
+
+import com.android.server.pm.PackageManagerService.InstallArgs;
+
+import android.content.pm.PackageManager;
+import android.util.SparseBooleanArray;
+
+/**
+ * Tracks the package verification state for a particular package. Each package
+ * verification has a required verifier and zero or more sufficient verifiers.
+ * Only one of the sufficient verifier list must return affirmative to allow the
+ * package to be considered verified. If there are zero sufficient verifiers,
+ * then package verification is considered complete.
+ */
+class PackageVerificationState {
+    private final InstallArgs mArgs;
+
+    private final SparseBooleanArray mSufficientVerifierUids;
+
+    private final int mRequiredVerifierUid;
+
+    private boolean mSufficientVerificationComplete;
+
+    private boolean mSufficientVerificationPassed;
+
+    private boolean mRequiredVerificationComplete;
+
+    private boolean mRequiredVerificationPassed;
+
+    /**
+     * Create a new package verification state where {@code requiredVerifierUid}
+     * is the user ID for the package that must reply affirmative before things
+     * can continue.
+     *
+     * @param requiredVerifierUid user ID of required package verifier
+     * @param args
+     */
+    public PackageVerificationState(int requiredVerifierUid, InstallArgs args) {
+        mRequiredVerifierUid = requiredVerifierUid;
+        mArgs = args;
+        mSufficientVerifierUids = new SparseBooleanArray();
+    }
+
+    public InstallArgs getInstallArgs() {
+        return mArgs;
+    }
+
+    /**
+     * Add a verifier which is added to our sufficient list.
+     *
+     * @param uid user ID of sufficient verifier
+     */
+    public void addSufficientVerifier(int uid) {
+        mSufficientVerifierUids.put(uid, true);
+    }
+
+    /**
+     * Should be called when a verification is received from an agent so the
+     * state of the package verification can be tracked.
+     *
+     * @param uid user ID of the verifying agent
+     * @return {@code true} if the verifying agent actually exists in our list
+     */
+    public boolean setVerifierResponse(int uid, int code) {
+        if (uid == mRequiredVerifierUid) {
+            mRequiredVerificationComplete = true;
+            switch (code) {
+                case PackageManager.VERIFICATION_ALLOW_WITHOUT_SUFFICIENT:
+                    mSufficientVerifierUids.clear();
+                    // fall through
+                case PackageManager.VERIFICATION_ALLOW:
+                    mRequiredVerificationPassed = true;
+                    break;
+                default:
+                    mRequiredVerificationPassed = false;
+            }
+            return true;
+        } else {
+            if (mSufficientVerifierUids.get(uid)) {
+                if (code == PackageManager.VERIFICATION_ALLOW) {
+                    mSufficientVerificationComplete = true;
+                    mSufficientVerificationPassed = true;
+                }
+
+                mSufficientVerifierUids.delete(uid);
+                if (mSufficientVerifierUids.size() == 0) {
+                    mSufficientVerificationComplete = true;
+                }
+
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    /**
+     * Returns whether verification is considered complete. This means that the
+     * required verifier and at least one of the sufficient verifiers has
+     * returned a positive verification.
+     *
+     * @return {@code true} when verification is considered complete
+     */
+    public boolean isVerificationComplete() {
+        if (!mRequiredVerificationComplete) {
+            return false;
+        }
+
+        if (mSufficientVerifierUids.size() == 0) {
+            return true;
+        }
+
+        return mSufficientVerificationComplete;
+    }
+
+    /**
+     * Returns whether installation should be allowed. This should only be
+     * called after {@link #isVerificationComplete()} returns {@code true}.
+     *
+     * @return {@code true} if installation should be allowed
+     */
+    public boolean isInstallAllowed() {
+        if (!mRequiredVerificationPassed) {
+            return false;
+        }
+
+        if (mSufficientVerificationComplete) {
+            return mSufficientVerificationPassed;
+        }
+
+        return true;
+    }
+}
diff --git a/services/java/com/android/server/wm/WindowState.java b/services/java/com/android/server/wm/WindowState.java
index 455d6649..3640a15 100644
--- a/services/java/com/android/server/wm/WindowState.java
+++ b/services/java/com/android/server/wm/WindowState.java
@@ -636,7 +636,7 @@
                 final boolean isHwAccelerated = (mAttrs.flags &
                         WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED) != 0;
                 final int format = isHwAccelerated ? PixelFormat.TRANSLUCENT : mAttrs.format;
-                if (isHwAccelerated && mAttrs.format == PixelFormat.OPAQUE) {
+                if (!PixelFormat.formatHasAlpha(mAttrs.format)) {
                     flags |= Surface.OPAQUE;
                 }
                 mSurface = new Surface(
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index f85ce7f..41d7a90 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -112,6 +112,11 @@
     mSurfaceTexture->abandon();
 }
 
+void Layer::setName(const String8& name) {
+    LayerBase::setName(name);
+    mSurfaceTexture->setName(name);
+}
+
 sp<ISurface> Layer::createSurface()
 {
     class BSurface : public BnSurface, public LayerCleaner {
@@ -371,11 +376,12 @@
             Layer::State& editDraw(mDrawingState);
             editDraw.requested_w = temp.requested_w;
             editDraw.requested_h = temp.requested_h;
-
-            // record the new size, form this point on, when the client request
-            // a buffer, it'll get the new size.
-            mSurfaceTexture->setDefaultBufferSize(temp.requested_w, temp.requested_h);
         }
+
+        // record the new size, form this point on, when the client request
+        // a buffer, it'll get the new size.
+        mSurfaceTexture->setDefaultBufferSize(temp.requested_w,
+                temp.requested_h);
     }
 
     if (temp.sequence != front.sequence) {
@@ -578,7 +584,7 @@
 uint32_t Layer::getTransformHint() const {
     uint32_t orientation = 0;
     if (!mFlinger->mDebugDisableTransformHint) {
-        orientation = getOrientation();
+        orientation = getPlaneOrientation();
         if (orientation & Transform::ROT_INVALID) {
             orientation = 0;
         }
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index ff389ae..82e3521 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -74,6 +74,7 @@
     virtual bool isProtected() const;
     virtual void onRemoved();
     virtual sp<Layer> getLayer() const { return const_cast<Layer*>(this); }
+    virtual void setName(const String8& name);
 
     // LayerBaseClient interface
     virtual wp<IBinder> getSurfaceTextureBinder() const;
diff --git a/services/surfaceflinger/LayerBase.cpp b/services/surfaceflinger/LayerBase.cpp
index e5ce814..7a47f62 100644
--- a/services/surfaceflinger/LayerBase.cpp
+++ b/services/surfaceflinger/LayerBase.cpp
@@ -45,6 +45,7 @@
       mFlinger(flinger), mFiltering(false),
       mNeedsFiltering(false), mInOverlay(false),
       mOrientation(0),
+      mPlaneOrientation(0),
       mTransactionFlags(0),
       mPremultipliedAlpha(true), mName("unnamed"), mDebug(false),
       mInvalidate(0)
@@ -256,6 +257,7 @@
 
     // cache a few things...
     mOrientation = tr.getOrientation();
+    mPlaneOrientation = planeTransform.getOrientation();
     mTransform = tr;
     mTransformedBounds = tr.makeBounds(w, h);
 }
diff --git a/services/surfaceflinger/LayerBase.h b/services/surfaceflinger/LayerBase.h
index a14b397..7f62145 100644
--- a/services/surfaceflinger/LayerBase.h
+++ b/services/surfaceflinger/LayerBase.h
@@ -81,7 +81,7 @@
                 Region          transparentRegion;
             };
 
-            void setName(const String8& name);
+    virtual void setName(const String8& name);
             String8 getName() const;
 
             // modify current state
@@ -221,6 +221,7 @@
     inline  State&          currentState()          { return mCurrentState; }
 
     int32_t  getOrientation() const { return mOrientation; }
+    int32_t  getPlaneOrientation() const { return mPlaneOrientation; }
     
 protected:
     const GraphicPlane& graphicPlane(int dpy) const;
@@ -254,6 +255,7 @@
 protected:
                 // cached during validateVisibility()
                 int32_t         mOrientation;
+                int32_t         mPlaneOrientation;
                 Transform       mTransform;
                 GLfloat         mVertices[4][2];
                 Rect            mTransformedBounds;
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageVerificationStateTest.java b/services/tests/servicestests/src/com/android/server/pm/PackageVerificationStateTest.java
new file mode 100644
index 0000000..ebd3633
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageVerificationStateTest.java
@@ -0,0 +1,205 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.pm;
+
+import android.content.pm.PackageManager;
+import com.android.server.pm.PackageVerificationState;
+
+import android.test.AndroidTestCase;
+
+public class PackageVerificationStateTest extends AndroidTestCase {
+    private static final int REQUIRED_UID = 1948;
+
+    private static final int SUFFICIENT_UID_1 = 1005;
+
+    private static final int SUFFICIENT_UID_2 = 8938;
+
+    public void testPackageVerificationState_OnlyRequiredVerifier_AllowedInstall() {
+        PackageVerificationState state = new PackageVerificationState(REQUIRED_UID, null);
+
+        assertFalse("Verification should not be marked as complete yet",
+                state.isVerificationComplete());
+
+        state.setVerifierResponse(REQUIRED_UID, PackageManager.VERIFICATION_ALLOW);
+
+        assertTrue("Verification should be considered complete now",
+                state.isVerificationComplete());
+
+        assertTrue("Installation should be marked as allowed",
+                state.isInstallAllowed());
+    }
+
+    public void testPackageVerificationState_OnlyRequiredVerifier_DeniedInstall() {
+        PackageVerificationState state = new PackageVerificationState(REQUIRED_UID, null);
+
+        assertFalse("Verification should not be marked as complete yet",
+                state.isVerificationComplete());
+
+        state.setVerifierResponse(REQUIRED_UID, PackageManager.VERIFICATION_REJECT);
+
+        assertTrue("Verification should be considered complete now",
+                state.isVerificationComplete());
+
+        assertFalse("Installation should be marked as allowed",
+                state.isInstallAllowed());
+    }
+
+    public void testPackageVerificationState_RequiredAndOneSufficient_RequiredDeniedInstall() {
+        PackageVerificationState state = new PackageVerificationState(REQUIRED_UID, null);
+
+        assertFalse("Verification should not be marked as complete yet",
+                state.isVerificationComplete());
+
+        state.addSufficientVerifier(SUFFICIENT_UID_1);
+
+        assertFalse("Verification should not be marked as complete yet",
+                state.isVerificationComplete());
+
+        state.setVerifierResponse(SUFFICIENT_UID_1, PackageManager.VERIFICATION_ALLOW);
+
+        assertFalse("Verification should not be marked as complete yet",
+                state.isVerificationComplete());
+
+        state.setVerifierResponse(REQUIRED_UID, PackageManager.VERIFICATION_REJECT);
+
+        assertTrue("Verification should be considered complete now",
+                state.isVerificationComplete());
+
+        assertFalse("Installation should be marked as allowed",
+                state.isInstallAllowed());
+    }
+
+    public void testPackageVerificationState_RequiredAndOneSufficient_SufficientDeniedInstall() {
+        PackageVerificationState state = new PackageVerificationState(REQUIRED_UID, null);
+
+        assertFalse("Verification should not be marked as complete yet",
+                state.isVerificationComplete());
+
+        state.addSufficientVerifier(SUFFICIENT_UID_1);
+
+        assertFalse("Verification should not be marked as complete yet",
+                state.isVerificationComplete());
+
+        state.setVerifierResponse(SUFFICIENT_UID_1, PackageManager.VERIFICATION_REJECT);
+
+        assertFalse("Verification should not be marked as complete yet",
+                state.isVerificationComplete());
+
+        state.setVerifierResponse(REQUIRED_UID, PackageManager.VERIFICATION_ALLOW);
+
+        assertTrue("Verification should be considered complete now",
+                state.isVerificationComplete());
+
+        assertFalse("Installation should be marked as allowed",
+                state.isInstallAllowed());
+    }
+
+    public void testPackageVerificationState_RequiredAndTwoSufficient_OneSufficientIsEnough() {
+        PackageVerificationState state = new PackageVerificationState(REQUIRED_UID, null);
+
+        assertFalse("Verification should not be marked as complete yet",
+                state.isVerificationComplete());
+
+        state.addSufficientVerifier(SUFFICIENT_UID_1);
+        state.addSufficientVerifier(SUFFICIENT_UID_2);
+
+        assertFalse("Verification should not be marked as complete yet",
+                state.isVerificationComplete());
+
+        state.setVerifierResponse(SUFFICIENT_UID_1, PackageManager.VERIFICATION_ALLOW);
+
+        assertFalse("Verification should not be marked as complete yet",
+                state.isVerificationComplete());
+
+        state.setVerifierResponse(REQUIRED_UID, PackageManager.VERIFICATION_ALLOW);
+
+        assertTrue("Verification should be considered complete now",
+                state.isVerificationComplete());
+
+        assertTrue("Installation should be marked as allowed",
+                state.isInstallAllowed());
+    }
+
+    public void testPackageVerificationState_RequiredAndTwoSufficient_SecondSufficientIsEnough() {
+        PackageVerificationState state = new PackageVerificationState(REQUIRED_UID, null);
+
+        assertFalse("Verification should not be marked as complete yet",
+                state.isVerificationComplete());
+
+        state.addSufficientVerifier(SUFFICIENT_UID_1);
+        state.addSufficientVerifier(SUFFICIENT_UID_2);
+
+        assertFalse("Verification should not be marked as complete yet",
+                state.isVerificationComplete());
+
+        state.setVerifierResponse(REQUIRED_UID, PackageManager.VERIFICATION_ALLOW);
+
+        assertFalse("Verification should not be marked as complete yet",
+                state.isVerificationComplete());
+
+        state.setVerifierResponse(SUFFICIENT_UID_1, PackageManager.VERIFICATION_REJECT);
+
+        assertFalse("Verification should not be marked as complete yet",
+                state.isVerificationComplete());
+
+        state.setVerifierResponse(SUFFICIENT_UID_2, PackageManager.VERIFICATION_ALLOW);
+
+        assertTrue("Verification should be considered complete now",
+                state.isVerificationComplete());
+
+        assertTrue("Installation should be marked as allowed",
+                state.isInstallAllowed());
+    }
+
+    public void testPackageVerificationState_RequiredAndTwoSufficient_RequiredOverrides() {
+        PackageVerificationState state = new PackageVerificationState(REQUIRED_UID, null);
+
+        assertFalse("Verification should not be marked as complete yet",
+                state.isVerificationComplete());
+
+        state.addSufficientVerifier(SUFFICIENT_UID_1);
+        state.addSufficientVerifier(SUFFICIENT_UID_2);
+
+        assertFalse("Verification should not be marked as complete yet",
+                state.isVerificationComplete());
+
+        state.setVerifierResponse(REQUIRED_UID,
+                PackageManager.VERIFICATION_ALLOW_WITHOUT_SUFFICIENT);
+
+        assertTrue("Verification should be marked as complete immediately",
+                state.isVerificationComplete());
+
+        assertTrue("Installation should be marked as allowed",
+                state.isInstallAllowed());
+
+        state.setVerifierResponse(SUFFICIENT_UID_1, PackageManager.VERIFICATION_REJECT);
+
+        assertTrue("Verification should still be marked as completed",
+                state.isVerificationComplete());
+
+        assertTrue("Installation should be marked as allowed still",
+                state.isInstallAllowed());
+
+        state.setVerifierResponse(SUFFICIENT_UID_2, PackageManager.VERIFICATION_ALLOW);
+
+        assertTrue("Verification should still be complete",
+                state.isVerificationComplete());
+
+        assertTrue("Installation should be marked as allowed still",
+                state.isInstallAllowed());
+    }
+}
diff --git a/telephony/java/android/telephony/PhoneNumberUtils.java b/telephony/java/android/telephony/PhoneNumberUtils.java
index ea349bf..34f8848 100644
--- a/telephony/java/android/telephony/PhoneNumberUtils.java
+++ b/telephony/java/android/telephony/PhoneNumberUtils.java
@@ -1409,6 +1409,11 @@
      * @hide
      */
     public static String formatNumber(String phoneNumber, String defaultCountryIso) {
+        // Do not attempt to format numbers that start with a hash or star symbol.
+        if (phoneNumber.startsWith("#") || phoneNumber.startsWith("*")) {
+            return phoneNumber;
+        }
+
         PhoneNumberUtil util = PhoneNumberUtil.getInstance();
         String result = null;
         try {
diff --git a/telephony/java/com/android/internal/telephony/TelephonyProperties.java b/telephony/java/com/android/internal/telephony/TelephonyProperties.java
index 101dd55..abb4523 100644
--- a/telephony/java/com/android/internal/telephony/TelephonyProperties.java
+++ b/telephony/java/com/android/internal/telephony/TelephonyProperties.java
@@ -182,9 +182,4 @@
      * in commercial configuration.
      */
     static final String PROPERTY_TEST_CSIM = "persist.radio.test-csim";
-
-    /**
-     * Set to true to indicate a test ims registration required.
-     */
-    static final String PROPERTY_IMS_REG_REQUIRED = "persist.radio.imsregrequired";
 }
diff --git a/telephony/tests/telephonytests/src/com/android/internal/telephony/PhoneNumberUtilsTest.java b/telephony/tests/telephonytests/src/com/android/internal/telephony/PhoneNumberUtilsTest.java
index 849ff48..e2349af 100644
--- a/telephony/tests/telephonytests/src/com/android/internal/telephony/PhoneNumberUtilsTest.java
+++ b/telephony/tests/telephonytests/src/com/android/internal/telephony/PhoneNumberUtilsTest.java
@@ -513,7 +513,19 @@
         assertEquals("(650) 291-0000", PhoneNumberUtils.formatNumber("650 2910000", "US"));
         assertEquals("123-4567", PhoneNumberUtils.formatNumber("1234567", "US"));
         assertEquals("(800) 466-4114", PhoneNumberUtils.formatNumber("800-GOOG-114", "US"));
+    }
 
+    @SmallTest
+    public void testFormatNumber_LeadingStarAndHash() {
+        // Numbers with a leading '*' or '#' should be left unchanged.
+        assertEquals("*650 2910000", PhoneNumberUtils.formatNumber("*650 2910000", "US"));
+        assertEquals("#650 2910000", PhoneNumberUtils.formatNumber("#650 2910000", "US"));
+        assertEquals("*#650 2910000", PhoneNumberUtils.formatNumber("*#650 2910000", "US"));
+        assertEquals("#*650 2910000", PhoneNumberUtils.formatNumber("#*650 2910000", "US"));
+        assertEquals("#650*2910000", PhoneNumberUtils.formatNumber("#650*2910000", "US"));
+        assertEquals("#650*2910000", PhoneNumberUtils.formatNumber("#650*2910000", "US"));
+        assertEquals("##650 2910000", PhoneNumberUtils.formatNumber("##650 2910000", "US"));
+        assertEquals("**650 2910000", PhoneNumberUtils.formatNumber("**650 2910000", "US"));
     }
 
     @SmallTest
diff --git a/test-runner/src/android/test/mock/MockPackageManager.java b/test-runner/src/android/test/mock/MockPackageManager.java
index 3525abe..58680ea 100644
--- a/test-runner/src/android/test/mock/MockPackageManager.java
+++ b/test-runner/src/android/test/mock/MockPackageManager.java
@@ -36,9 +36,11 @@
 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;
diff --git a/tests/DataIdleTest/src/com/android/tests/dataidle/DataIdleTest.java b/tests/DataIdleTest/src/com/android/tests/dataidle/DataIdleTest.java
index b803b98..a13c0c9 100644
--- a/tests/DataIdleTest/src/com/android/tests/dataidle/DataIdleTest.java
+++ b/tests/DataIdleTest/src/com/android/tests/dataidle/DataIdleTest.java
@@ -89,18 +89,27 @@
         Bundle result = new Bundle();
         long rxBytes = 0;
         long txBytes = 0;
+        long rxPackets = 0;
+        long txPackets = 0;
         for (int i = 0; i < stats.size(); ++i) {
             // Label will be iface_uid_tag_set
             Entry  statsEntry = stats.getValues(i, null);
+            // Debugging use.
+            /*
             String labelTemplate = String.format("%s_%d_%d_%d", statsEntry.iface, statsEntry.uid,
                     statsEntry.tag, statsEntry.set) + "_%s";
             result.putLong(String.format(labelTemplate, "rxBytes"), statsEntry.rxBytes);
             result.putLong(String.format(labelTemplate, "txBytes"), statsEntry.txBytes);
+            */
+            rxPackets += statsEntry.rxPackets;
             rxBytes += statsEntry.rxBytes;
+            txPackets += statsEntry.txPackets;
             txBytes += statsEntry.txBytes;
         }
-        result.putLong("Total rxBytes", rxBytes);
-        result.putLong("Total txBytes", txBytes);
+        result.putLong("Total rx Bytes", rxBytes);
+        result.putLong("Total tx Bytes", txBytes);
+        result.putLong("Total rx Packets", rxPackets);
+        result.putLong("Total tx Packets", txPackets);
         getInstrumentation().sendStatus(INSTRUMENTATION_IN_PROGRESS, result);
 
     }
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java b/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java
index 4ba2e18..945b8f2 100644
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java
@@ -916,6 +916,9 @@
         settings.setWorkersEnabled(false);
         settings.setXSSAuditorEnabled(false);
         settings.setPageCacheCapacity(0);
+        // this enables cpu upload path (as opposed to gpu upload path)
+        // and it's only meant to be a temporary workaround!
+        settings.setProperty("enable_cpu_upload_path", "true");
     }
 
     private WebView mWebView;
diff --git a/wifi/java/android/net/wifi/WifiNative.java b/wifi/java/android/net/wifi/WifiNative.java
index a6ea6d4..6ff1bc2 100644
--- a/wifi/java/android/net/wifi/WifiNative.java
+++ b/wifi/java/android/net/wifi/WifiNative.java
@@ -106,12 +106,6 @@
 
     public native static String statusCommand();
 
-    public native static int getRssiCommand();
-
-    public native static int getRssiApproxCommand();
-
-    public native static int getLinkSpeedCommand();
-
     public native static String getMacAddressCommand();
 
     public native static String scanResultsCommand();
@@ -209,6 +203,16 @@
 
     private native static String doStringCommand(String command);
 
+    /** Example output:
+     * RSSI=-65
+     * LINKSPEED=48
+     * NOISE=9999
+     * FREQUENCY=0
+     */
+    public static String signalPoll() {
+        return doStringCommand("SIGNAL_POLL");
+    }
+
     public static boolean wpsPbc() {
         return doBooleanCommand("WPS_PBC");
     }
diff --git a/wifi/java/android/net/wifi/WifiStateMachine.java b/wifi/java/android/net/wifi/WifiStateMachine.java
index 052d332..41fc55d 100644
--- a/wifi/java/android/net/wifi/WifiStateMachine.java
+++ b/wifi/java/android/net/wifi/WifiStateMachine.java
@@ -1362,7 +1362,28 @@
      * Fetch RSSI and linkspeed on current connection
      */
     private void fetchRssiAndLinkSpeedNative() {
-        int newRssi = WifiNative.getRssiCommand();
+        int newRssi = -1;
+        int newLinkSpeed = -1;
+
+        String signalPoll = WifiNative.signalPoll();
+
+        if (signalPoll != null) {
+            String[] lines = signalPoll.split("\n");
+            for (String line : lines) {
+                String[] prop = line.split("=");
+                if (prop.length < 2) continue;
+                try {
+                    if (prop[0].equals("RSSI")) {
+                        newRssi = Integer.parseInt(prop[1]);
+                    } else if (prop[0].equals("LINKSPEED")) {
+                        newLinkSpeed = Integer.parseInt(prop[1]);
+                    }
+                } catch (NumberFormatException e) {
+                    //Ignore, defaults on rssi and linkspeed are assigned
+                }
+            }
+        }
+
         if (newRssi != -1 && MIN_RSSI < newRssi && newRssi < MAX_RSSI) { // screen out invalid values
             /* some implementations avoid negative values by adding 256
              * so we need to adjust for that here.
@@ -1390,7 +1411,7 @@
         } else {
             mWifiInfo.setRssi(MIN_RSSI);
         }
-        int newLinkSpeed = WifiNative.getLinkSpeedCommand();
+
         if (newLinkSpeed != -1) {
             mWifiInfo.setLinkSpeed(newLinkSpeed);
         }