Merge "Pass the targetSdkVersion through to the zygote-forked dalvik."
diff --git a/Android.mk b/Android.mk
index 9fbdde7..335fb73 100644
--- a/Android.mk
+++ b/Android.mk
@@ -36,6 +36,7 @@
 # EventLogTags files.
 LOCAL_SRC_FILES += \
        core/java/android/content/EventLogTags.logtags \
+       core/java/android/speech/tts/EventLogTags.logtags \
        core/java/android/webkit/EventLogTags.logtags \
        telephony/java/com/android/internal/telephony/EventLogTags.logtags \
 
diff --git a/api/current.txt b/api/current.txt
index 1e13e24..559672f 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -312,10 +312,15 @@
     field public static final int codes = 16843330; // 0x1010242
     field public static final int collapseColumns = 16843083; // 0x101014b
     field public static final int color = 16843173; // 0x10101a5
+    field public static final int colorActivatedHighlight = 16843684; // 0x10103a4
     field public static final int colorBackground = 16842801; // 0x1010031
     field public static final int colorBackgroundCacheHint = 16843435; // 0x10102ab
+    field public static final int colorFocusedHighlight = 16843683; // 0x10103a3
     field public static final int colorForeground = 16842800; // 0x1010030
     field public static final int colorForegroundInverse = 16843270; // 0x1010206
+    field public static final int colorLongPressedHighlight = 16843682; // 0x10103a2
+    field public static final int colorMultiSelectHighlight = 16843685; // 0x10103a5
+    field public static final int colorPressedHighlight = 16843681; // 0x10103a1
     field public static final int columnCount = 16843638; // 0x1010376
     field public static final int columnDelay = 16843215; // 0x10101cf
     field public static final int columnOrderPreserved = 16843639; // 0x1010377
@@ -941,6 +946,7 @@
     field public static final int tension = 16843370; // 0x101026a
     field public static final int testOnly = 16843378; // 0x1010272
     field public static final int text = 16843087; // 0x101014f
+    field public static final int textAllCaps = 16843680; // 0x10103a0
     field public static final int textAppearance = 16842804; // 0x1010034
     field public static final int textAppearanceButton = 16843271; // 0x1010207
     field public static final int textAppearanceInverse = 16842805; // 0x1010035
@@ -1120,6 +1126,16 @@
     field public static final int background_light = 17170447; // 0x106000f
     field public static final int black = 17170444; // 0x106000c
     field public static final int darker_gray = 17170432; // 0x1060000
+    field public static final int holo_blue_bright = 17170459; // 0x106001b
+    field public static final int holo_blue_dark = 17170451; // 0x1060013
+    field public static final int holo_blue_light = 17170450; // 0x1060012
+    field public static final int holo_green_dark = 17170453; // 0x1060015
+    field public static final int holo_green_light = 17170452; // 0x1060014
+    field public static final int holo_orange_dark = 17170457; // 0x1060019
+    field public static final int holo_orange_light = 17170456; // 0x1060018
+    field public static final int holo_purple = 17170458; // 0x106001a
+    field public static final int holo_red_dark = 17170455; // 0x1060017
+    field public static final int holo_red_light = 17170454; // 0x1060016
     field public static final int primary_text_dark = 17170433; // 0x1060001
     field public static final int primary_text_dark_nodisable = 17170434; // 0x1060002
     field public static final int primary_text_light = 17170435; // 0x1060003
@@ -14998,6 +15014,257 @@
     field public static final deprecated java.lang.String URL = "url";
   }
 
+  public final class CalendarContract {
+    field public static final java.lang.String ACCOUNT_TYPE_LOCAL = "LOCAL";
+    field public static final java.lang.String ACTION_EVENT_REMINDER = "android.intent.action.EVENT_REMINDER";
+    field public static final java.lang.String AUTHORITY = "com.android.calendar";
+    field public static final java.lang.String CALLER_IS_SYNCADAPTER = "caller_is_syncadapter";
+    field public static final android.net.Uri CONTENT_URI;
+    field public static final java.lang.String EXTRA_EVENT_BEGIN_TIME = "beginTime";
+    field public static final java.lang.String EXTRA_EVENT_END_TIME = "endTime";
+  }
+
+  public static final class CalendarContract.Attendees implements android.provider.BaseColumns android.provider.CalendarContract.AttendeesColumns android.provider.CalendarContract.EventsColumns {
+    method public static final android.database.Cursor query(android.content.ContentResolver, long, java.lang.String[]);
+    field public static final android.net.Uri CONTENT_URI;
+  }
+
+  protected static abstract interface CalendarContract.AttendeesColumns {
+    field public static final java.lang.String ATTENDEE_EMAIL = "attendeeEmail";
+    field public static final java.lang.String ATTENDEE_NAME = "attendeeName";
+    field public static final java.lang.String ATTENDEE_RELATIONSHIP = "attendeeRelationship";
+    field public static final java.lang.String ATTENDEE_STATUS = "attendeeStatus";
+    field public static final int ATTENDEE_STATUS_ACCEPTED = 1; // 0x1
+    field public static final int ATTENDEE_STATUS_DECLINED = 2; // 0x2
+    field public static final int ATTENDEE_STATUS_INVITED = 3; // 0x3
+    field public static final int ATTENDEE_STATUS_NONE = 0; // 0x0
+    field public static final int ATTENDEE_STATUS_TENTATIVE = 4; // 0x4
+    field public static final java.lang.String ATTENDEE_TYPE = "attendeeType";
+    field public static final java.lang.String EVENT_ID = "event_id";
+    field public static final int RELATIONSHIP_ATTENDEE = 1; // 0x1
+    field public static final int RELATIONSHIP_NONE = 0; // 0x0
+    field public static final int RELATIONSHIP_ORGANIZER = 2; // 0x2
+    field public static final int RELATIONSHIP_PERFORMER = 3; // 0x3
+    field public static final int RELATIONSHIP_SPEAKER = 4; // 0x4
+    field public static final int TYPE_NONE = 0; // 0x0
+    field public static final int TYPE_OPTIONAL = 2; // 0x2
+    field public static final int TYPE_REQUIRED = 1; // 0x1
+  }
+
+  public static final class CalendarContract.CalendarAlerts implements android.provider.BaseColumns android.provider.CalendarContract.CalendarAlertsColumns android.provider.CalendarContract.CalendarColumns android.provider.CalendarContract.EventsColumns {
+    field public static final android.net.Uri CONTENT_URI;
+    field public static final android.net.Uri CONTENT_URI_BY_INSTANCE;
+  }
+
+  protected static abstract interface CalendarContract.CalendarAlertsColumns {
+    field public static final java.lang.String ALARM_TIME = "alarmTime";
+    field public static final java.lang.String BEGIN = "begin";
+    field public static final java.lang.String CREATION_TIME = "creationTime";
+    field public static final java.lang.String DEFAULT_SORT_ORDER = "begin ASC,title ASC";
+    field public static final java.lang.String END = "end";
+    field public static final java.lang.String EVENT_ID = "event_id";
+    field public static final java.lang.String MINUTES = "minutes";
+    field public static final java.lang.String NOTIFY_TIME = "notifyTime";
+    field public static final java.lang.String RECEIVED_TIME = "receivedTime";
+    field public static final java.lang.String STATE = "state";
+    field public static final int STATE_DISMISSED = 2; // 0x2
+    field public static final int STATE_FIRED = 1; // 0x1
+    field public static final int STATE_SCHEDULED = 0; // 0x0
+  }
+
+  public static final class CalendarContract.CalendarCache implements android.provider.CalendarContract.CalendarCacheColumns {
+    field public static final java.lang.String KEY_TIMEZONE_INSTANCES = "timezoneInstances";
+    field public static final java.lang.String KEY_TIMEZONE_INSTANCES_PREVIOUS = "timezoneInstancesPrevious";
+    field public static final java.lang.String KEY_TIMEZONE_TYPE = "timezoneType";
+    field public static final java.lang.String TIMEZONE_TYPE_AUTO = "auto";
+    field public static final java.lang.String TIMEZONE_TYPE_HOME = "home";
+    field public static final android.net.Uri URI;
+  }
+
+  protected static abstract interface CalendarContract.CalendarCacheColumns {
+    field public static final java.lang.String KEY = "key";
+    field public static final java.lang.String VALUE = "value";
+  }
+
+  protected static abstract interface CalendarContract.CalendarColumns {
+    field public static final java.lang.String ALLOWED_REMINDERS = "allowedReminders";
+    field public static final java.lang.String CALENDAR_ACCESS_LEVEL = "calendar_access_level";
+    field public static final java.lang.String CALENDAR_COLOR = "calendar_color";
+    field public static final java.lang.String CALENDAR_DISPLAY_NAME = "calendar_displayName";
+    field public static final java.lang.String CALENDAR_TIME_ZONE = "calendar_timezone";
+    field public static final int CAL_ACCESS_CONTRIBUTOR = 500; // 0x1f4
+    field public static final int CAL_ACCESS_EDITOR = 600; // 0x258
+    field public static final int CAL_ACCESS_FREEBUSY = 100; // 0x64
+    field public static final int CAL_ACCESS_NONE = 0; // 0x0
+    field public static final int CAL_ACCESS_OVERRIDE = 400; // 0x190
+    field public static final int CAL_ACCESS_OWNER = 700; // 0x2bc
+    field public static final int CAL_ACCESS_READ = 200; // 0xc8
+    field public static final int CAL_ACCESS_RESPOND = 300; // 0x12c
+    field public static final int CAL_ACCESS_ROOT = 800; // 0x320
+    field public static final java.lang.String CAN_MODIFY_TIME_ZONE = "canModifyTimeZone";
+    field public static final java.lang.String CAN_ORGANIZER_RESPOND = "canOrganizerRespond";
+    field public static final java.lang.String MAX_REMINDERS = "maxReminders";
+    field public static final java.lang.String OWNER_ACCOUNT = "ownerAccount";
+    field public static final java.lang.String SYNC_EVENTS = "sync_events";
+    field public static final java.lang.String VISIBLE = "visible";
+  }
+
+  public static final class CalendarContract.CalendarEntity implements android.provider.BaseColumns android.provider.CalendarContract.CalendarColumns android.provider.CalendarContract.SyncColumns {
+    method public static android.content.EntityIterator newEntityIterator(android.database.Cursor);
+    field public static final android.net.Uri CONTENT_URI;
+  }
+
+  protected static abstract interface CalendarContract.CalendarSyncColumns {
+    field public static final java.lang.String CAL_SYNC1 = "cal_sync1";
+    field public static final java.lang.String CAL_SYNC10 = "cal_sync10";
+    field public static final java.lang.String CAL_SYNC2 = "cal_sync2";
+    field public static final java.lang.String CAL_SYNC3 = "cal_sync3";
+    field public static final java.lang.String CAL_SYNC4 = "cal_sync4";
+    field public static final java.lang.String CAL_SYNC5 = "cal_sync5";
+    field public static final java.lang.String CAL_SYNC6 = "cal_sync6";
+    field public static final java.lang.String CAL_SYNC7 = "cal_sync7";
+    field public static final java.lang.String CAL_SYNC8 = "cal_sync8";
+    field public static final java.lang.String CAL_SYNC9 = "cal_sync9";
+  }
+
+  public static final class CalendarContract.Calendars implements android.provider.BaseColumns android.provider.CalendarContract.CalendarColumns android.provider.CalendarContract.SyncColumns {
+    field public static final java.lang.String CALENDAR_LOCATION = "calendar_location";
+    field public static final android.net.Uri CONTENT_URI;
+    field public static final java.lang.String DEFAULT_SORT_ORDER = "displayName";
+    field public static final java.lang.String NAME = "name";
+  }
+
+  public static final class CalendarContract.EventDays implements android.provider.CalendarContract.EventDaysColumns {
+    method public static final android.database.Cursor query(android.content.ContentResolver, int, int, java.lang.String[]);
+    field public static final android.net.Uri CONTENT_URI;
+  }
+
+  protected static abstract interface CalendarContract.EventDaysColumns {
+    field public static final java.lang.String ENDDAY = "endDay";
+    field public static final java.lang.String STARTDAY = "startDay";
+  }
+
+  public static final class CalendarContract.Events implements android.provider.BaseColumns android.provider.CalendarContract.CalendarColumns android.provider.CalendarContract.EventsColumns android.provider.CalendarContract.SyncColumns {
+    field public static final android.net.Uri CONTENT_EXCEPTION_URI;
+    field public static final android.net.Uri CONTENT_URI;
+  }
+
+  protected static abstract interface CalendarContract.EventsColumns {
+    field public static final int ACCESS_CONFIDENTIAL = 1; // 0x1
+    field public static final int ACCESS_DEFAULT = 0; // 0x0
+    field public static final java.lang.String ACCESS_LEVEL = "accessLevel";
+    field public static final int ACCESS_PRIVATE = 2; // 0x2
+    field public static final int ACCESS_PUBLIC = 3; // 0x3
+    field public static final java.lang.String ALL_DAY = "allDay";
+    field public static final java.lang.String AVAILABILITY = "availability";
+    field public static final int AVAILABILITY_BUSY = 0; // 0x0
+    field public static final int AVAILABILITY_FREE = 1; // 0x1
+    field public static final java.lang.String CALENDAR_ID = "calendar_id";
+    field public static final java.lang.String CAN_INVITE_OTHERS = "canInviteOthers";
+    field public static final java.lang.String DESCRIPTION = "description";
+    field public static final java.lang.String DTEND = "dtend";
+    field public static final java.lang.String DTSTART = "dtstart";
+    field public static final java.lang.String DURATION = "duration";
+    field public static final java.lang.String EVENT_COLOR = "eventColor";
+    field public static final java.lang.String EVENT_END_TIMEZONE = "eventEndTimezone";
+    field public static final java.lang.String EVENT_LOCATION = "eventLocation";
+    field public static final java.lang.String EVENT_TIMEZONE = "eventTimezone";
+    field public static final java.lang.String EXDATE = "exdate";
+    field public static final java.lang.String EXRULE = "exrule";
+    field public static final java.lang.String GUESTS_CAN_INVITE_OTHERS = "guestsCanInviteOthers";
+    field public static final java.lang.String GUESTS_CAN_MODIFY = "guestsCanModify";
+    field public static final java.lang.String GUESTS_CAN_SEE_GUESTS = "guestsCanSeeGuests";
+    field public static final java.lang.String HAS_ALARM = "hasAlarm";
+    field public static final java.lang.String HAS_ATTENDEE_DATA = "hasAttendeeData";
+    field public static final java.lang.String HAS_EXTENDED_PROPERTIES = "hasExtendedProperties";
+    field public static final java.lang.String LAST_DATE = "lastDate";
+    field public static final java.lang.String LAST_SYNCED = "lastSynced";
+    field public static final java.lang.String ORGANIZER = "organizer";
+    field public static final java.lang.String ORIGINAL_ALL_DAY = "originalAllDay";
+    field public static final java.lang.String ORIGINAL_ID = "original_id";
+    field public static final java.lang.String ORIGINAL_INSTANCE_TIME = "originalInstanceTime";
+    field public static final java.lang.String ORIGINAL_SYNC_ID = "original_sync_id";
+    field public static final java.lang.String RDATE = "rdate";
+    field public static final java.lang.String RRULE = "rrule";
+    field public static final java.lang.String SELF_ATTENDEE_STATUS = "selfAttendeeStatus";
+    field public static final java.lang.String STATUS = "eventStatus";
+    field public static final int STATUS_CANCELED = 2; // 0x2
+    field public static final int STATUS_CONFIRMED = 1; // 0x1
+    field public static final int STATUS_TENTATIVE = 0; // 0x0
+    field public static final java.lang.String SYNC_DATA1 = "sync_data1";
+    field public static final java.lang.String SYNC_DATA10 = "sync_data10";
+    field public static final java.lang.String SYNC_DATA2 = "sync_data2";
+    field public static final java.lang.String SYNC_DATA3 = "sync_data3";
+    field public static final java.lang.String SYNC_DATA4 = "sync_data4";
+    field public static final java.lang.String SYNC_DATA5 = "sync_data5";
+    field public static final java.lang.String SYNC_DATA6 = "sync_data6";
+    field public static final java.lang.String SYNC_DATA7 = "sync_data7";
+    field public static final java.lang.String SYNC_DATA8 = "sync_data8";
+    field public static final java.lang.String SYNC_DATA9 = "sync_data9";
+    field public static final java.lang.String TITLE = "title";
+  }
+
+  public static final class CalendarContract.EventsEntity implements android.provider.BaseColumns android.provider.CalendarContract.EventsColumns android.provider.CalendarContract.SyncColumns {
+    method public static android.content.EntityIterator newEntityIterator(android.database.Cursor, android.content.ContentResolver);
+    method public static android.content.EntityIterator newEntityIterator(android.database.Cursor, android.content.ContentProviderClient);
+    field public static final android.net.Uri CONTENT_URI;
+  }
+
+  public static final class CalendarContract.ExtendedProperties implements android.provider.BaseColumns android.provider.CalendarContract.EventsColumns android.provider.CalendarContract.ExtendedPropertiesColumns {
+    field public static final android.net.Uri CONTENT_URI;
+  }
+
+  protected static abstract interface CalendarContract.ExtendedPropertiesColumns {
+    field public static final java.lang.String EVENT_ID = "event_id";
+    field public static final java.lang.String NAME = "name";
+    field public static final java.lang.String VALUE = "value";
+  }
+
+  public static final class CalendarContract.Instances implements android.provider.BaseColumns android.provider.CalendarContract.CalendarColumns android.provider.CalendarContract.EventsColumns {
+    method public static final android.database.Cursor query(android.content.ContentResolver, java.lang.String[], long, long);
+    method public static final android.database.Cursor query(android.content.ContentResolver, java.lang.String[], long, long, java.lang.String);
+    field public static final java.lang.String BEGIN = "begin";
+    field public static final android.net.Uri CONTENT_BY_DAY_URI;
+    field public static final android.net.Uri CONTENT_SEARCH_BY_DAY_URI;
+    field public static final android.net.Uri CONTENT_SEARCH_URI;
+    field public static final android.net.Uri CONTENT_URI;
+    field public static final java.lang.String END = "end";
+    field public static final java.lang.String END_DAY = "endDay";
+    field public static final java.lang.String END_MINUTE = "endMinute";
+    field public static final java.lang.String EVENT_ID = "event_id";
+    field public static final java.lang.String START_DAY = "startDay";
+    field public static final java.lang.String START_MINUTE = "startMinute";
+  }
+
+  public static final class CalendarContract.Reminders implements android.provider.BaseColumns android.provider.CalendarContract.EventsColumns android.provider.CalendarContract.RemindersColumns {
+    method public static final android.database.Cursor query(android.content.ContentResolver, long, java.lang.String[]);
+    field public static final android.net.Uri CONTENT_URI;
+  }
+
+  protected static abstract interface CalendarContract.RemindersColumns {
+    field public static final java.lang.String EVENT_ID = "event_id";
+    field public static final java.lang.String METHOD = "method";
+    field public static final int METHOD_ALERT = 1; // 0x1
+    field public static final int METHOD_DEFAULT = 0; // 0x0
+    field public static final int METHOD_EMAIL = 2; // 0x2
+    field public static final int METHOD_SMS = 3; // 0x3
+    field public static final java.lang.String MINUTES = "minutes";
+    field public static final int MINUTES_DEFAULT = -1; // 0xffffffff
+  }
+
+  protected static abstract interface CalendarContract.SyncColumns implements android.provider.CalendarContract.CalendarSyncColumns {
+    field public static final java.lang.String ACCOUNT_NAME = "account_name";
+    field public static final java.lang.String ACCOUNT_TYPE = "account_type";
+    field public static final java.lang.String CAN_PARTIALLY_UPDATE = "canPartiallyUpdate";
+    field public static final java.lang.String DELETED = "deleted";
+    field public static final java.lang.String DIRTY = "dirty";
+    field public static final java.lang.String _SYNC_ID = "_sync_id";
+  }
+
+  public static final class CalendarContract.SyncState implements android.provider.SyncStateContract.Columns {
+    field public static final android.net.Uri CONTENT_URI;
+  }
+
   public class CallLog {
     ctor public CallLog();
     field public static final java.lang.String AUTHORITY = "call_log";
@@ -26151,6 +26418,7 @@
     method public boolean onTextContextMenuItem(int);
     method public void removeTextChangedListener(android.text.TextWatcher);
     method protected void resetLayoutDirectionResolution();
+    method public void setAllCaps(boolean);
     method public final void setAutoLinkMask(int);
     method public void setCompoundDrawablePadding(int);
     method public void setCompoundDrawables(android.graphics.drawable.Drawable, android.graphics.drawable.Drawable, android.graphics.drawable.Drawable, android.graphics.drawable.Drawable);
diff --git a/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java b/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java
index 38d0d2a..2666b41 100644
--- a/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java
+++ b/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java
@@ -23,6 +23,8 @@
 import android.os.RemoteException;
 import android.os.ServiceManager;
 
+import java.util.HashSet;
+
 public final class Bmgr {
     IBackupManager mBmgr;
     IRestoreSession mRestore;
@@ -45,7 +47,6 @@
     }
 
     public void run(String[] args) {
-        boolean validCommand = false;
         if (args.length < 1) {
             showUsage();
             return;
@@ -329,7 +330,13 @@
         } else {
             try {
                 long token = Long.parseLong(arg, 16);
-                doRestoreAll(token);
+                HashSet<String> filter = null;
+                while ((arg = nextArg()) != null) {
+                    if (filter == null) filter = new HashSet<String>();
+                    filter.add(arg);
+                }
+
+                doRestoreAll(token, filter);
             } catch (NumberFormatException e) {
                 showUsage();
                 return;
@@ -364,7 +371,7 @@
         }
     }
 
-    private void doRestoreAll(long token) {
+    private void doRestoreAll(long token, HashSet<String> filter) {
         RestoreObserver observer = new RestoreObserver();
 
         try {
@@ -383,7 +390,13 @@
                     for (RestoreSet s : sets) {
                         if (s.token == token) {
                             System.out.println("Scheduling restore: " + s.name);
-                            didRestore = (mRestore.restoreAll(token, observer) == 0);
+                            if (filter == null) {
+                                didRestore = (mRestore.restoreAll(token, observer) == 0);
+                            } else {
+                                String[] names = new String[filter.size()];
+                                filter.toArray(names);
+                                didRestore = (mRestore.restoreSome(token, observer, names) == 0);
+                            }
                             break;
                         }
                     }
@@ -430,6 +443,7 @@
         System.err.println("       bmgr list sets");
         System.err.println("       bmgr transport WHICH");
         System.err.println("       bmgr restore TOKEN");
+        System.err.println("       bmgr restore TOKEN PACKAGE...");
         System.err.println("       bmgr restore PACKAGE");
         System.err.println("       bmgr run");
         System.err.println("       bmgr wipe PACKAGE");
@@ -457,12 +471,18 @@
         System.err.println("The 'transport' command designates the named transport as the currently");
         System.err.println("active one.  This setting is persistent across reboots.");
         System.err.println("");
-        System.err.println("The 'restore' command when given a restore token initiates a full-system");
+        System.err.println("The 'restore' command when given just a restore token initiates a full-system");
         System.err.println("restore operation from the currently active transport.  It will deliver");
         System.err.println("the restore set designated by the TOKEN argument to each application");
         System.err.println("that had contributed data to that restore set.");
         System.err.println("");
-        System.err.println("The 'restore' command when given a package name intiates a restore of");
+        System.err.println("The 'restore' command when given a token and one or more package names");
+        System.err.println("initiates a restore operation of just those given packages from the restore");
+        System.err.println("set designated by the TOKEN argument.  It is effectively the same as the");
+        System.err.println("'restore' operation supplying only a token, but applies a filter to the");
+        System.err.println("set of applications to be restored.");
+        System.err.println("");
+        System.err.println("The 'restore' command when given just a package name intiates a restore of");
         System.err.println("just that one package according to the restore set selection algorithm");
         System.err.println("used by the RestoreSession.restorePackage() method.");
         System.err.println("");
diff --git a/core/java/android/app/backup/IRestoreSession.aidl b/core/java/android/app/backup/IRestoreSession.aidl
index 1dddbb0..14731ee 100644
--- a/core/java/android/app/backup/IRestoreSession.aidl
+++ b/core/java/android/app/backup/IRestoreSession.aidl
@@ -52,6 +52,25 @@
     int restoreAll(long token, IRestoreObserver observer);
 
     /**
+     * Restore select packages from the given set onto the device, replacing the
+     * current data of any app contained in the set with the data previously
+     * backed up.
+     *
+     * <p>Callers must hold the android.permission.BACKUP permission to use this method.
+     *
+     * @return Zero on success, nonzero on error. The observer will only receive
+     *   progress callbacks if this method returned zero.
+     * @param token The token from {@link getAvailableRestoreSets()} corresponding to
+     *   the restore set that should be used.
+     * @param observer If non-null, this binder points to an object that will receive
+     *   progress callbacks during the restore operation.
+     * @param packages The set of packages for which to attempt a restore.  Regardless of
+     *   the contents of the actual back-end dataset named by {@code token}, only
+     *   applications mentioned in this list will have their data restored.
+     */
+    int restoreSome(long token, IRestoreObserver observer, in String[] packages);
+
+    /**
      * Restore a single application from backup.  The data will be restored from the
      * current backup dataset if the given package has stored data there, or from
      * the dataset used during the last full device setup operation if the current
diff --git a/core/java/android/app/backup/RestoreSession.java b/core/java/android/app/backup/RestoreSession.java
index 24ddb99..7181c61 100644
--- a/core/java/android/app/backup/RestoreSession.java
+++ b/core/java/android/app/backup/RestoreSession.java
@@ -87,6 +87,40 @@
     }
 
     /**
+     * Restore select packages from the given set onto the device, replacing the
+     * current data of any app contained in the set with the data previously
+     * backed up.
+     *
+     * <p>Callers must hold the android.permission.BACKUP permission to use this method.
+     *
+     * @return Zero on success, nonzero on error. The observer will only receive
+     *   progress callbacks if this method returned zero.
+     * @param token The token from {@link getAvailableRestoreSets()} corresponding to
+     *   the restore set that should be used.
+     * @param observer If non-null, this binder points to an object that will receive
+     *   progress callbacks during the restore operation.
+     * @param packages The set of packages for which to attempt a restore.  Regardless of
+     *   the contents of the actual back-end dataset named by {@code token}, only
+     *   applications mentioned in this list will have their data restored.
+     *
+     * @hide
+     */
+    public int restoreSome(long token, RestoreObserver observer, String[] packages) {
+        int err = -1;
+        if (mObserver != null) {
+            Log.d(TAG, "restoreAll() called during active restore");
+            return -1;
+        }
+        mObserver = new RestoreObserverWrapper(mContext, observer);
+        try {
+            err = mBinder.restoreSome(token, mObserver, packages);
+        } catch (RemoteException e) {
+            Log.d(TAG, "Can't contact server to restore packages");
+        }
+        return err;
+    }
+
+    /**
      * Restore a single application from backup.  The data will be restored from the
      * current backup dataset if the given package has stored data there, or from
      * the dataset used during the last full device setup operation if the current
diff --git a/core/java/android/bluetooth/BluetoothServerSocket.java b/core/java/android/bluetooth/BluetoothServerSocket.java
index 83e59e2..acce182 100644
--- a/core/java/android/bluetooth/BluetoothServerSocket.java
+++ b/core/java/android/bluetooth/BluetoothServerSocket.java
@@ -62,6 +62,7 @@
     /*package*/ final BluetoothSocket mSocket;
     private Handler mHandler;
     private int mMessage;
+    private final int mChannel;
 
     /**
      * Construct a socket for incoming connections.
@@ -74,6 +75,7 @@
      */
     /*package*/ BluetoothServerSocket(int type, boolean auth, boolean encrypt, int port)
             throws IOException {
+        mChannel = port;
         mSocket = new BluetoothSocket(type, -1, auth, encrypt, null, port, null);
     }
 
@@ -125,4 +127,12 @@
         mHandler = handler;
         mMessage = message;
     }
+
+    /**
+     * Returns the channel on which this socket is bound.
+     * @hide
+     */
+    public int getChannel() {
+        return mChannel;
+    }
 }
diff --git a/core/java/android/net/NetworkUtils.java b/core/java/android/net/NetworkUtils.java
index 8a678d6..76534ef 100644
--- a/core/java/android/net/NetworkUtils.java
+++ b/core/java/android/net/NetworkUtils.java
@@ -38,8 +38,22 @@
     /** Bring the named network interface down. */
     public native static int disableInterface(String interfaceName);
 
-    /** Reset any sockets that are connected via the named interface. */
-    public native static int resetConnections(String interfaceName);
+    /** Setting bit 0 indicates reseting of IPv4 addresses required */
+    public static final int RESET_IPV4_ADDRESSES = 0x01;
+
+    /** Setting bit 1 indicates reseting of IPv4 addresses required */
+    public static final int RESET_IPV6_ADDRESSES = 0x02;
+
+    /** Reset all addresses */
+    public static final int RESET_ALL_ADDRESSES = RESET_IPV4_ADDRESSES | RESET_IPV6_ADDRESSES;
+
+    /**
+     * Reset IPv6 or IPv4 sockets that are connected via the named interface.
+     *
+     * @param interfaceName is the interface to reset
+     * @param mask {@see #RESET_IPV4_ADDRESSES} and {@see #RESET_IPV6_ADDRESSES}
+     */
+    public native static int resetConnections(String interfaceName, int mask);
 
     /**
      * Start the DHCP client daemon, in order to have it request addresses
diff --git a/core/java/android/provider/CalendarContract.java b/core/java/android/provider/CalendarContract.java
index b492615..5b29103 100644
--- a/core/java/android/provider/CalendarContract.java
+++ b/core/java/android/provider/CalendarContract.java
@@ -17,6 +17,8 @@
 package android.provider;
 
 
+import android.annotation.SdkConstant;
+import android.annotation.SdkConstant.SdkConstantType;
 import android.app.AlarmManager;
 import android.app.PendingIntent;
 import android.content.ContentProviderClient;
@@ -83,7 +85,6 @@
  * adapters</li>
  * </ul>
  *
- * @hide
  */
 public final class CalendarContract {
     private static final String TAG = "Calendar";
@@ -92,8 +93,8 @@
      * Broadcast Action: This is the intent that gets fired when an alarm
      * notification needs to be posted for a reminder.
      *
-     * @SdkConstant
      */
+    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
     public static final String ACTION_EVENT_REMINDER = "android.intent.action.EVENT_REMINDER";
 
     /**
@@ -146,6 +147,11 @@
     public static final String ACCOUNT_TYPE_LOCAL = "LOCAL";
 
     /**
+     * This utility class cannot be instantiated
+     */
+    private CalendarContract() {}
+
+    /**
      * Generic columns for use by sync adapters. The specific functions of these
      * columns are private to the sync adapter. Other clients of the API should
      * not attempt to either read or write this column. These columns are
@@ -384,7 +390,7 @@
      * Class that represents a Calendar Entity. There is one entry per calendar.
      * This is a helper class to make batch operations easier.
      */
-    public static class CalendarEntity implements BaseColumns, SyncColumns, CalendarColumns {
+    public static final class CalendarEntity implements BaseColumns, SyncColumns, CalendarColumns {
 
         /**
          * The default Uri used when creating a new calendar EntityIterator.
@@ -394,6 +400,11 @@
                 "/calendar_entities");
 
         /**
+         * This utility class cannot be instantiated
+         */
+        private CalendarEntity() {}
+
+        /**
          * Creates an entity iterator for the given cursor. It assumes the
          * cursor contains a calendars query.
          *
@@ -566,7 +577,13 @@
      * <li>{@link #CAL_SYNC10}</li>
      * </ul>
      */
-    public static class Calendars implements BaseColumns, SyncColumns, CalendarColumns {
+    public static final class Calendars implements BaseColumns, SyncColumns, CalendarColumns {
+
+        /**
+         * This utility class cannot be instantiated
+         */
+        private Calendars() {}
+
         /**
          * The content:// style URL for accessing Calendars
          */
@@ -687,7 +704,7 @@
     /**
      * Fields and helpers for interacting with Attendees. Each row of this table
      * represents a single attendee or guest of an event. Calling
-     * {@link #query(ContentResolver, long)} will return a list of attendees for
+     * {@link #query(ContentResolver, long, String[])} will return a list of attendees for
      * the event with the given eventId. Both apps and sync adapters may write
      * to this table. There are six writable fields and all of them except
      * {@link #ATTENDEE_NAME} must be included when inserting a new attendee.
@@ -708,24 +725,25 @@
          */
         @SuppressWarnings("hiding")
         public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/attendees");
-        /**
-         * the projection used by the attendees query
-         */
-        public static final String[] PROJECTION = new String[] {
-                _ID, ATTENDEE_NAME, ATTENDEE_EMAIL, ATTENDEE_RELATIONSHIP, ATTENDEE_STATUS,};
         private static final String ATTENDEES_WHERE = Attendees.EVENT_ID + "=?";
 
         /**
+         * This utility class cannot be instantiated
+         */
+        private Attendees() {}
+
+        /**
          * Queries all attendees associated with the given event. This is a
          * blocking call and should not be done on the UI thread.
          *
          * @param cr The content resolver to use for the query
          * @param eventId The id of the event to retrieve attendees for
+         * @param projection the columns to return in the cursor
          * @return A Cursor containing all attendees for the event
          */
-        public static final Cursor query(ContentResolver cr, long eventId) {
+        public static final Cursor query(ContentResolver cr, long eventId, String[] projection) {
             String[] attArgs = {Long.toString(eventId)};
-            return cr.query(CONTENT_URI, PROJECTION, ATTENDEES_WHERE, attArgs /* selection args */,
+            return cr.query(CONTENT_URI, projection, ATTENDEES_WHERE, attArgs /* selection args */,
                     null /* sort order */);
         }
     }
@@ -1068,6 +1086,11 @@
                 "/event_entities");
 
         /**
+         * This utility class cannot be instantiated
+         */
+        private EventsEntity() {}
+
+        /**
          * Creates a new iterator for events
          *
          * @param cursor An event query
@@ -1411,6 +1434,11 @@
                 Uri.parse("content://" + AUTHORITY + "/exception");
 
         /**
+         * This utility class cannot be instantiated
+         */
+        private Events() {}
+
+        /**
          * The default sort order for this table
          */
         private static final String DEFAULT_SORT_ORDER = "";
@@ -1484,6 +1512,11 @@
         };
 
         /**
+         * This utility class cannot be instantiated
+         */
+        private Instances() {}
+
+        /**
          * Performs a query to return all visible instances in the given range.
          * This is a blocking function and should not be done on the UI thread.
          * This will cause an expansion of recurring events to fill this time
@@ -1636,7 +1669,7 @@
      * time zone for the instances. These settings are stored using a key/value
      * scheme. A {@link #KEY} must be specified when updating these values.
      */
-    public static class CalendarCache implements CalendarCacheColumns {
+    public static final class CalendarCache implements CalendarCacheColumns {
         /**
          * The URI to use for retrieving the properties from the Calendar db.
          */
@@ -1644,6 +1677,11 @@
                 Uri.parse("content://" + AUTHORITY + "/properties");
 
         /**
+         * This utility class cannot be instantiated
+         */
+        private CalendarCache() {}
+
+        /**
          * They key for updating the use of auto/home time zones in Calendar.
          * Valid values are {@link #TIMEZONE_TYPE_AUTO} or
          * {@link #TIMEZONE_TYPE_HOME}.
@@ -1724,6 +1762,11 @@
      * @hide
      */
     public static final class CalendarMetaData implements CalendarMetaDataColumns, BaseColumns {
+
+        /**
+         * This utility class cannot be instantiated
+         */
+        private CalendarMetaData() {}
     }
 
     protected interface EventDaysColumns {
@@ -1746,14 +1789,12 @@
     public static final class EventDays implements EventDaysColumns {
         public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY
                 + "/instances/groupbyday");
+        private static final String SELECTION = "selected=1";
 
         /**
-         * The projection used by the EventDays query.
+         * This utility class cannot be instantiated
          */
-        public static final String[] PROJECTION = {
-                STARTDAY, ENDDAY
-        };
-        private static final String SELECTION = "selected=1";
+        private EventDays() {}
 
         /**
          * Retrieves the days with events for the Julian days starting at
@@ -1765,10 +1806,12 @@
          * @param cr the ContentResolver
          * @param startDay the first Julian day in the range
          * @param numDays the number of days to load (must be at least 1)
+         * @param projection the columns to return in the cursor
          * @return a database cursor containing a list of start and end days for
          *         events
          */
-        public static final Cursor query(ContentResolver cr, int startDay, int numDays) {
+        public static final Cursor query(ContentResolver cr, int startDay, int numDays,
+                String[] projection) {
             if (numDays < 1) {
                 return null;
             }
@@ -1776,7 +1819,7 @@
             Uri.Builder builder = CONTENT_URI.buildUpon();
             ContentUris.appendId(builder, startDay);
             ContentUris.appendId(builder, endDay);
-            return cr.query(builder.build(), PROJECTION, SELECTION,
+            return cr.query(builder.build(), projection, SELECTION,
                     null /* selection args */, STARTDAY);
         }
     }
@@ -1821,7 +1864,7 @@
     /**
      * Fields and helpers for accessing reminders for an event. Each row of this
      * table represents a single reminder for an event. Calling
-     * {@link #query(ContentResolver, long)} will return a list of reminders for
+     * {@link #query(ContentResolver, long, String[])} will return a list of reminders for
      * the event with the given eventId. Both apps and sync adapters may write
      * to this table. There are three writable fields and all of them must be
      * included when inserting a new reminder. They are:
@@ -1833,25 +1876,26 @@
      */
     public static final class Reminders implements BaseColumns, RemindersColumns, EventsColumns {
         private static final String REMINDERS_WHERE = CalendarContract.Reminders.EVENT_ID + "=?";
-        /**
-         * The projection used by the reminders query.
-         */
-        public static final String[] PROJECTION = new String[] {
-                _ID, MINUTES, METHOD,};
         @SuppressWarnings("hiding")
         public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/reminders");
 
         /**
+         * This utility class cannot be instantiated
+         */
+        private Reminders() {}
+
+        /**
          * Queries all reminders associated with the given event. This is a
          * blocking call and should not be done on the UI thread.
          *
          * @param cr The content resolver to use for the query
          * @param eventId The id of the event to retrieve reminders for
+         * @param projection the columns to return in the cursor
          * @return A Cursor containing all reminders for the event
          */
-        public static final Cursor query(ContentResolver cr, long eventId) {
+        public static final Cursor query(ContentResolver cr, long eventId, String[] projection) {
             String[] remArgs = {Long.toString(eventId)};
-            return cr.query(CONTENT_URI, PROJECTION, REMINDERS_WHERE, remArgs /* selection args */,
+            return cr.query(CONTENT_URI, projection, REMINDERS_WHERE, remArgs /*selection args*/,
                     null /* sort order */);
         }
     }
@@ -1964,6 +2008,11 @@
         public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY +
                 "/calendar_alerts");
 
+        /**
+         * This utility class cannot be instantiated
+         */
+        private CalendarAlerts() {}
+
         private static final String WHERE_ALARM_EXISTS = EVENT_ID + "=?"
                 + " AND " + BEGIN + "=?"
                 + " AND " + ALARM_TIME + "=?";
@@ -2134,7 +2183,7 @@
          * given event id, begin time and alarm time. If one is found then this
          * alarm already exists and this method returns true. TODO Move to
          * provider
-         * 
+         *
          * @param cr the ContentResolver
          * @param eventId the event id to match
          * @param begin the start time of the event in UTC millis
@@ -2203,6 +2252,11 @@
         public static final Uri CONTENT_URI =
                 Uri.parse("content://" + AUTHORITY + "/extendedproperties");
 
+        /**
+         * This utility class cannot be instantiated
+         */
+        private ExtendedProperties() {}
+
         // TODO: fill out this class when we actually start utilizing extendedproperties
         // in the calendar application.
    }
@@ -2271,5 +2325,10 @@
      * @hide
      */
     public static final class EventsRawTimes implements BaseColumns, EventsRawTimesColumns {
+
+        /**
+         * This utility class cannot be instantiated
+         */
+        private EventsRawTimes() {}
     }
 }
diff --git a/core/java/android/speech/tts/AudioPlaybackHandler.java b/core/java/android/speech/tts/AudioPlaybackHandler.java
index c7603ee..8ef4295 100644
--- a/core/java/android/speech/tts/AudioPlaybackHandler.java
+++ b/core/java/android/speech/tts/AudioPlaybackHandler.java
@@ -384,11 +384,16 @@
             }
             count += written;
         }
+
+        param.mLogger.onPlaybackStart();
     }
 
     private void handleSynthesisDone(MessageParams msg) {
         final SynthesisMessageParams params = (SynthesisMessageParams) msg;
         handleSynthesisDone(params);
+        // This call is delayed more than it should be, but we are
+        // certain at this point that we have all the data we want.
+        params.mLogger.onWriteData();
     }
 
     // Flush all remaining data to the audio track, stop it and release
@@ -416,6 +421,8 @@
         final SynthesisMessageParams params = (SynthesisMessageParams) msg;
         if (DBG) Log.d(TAG, "completeAudioAvailable(" + params + ")");
 
+        params.mLogger.onPlaybackStart();
+
         // Channel config and bytes per frame are checked before
         // this message is sent.
         int channelConfig = AudioPlaybackHandler.getChannelConfig(params.mChannelCount);
diff --git a/core/java/android/speech/tts/EventLogTags.logtags b/core/java/android/speech/tts/EventLogTags.logtags
new file mode 100644
index 0000000..1a9f5fe
--- /dev/null
+++ b/core/java/android/speech/tts/EventLogTags.logtags
@@ -0,0 +1,6 @@
+# See system/core/logcat/event.logtags for a description of the format of this file.
+
+option java_package android.speech.tts;
+
+76001 tts_speak_success (engine|3),(caller|3),(length|1),(locale|3),(rate|1),(pitch|1),(engine_latency|2|3),(engine_total|2|3),(audio_latency|2|3)
+76002 tts_speak_failure (engine|3),(caller|3),(length|1),(locale|3),(rate|1),(pitch|1)
diff --git a/core/java/android/speech/tts/EventLogger.java b/core/java/android/speech/tts/EventLogger.java
new file mode 100644
index 0000000..63b954b
--- /dev/null
+++ b/core/java/android/speech/tts/EventLogger.java
@@ -0,0 +1,175 @@
+/*
+ * 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.speech.tts;
+
+import android.os.SystemClock;
+import android.text.TextUtils;
+
+/**
+ * Writes data about a given speech synthesis request to the event logs.
+ * The data that is logged includes the calling app, length of the utterance,
+ * speech rate / pitch and the latency and overall time taken.
+ *
+ * Note that {@link EventLogger#onStopped()} and {@link EventLogger#onError()}
+ * might be called from any thread, but on {@link EventLogger#onPlaybackStart()} and
+ * {@link EventLogger#onComplete()} must be called from a single thread
+ * (usually the audio playback thread}
+ */
+class EventLogger {
+    private final SynthesisRequest mRequest;
+    private final String mCallingApp;
+    private final String mServiceApp;
+    private final long mReceivedTime;
+    private long mPlaybackStartTime = -1;
+    private volatile long mRequestProcessingStartTime = -1;
+    private volatile long mEngineStartTime = -1;
+    private volatile long mEngineCompleteTime = -1;
+
+    private volatile boolean mError = false;
+    private volatile boolean mStopped = false;
+    private boolean mLogWritten = false;
+
+    EventLogger(SynthesisRequest request, String callingApp,
+            String serviceApp) {
+        mRequest = request;
+        mCallingApp = callingApp;
+        mServiceApp = serviceApp;
+        mReceivedTime = SystemClock.elapsedRealtime();
+    }
+
+    /**
+     * Notifies the logger that this request has been selected from
+     * the processing queue for processing. Engine latency / total time
+     * is measured from this baseline.
+     */
+    public void onRequestProcessingStart() {
+        mRequestProcessingStartTime = SystemClock.elapsedRealtime();
+    }
+
+    /**
+     * Notifies the logger that a chunk of data has been received from
+     * the engine. Might be called multiple times.
+     */
+    public void onEngineDataReceived() {
+        if (mEngineStartTime == -1) {
+            mEngineStartTime = SystemClock.elapsedRealtime();
+        }
+    }
+
+    /**
+     * Notifies the logger that the engine has finished processing data.
+     * Will be called exactly once.
+     */
+    public void onEngineComplete() {
+        mEngineCompleteTime = SystemClock.elapsedRealtime();
+    }
+
+    /**
+     * Notifies the logger that audio playback has started for some section
+     * of the synthesis. This is normally some amount of time after the engine
+     * has synthesized data and varides depending on utterances and
+     * other audio currently in the queue.
+     */
+    public void onPlaybackStart() {
+        // For now, keep track of only the first chunk of audio
+        // that was played.
+        if (mPlaybackStartTime == -1) {
+            mPlaybackStartTime = SystemClock.elapsedRealtime();
+        }
+    }
+
+    /**
+     * Notifies the logger that the current synthesis was stopped.
+     * Latency numbers are not reported for stopped syntheses.
+     */
+    public void onStopped() {
+        mStopped = false;
+    }
+
+    /**
+     * Notifies the logger that the current synthesis resulted in
+     * an error. This is logged using {@link EventLogTags#writeTtsSpeakFailure}.
+     */
+    public void onError() {
+        mError = true;
+    }
+
+    /**
+     * Notifies the logger that the current synthesis has completed.
+     * All available data is not logged.
+     */
+    public void onWriteData() {
+        if (mLogWritten) {
+            return;
+        } else {
+            mLogWritten = true;
+        }
+
+        long completionTime = SystemClock.elapsedRealtime();
+        // onPlaybackStart() should normally always be called if an
+        // error does not occur.
+        if (mError || mPlaybackStartTime == -1 || mEngineCompleteTime == -1) {
+            EventLogTags.writeTtsSpeakFailure(mServiceApp, mCallingApp,
+                    getUtteranceLength(), getLocaleString(),
+                    mRequest.getSpeechRate(), mRequest.getPitch());
+            return;
+        }
+
+        // We don't report stopped syntheses because their overall
+        // total time spent will be innacurate (will not correlate with
+        // the length of the utterance).
+        if (mStopped) {
+            return;
+        }
+
+        final long audioLatency = mPlaybackStartTime - mReceivedTime;
+        final long engineLatency = mEngineStartTime - mRequestProcessingStartTime;
+        final long engineTotal = mEngineCompleteTime - mRequestProcessingStartTime;
+        EventLogTags.writeTtsSpeakSuccess(mServiceApp, mCallingApp,
+                getUtteranceLength(), getLocaleString(),
+                mRequest.getSpeechRate(), mRequest.getPitch(),
+                engineLatency, engineTotal, audioLatency);
+    }
+
+    /**
+     * @return the length of the utterance for the given synthesis, 0
+     *          if the utterance was {@code null}.
+     */
+    private int getUtteranceLength() {
+        final String utterance = mRequest.getText();
+        return utterance == null ? 0 : utterance.length();
+    }
+
+    /**
+     * Returns a formatted locale string from the synthesis params of the
+     * form lang-country-variant.
+     */
+    private String getLocaleString() {
+        StringBuilder sb = new StringBuilder(mRequest.getLanguage());
+        if (!TextUtils.isEmpty(mRequest.getCountry())) {
+            sb.append('-');
+            sb.append(mRequest.getCountry());
+
+            if (!TextUtils.isEmpty(mRequest.getVariant())) {
+                sb.append('-');
+                sb.append(mRequest.getVariant());
+            }
+        }
+
+        return sb.toString();
+    }
+
+}
diff --git a/core/java/android/speech/tts/PlaybackSynthesisCallback.java b/core/java/android/speech/tts/PlaybackSynthesisCallback.java
index bdaa1b8..38030a6 100644
--- a/core/java/android/speech/tts/PlaybackSynthesisCallback.java
+++ b/core/java/android/speech/tts/PlaybackSynthesisCallback.java
@@ -65,29 +65,42 @@
 
     private final UtteranceCompletedDispatcher mDispatcher;
     private final String mCallingApp;
+    private final EventLogger mLogger;
 
     PlaybackSynthesisCallback(int streamType, float volume, float pan,
             AudioPlaybackHandler audioTrackHandler, UtteranceCompletedDispatcher dispatcher,
-            String callingApp) {
+            String callingApp, EventLogger logger) {
         mStreamType = streamType;
         mVolume = volume;
         mPan = pan;
         mAudioTrackHandler = audioTrackHandler;
         mDispatcher = dispatcher;
         mCallingApp = callingApp;
+        mLogger = logger;
     }
 
     @Override
     void stop() {
         if (DBG) Log.d(TAG, "stop()");
 
+        // Note that mLogger.mError might be true too at this point.
+        mLogger.onStopped();
+
         synchronized (mStateLock) {
-            if (mToken == null || mStopped) {
-                Log.w(TAG, "stop() called twice, before start(), or after done()");
+            if (mStopped) {
+                Log.w(TAG, "stop() called twice");
                 return;
             }
-            mAudioTrackHandler.stop(mToken);
-            mToken = null;
+            // mToken will be null if the engine encounters
+            // an error before it called start().
+            if (mToken != null) {
+                mAudioTrackHandler.stop(mToken);
+                mToken = null;
+            } else {
+                // In all other cases, mAudioTrackHandler.stop() will
+                // result in onComplete being called.
+                mLogger.onWriteData();
+            }
             mStopped = true;
         }
     }
@@ -124,7 +137,7 @@
             }
             SynthesisMessageParams params = new SynthesisMessageParams(
                     mStreamType, sampleRateInHz, audioFormat, channelCount, mVolume, mPan,
-                    mDispatcher, mCallingApp);
+                    mDispatcher, mCallingApp, mLogger);
             mAudioTrackHandler.enqueueSynthesisStart(params);
 
             mToken = params;
@@ -157,6 +170,8 @@
             mAudioTrackHandler.enqueueSynthesisDataAvailable(mToken);
         }
 
+        mLogger.onEngineDataReceived();
+
         return TextToSpeech.SUCCESS;
     }
 
@@ -177,6 +192,7 @@
             }
 
             mAudioTrackHandler.enqueueSynthesisDone(mToken);
+            mLogger.onEngineComplete();
         }
         return TextToSpeech.SUCCESS;
     }
@@ -184,6 +200,9 @@
     @Override
     public void error() {
         if (DBG) Log.d(TAG, "error() [will call stop]");
+        // Currently, this call will not be logged if error( ) is called
+        // before start.
+        mLogger.onError();
         stop();
     }
 
@@ -208,7 +227,7 @@
             }
             SynthesisMessageParams params = new SynthesisMessageParams(
                     mStreamType, sampleRateInHz, audioFormat, channelCount, mVolume, mPan,
-                    mDispatcher, mCallingApp);
+                    mDispatcher, mCallingApp, mLogger);
             params.addBuffer(buffer, offset, length);
 
             mAudioTrackHandler.enqueueSynthesisCompleteDataAvailable(params);
diff --git a/core/java/android/speech/tts/SynthesisMessageParams.java b/core/java/android/speech/tts/SynthesisMessageParams.java
index 51f3d2e..caf02ef 100644
--- a/core/java/android/speech/tts/SynthesisMessageParams.java
+++ b/core/java/android/speech/tts/SynthesisMessageParams.java
@@ -30,6 +30,7 @@
     final int mChannelCount;
     final float mVolume;
     final float mPan;
+    final EventLogger mLogger;
 
     public volatile AudioTrack mAudioTrack;
 
@@ -38,7 +39,7 @@
     SynthesisMessageParams(int streamType, int sampleRate,
             int audioFormat, int channelCount,
             float volume, float pan, UtteranceCompletedDispatcher dispatcher,
-            String callingApp) {
+            String callingApp, EventLogger logger) {
         super(dispatcher, callingApp);
 
         mStreamType = streamType;
@@ -47,6 +48,7 @@
         mChannelCount = channelCount;
         mVolume = volume;
         mPan = pan;
+        mLogger = logger;
 
         // initially null.
         mAudioTrack = null;
diff --git a/core/java/android/speech/tts/TextToSpeechService.java b/core/java/android/speech/tts/TextToSpeechService.java
index 7ea9373..010c155 100644
--- a/core/java/android/speech/tts/TextToSpeechService.java
+++ b/core/java/android/speech/tts/TextToSpeechService.java
@@ -82,8 +82,7 @@
     private AudioPlaybackHandler mAudioPlaybackHandler;
 
     private CallbackMap mCallbacks;
-
-    private int mDefaultAvailability = TextToSpeech.LANG_NOT_SUPPORTED;
+    private String mPackageName;
 
     @Override
     public void onCreate() {
@@ -99,9 +98,10 @@
 
         mCallbacks = new CallbackMap();
 
+        mPackageName = getApplicationInfo().packageName;
+
         // Load default language
-        mDefaultAvailability = onLoadLanguage(getDefaultLanguage(),
-                getDefaultCountry(), getDefaultVariant());
+        onLoadLanguage(getDefaultLanguage(), getDefaultCountry(), getDefaultVariant());
     }
 
     @Override
@@ -457,12 +457,14 @@
         // Non null after synthesis has started, and all accesses
         // guarded by 'this'.
         private AbstractSynthesisCallback mSynthesisCallback;
+        private final EventLogger mEventLogger;
 
         public SynthesisSpeechItem(String callingApp, Bundle params, String text) {
             super(callingApp, params);
             mText = text;
             mSynthesisRequest = new SynthesisRequest(mText, mParams);
             setRequestParams(mSynthesisRequest);
+            mEventLogger = new EventLogger(mSynthesisRequest, getCallingApp(), mPackageName);
         }
 
         public String getText() {
@@ -485,6 +487,7 @@
         @Override
         protected int playImpl() {
             AbstractSynthesisCallback synthesisCallback;
+            mEventLogger.onRequestProcessingStart();
             synchronized (this) {
                 mSynthesisCallback = createSynthesisCallback();
                 synthesisCallback = mSynthesisCallback;
@@ -495,7 +498,7 @@
 
         protected AbstractSynthesisCallback createSynthesisCallback() {
             return new PlaybackSynthesisCallback(getStreamType(), getVolume(), getPan(),
-                    mAudioPlaybackHandler, this, getCallingApp());
+                    mAudioPlaybackHandler, this, getCallingApp(), mEventLogger);
         }
 
         private void setRequestParams(SynthesisRequest request) {
diff --git a/core/java/android/text/method/AllCapsTransformationMethod.java b/core/java/android/text/method/AllCapsTransformationMethod.java
new file mode 100644
index 0000000..f9920dd
--- /dev/null
+++ b/core/java/android/text/method/AllCapsTransformationMethod.java
@@ -0,0 +1,59 @@
+/*
+ * 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.text.method;
+
+import android.content.Context;
+import android.graphics.Rect;
+import android.util.Log;
+import android.view.View;
+
+import java.util.Locale;
+
+/**
+ * Transforms source text into an ALL CAPS string, locale-aware.
+ *
+ * @hide
+ */
+public class AllCapsTransformationMethod implements TransformationMethod2 {
+    private static final String TAG = "AllCapsTransformationMethod";
+
+    private boolean mEnabled;
+    private Locale mLocale;
+
+    public AllCapsTransformationMethod(Context context) {
+        mLocale = context.getResources().getConfiguration().locale;
+    }
+
+    @Override
+    public CharSequence getTransformation(CharSequence source, View view) {
+        if (mEnabled) {
+            return source != null ? source.toString().toUpperCase(mLocale) : null;
+        }
+        Log.w(TAG, "Caller did not enable length changes; not transforming text");
+        return source;
+    }
+
+    @Override
+    public void onFocusChanged(View view, CharSequence sourceText, boolean focused, int direction,
+            Rect previouslyFocusedRect) {
+    }
+
+    @Override
+    public void setLengthChangesAllowed(boolean allowLengthChanges) {
+        mEnabled = allowLengthChanges;
+    }
+
+}
diff --git a/core/java/android/text/method/TransformationMethod2.java b/core/java/android/text/method/TransformationMethod2.java
new file mode 100644
index 0000000..ef00ecd
--- /dev/null
+++ b/core/java/android/text/method/TransformationMethod2.java
@@ -0,0 +1,33 @@
+/*
+ * 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.text.method;
+
+/**
+ * TransformationMethod2 extends the TransformationMethod interface
+ * and adds the ability to relax restrictions of TransformationMethod.
+ *
+ * @hide
+ */
+public interface TransformationMethod2 extends TransformationMethod {
+    /**
+     * Relax the contract of TransformationMethod to allow length changes,
+     * or revert to the length-restricted behavior.
+     *
+     * @param allowLengthChanges true to allow the transformation to change the length
+     *                           of the input string.
+     */
+    public void setLengthChangesAllowed(boolean allowLengthChanges);
+}
diff --git a/core/java/android/text/style/SuggestionSpan.java b/core/java/android/text/style/SuggestionSpan.java
index 240ad9b..555aac5 100644
--- a/core/java/android/text/style/SuggestionSpan.java
+++ b/core/java/android/text/style/SuggestionSpan.java
@@ -22,12 +22,22 @@
 import android.os.SystemClock;
 import android.text.ParcelableSpan;
 import android.text.TextUtils;
+import android.widget.TextView;
 
 import java.util.Arrays;
 import java.util.Locale;
 
 /**
- * Holds suggestion candidates of words under this span.
+ * Holds suggestion candidates for the text enclosed in this span.
+ *
+ * When such a span is edited in an EditText, double tapping on the text enclosed in this span will
+ * display a popup dialog listing suggestion replacement for that text. The user can then replace
+ * the original text by one of the suggestions.
+ *
+ * These spans should typically be created by the input method to privide correction and alternates
+ * for the text.
+ *
+ * @see TextView#setSuggestionsEnabled(boolean)
  */
 public class SuggestionSpan implements ParcelableSpan {
     /**
@@ -115,14 +125,14 @@
     }
 
     /**
-     * @return suggestions
+     * @return an array of suggestion texts for this span
      */
     public String[] getSuggestions() {
         return mSuggestions;
     }
 
     /**
-     * @return locale of suggestions
+     * @return the locale of the suggestions
      */
     public String getLocale() {
         return mLocaleString;
diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java
index b6c5522..4987e2f 100644
--- a/core/java/android/view/GLES20Canvas.java
+++ b/core/java/android/view/GLES20Canvas.java
@@ -246,8 +246,19 @@
         return nIsBackBufferPreserved();
     }
 
-    private static native boolean nIsBackBufferPreserved();    
-    
+    private static native boolean nIsBackBufferPreserved();
+
+    /**
+     * Disables v-sync. For performance testing only.
+     * 
+     * @hide
+     */
+    public static void disableVsync() {
+        nDisableVsync();
+    }
+
+    private static native void nDisableVsync();
+
     @Override
     void onPreDraw(Rect dirty) {
         if (dirty != null) {
@@ -265,7 +276,7 @@
     void onPostDraw() {
         nFinish(mRenderer);
     }
-    
+
     private static native void nFinish(int renderer);
 
     @Override
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java
index bbfb4c1..1638c74 100644
--- a/core/java/android/view/HardwareRenderer.java
+++ b/core/java/android/view/HardwareRenderer.java
@@ -57,6 +57,16 @@
      * "false", to disable partial invalidates
      */
     static final String RENDER_DIRTY_REGIONS_PROPERTY = "hwui.render_dirty_regions";
+    
+    /**
+     * System property used to enable or disable vsync.
+     * The default value of this property is assumed to be false.
+     * 
+     * Possible values:
+     * "true", to disable vsync
+     * "false", to enable vsync
+     */
+    static final String DISABLE_VSYNC_PROPERTY = "hwui.disable_vsync";
 
     /**
      * Turn on to draw dirty regions every other frame.
@@ -118,8 +128,14 @@
     abstract void updateSurface(SurfaceHolder holder) throws Surface.OutOfResourcesException;
 
     /**
-     * Setup the hardware renderer for drawing. This is called for every
-     * frame to draw.
+     * Invoked whenever the size of the target surface changes. This will
+     * not be invoked when the surface is first created.
+     */
+    abstract void preapareSurfaceForResize();
+
+    /**
+     * Setup the hardware renderer for drawing. This is called whenever the
+     * size of the target surface changes or when the surface is first created.
      * 
      * @param width Width of the drawing surface.
      * @param height Height of the drawing surface.
@@ -279,9 +295,9 @@
     static abstract class GlRenderer extends HardwareRenderer {
         // These values are not exposed in our EGL APIs
         static final int EGL_CONTEXT_CLIENT_VERSION = 0x3098;
-        static final int EGL_SURFACE_TYPE = 0x3033;
-        static final int EGL_SWAP_BEHAVIOR_PRESERVED_BIT = 0x0400;
         static final int EGL_OPENGL_ES2_BIT = 4;
+        static final int EGL_SURFACE_TYPE = 0x3033;
+        static final int EGL_SWAP_BEHAVIOR_PRESERVED_BIT = 0x0400;        
 
         private static final int SURFACE_STATE_ERROR = 0;
         private static final int SURFACE_STATE_SUCCESS = 1;
@@ -301,8 +317,17 @@
         int mFrameCount;
         Paint mDebugPaint;
 
-        boolean mDirtyRegions;
-        final boolean mDirtyRegionsRequested;
+        static boolean sDirtyRegions;
+        static final boolean sDirtyRegionsRequested;
+        static {
+            String dirtyProperty = SystemProperties.get(RENDER_DIRTY_REGIONS_PROPERTY, "true");
+            //noinspection PointlessBooleanExpression,ConstantConditions
+            sDirtyRegions = RENDER_DIRTY_REGIONS && "true".equalsIgnoreCase(dirtyProperty);
+            sDirtyRegionsRequested = sDirtyRegions;
+        }
+
+        boolean mDirtyRegionsEnabled;
+        final boolean mVsyncDisabled;
 
         final int mGlVersion;
         final boolean mTranslucent;
@@ -314,17 +339,19 @@
         GlRenderer(int glVersion, boolean translucent) {
             mGlVersion = glVersion;
             mTranslucent = translucent;
-            final String dirtyProperty = SystemProperties.get(RENDER_DIRTY_REGIONS_PROPERTY, "true");
-            //noinspection PointlessBooleanExpression,ConstantConditions
-            mDirtyRegions = RENDER_DIRTY_REGIONS && "true".equalsIgnoreCase(dirtyProperty);
-            mDirtyRegionsRequested = mDirtyRegions;
+
+            final String vsyncProperty = SystemProperties.get(DISABLE_VSYNC_PROPERTY, "false");
+            mVsyncDisabled = "true".equalsIgnoreCase(vsyncProperty);
+            if (mVsyncDisabled) {
+                Log.d(LOG_TAG, "Disabling v-sync");
+            }
         }
 
         /**
          * Indicates whether this renderer instance can track and update dirty regions.
          */
         boolean hasDirtyRegions() {
-            return mDirtyRegions;
+            return mDirtyRegionsEnabled;
         }
 
         /**
@@ -461,8 +488,8 @@
             sEglConfig = chooseEglConfig();
             if (sEglConfig == null) {
                 // We tried to use EGL_SWAP_BEHAVIOR_PRESERVED_BIT, try again without
-                if (mDirtyRegions) {
-                    mDirtyRegions = false;
+                if (sDirtyRegions) {
+                    sDirtyRegions = false;
                     sEglConfig = chooseEglConfig();
                     if (sEglConfig == null) {
                         throw new RuntimeException("eglConfig not initialized");
@@ -482,7 +509,7 @@
         private EGLConfig chooseEglConfig() {
             int[] configsCount = new int[1];
             EGLConfig[] configs = new EGLConfig[1];
-            int[] configSpec = getConfig(mDirtyRegions);
+            int[] configSpec = getConfig(sDirtyRegions);
             if (!sEgl.eglChooseConfig(sEglDisplay, configSpec, configs, 1, configsCount)) {
                 throw new IllegalArgumentException("eglChooseConfig failed " +
                         getEGLErrorString(sEgl.eglGetError()));
@@ -548,18 +575,18 @@
 
             // If mDirtyRegions is set, this means we have an EGL configuration
             // with EGL_SWAP_BEHAVIOR_PRESERVED_BIT set
-            if (mDirtyRegions) {
-                if (!GLES20Canvas.preserveBackBuffer()) {
+            if (sDirtyRegions) {
+                if (!(mDirtyRegionsEnabled = GLES20Canvas.preserveBackBuffer())) {
                     Log.w(LOG_TAG, "Backbuffer cannot be preserved");
                 }
-            } else if (mDirtyRegionsRequested) {
+            } else if (sDirtyRegionsRequested) {
                 // If mDirtyRegions is not set, our EGL configuration does not
                 // have EGL_SWAP_BEHAVIOR_PRESERVED_BIT; however, the default
                 // swap behavior might be EGL_BUFFER_PRESERVED, which means we
                 // want to set mDirtyRegions. We try to do this only if dirty
                 // regions were initially requested as part of the device
                 // configuration (see RENDER_DIRTY_REGIONS)
-                mDirtyRegions = GLES20Canvas.isBackBufferPreserved();
+                mDirtyRegionsEnabled = GLES20Canvas.isBackBufferPreserved();
             }
 
             return sEglContext.getGL();
@@ -602,6 +629,14 @@
         }
 
         @Override
+        void preapareSurfaceForResize() {
+            // Cancels any existing buffer to ensure we'll get a buffer
+            // of the right size before we call eglSwapBuffers
+            sEgl.eglMakeCurrent(sEglDisplay, EGL10.EGL_NO_SURFACE,
+                    EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT);              
+        }
+
+        @Override
         void setup(int width, int height) {
             mCanvas.setViewport(width, height);
         }
@@ -765,6 +800,14 @@
         }
 
         @Override
+        void setup(int width, int height) {
+            super.setup(width, height);
+            if (mVsyncDisabled) {
+                GLES20Canvas.disableVsync();
+            }
+        }
+
+        @Override
         DisplayList createDisplayList(View v) {
             return new GLES20DisplayList(v);
         }
diff --git a/core/java/android/view/ViewAncestor.java b/core/java/android/view/ViewAncestor.java
index d70c798..c0619a5 100644
--- a/core/java/android/view/ViewAncestor.java
+++ b/core/java/android/view/ViewAncestor.java
@@ -1314,6 +1314,9 @@
             if (hwInitialized || ((windowShouldResize || params != null) &&
                     mAttachInfo.mHardwareRenderer != null &&
                     mAttachInfo.mHardwareRenderer.isEnabled())) {
+                if (!hwInitialized) {
+                    mAttachInfo.mHardwareRenderer.preapareSurfaceForResize();
+                }
                 mAttachInfo.mHardwareRenderer.setup(mWidth, mHeight);
             }
 
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 41412de..e6fdb17 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -46,7 +46,6 @@
 
 import java.util.ArrayList;
 import java.util.HashSet;
-import java.util.Locale;
 
 /**
  * <p>
@@ -5019,7 +5018,7 @@
      */
     @Override
     protected void resolveTextDirection() {
-        int resolvedTextDirection = TEXT_DIRECTION_UNDEFINED;
+        int resolvedTextDirection;
         switch(mTextDirection) {
             default:
             case TEXT_DIRECTION_INHERIT:
diff --git a/core/java/android/webkit/L10nUtils.java b/core/java/android/webkit/L10nUtils.java
index 4c42cde..f9d0067d 100644
--- a/core/java/android/webkit/L10nUtils.java
+++ b/core/java/android/webkit/L10nUtils.java
@@ -74,7 +74,8 @@
         com.android.internal.R.string.autofill_country_code_re,             // IDS_AUTOFILL_COUNTRY_CODE_RE
         com.android.internal.R.string.autofill_area_code_notext_re,         // IDS_AUTOFILL_AREA_CODE_NOTEXT_RE
         com.android.internal.R.string.autofill_phone_prefix_separator_re,   // IDS_AUTOFILL_PHONE_PREFIX_SEPARATOR_RE
-        com.android.internal.R.string.autofill_phone_suffix_separator_re    // IDS_AUTOFILL_PHONE_SUFFIX_SEPARATOR_RE
+        com.android.internal.R.string.autofill_phone_suffix_separator_re,   // IDS_AUTOFILL_PHONE_SUFFIX_SEPARATOR_RE
+        com.android.internal.R.string.credit_card_number_preview_format     // IDS_CREDIT_CARD_NUMBER_PREVIEW_FORMAT
     };
 
     private static Context mApplicationContext;
diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java
index 2145edd..c652e55 100644
--- a/core/java/android/webkit/WebViewCore.java
+++ b/core/java/android/webkit/WebViewCore.java
@@ -2240,6 +2240,10 @@
     }
 
     private void setupViewport(boolean updateViewState) {
+        if (mWebView == null || mSettings == null) {
+            // We've been destroyed or are being destroyed, return early
+            return;
+        }
         // set the viewport settings from WebKit
         setViewportSettingsFromNative();
 
diff --git a/core/java/android/webkit/ZoomManager.java b/core/java/android/webkit/ZoomManager.java
index 252fc8f..7d3f313 100644
--- a/core/java/android/webkit/ZoomManager.java
+++ b/core/java/android/webkit/ZoomManager.java
@@ -300,7 +300,7 @@
     }
 
     public final float getDefaultScale() {
-        return mDefaultScale;
+        return mInitialScale > 0 ? mInitialScale : mDefaultScale;
     }
 
     public final float getReadingLevelScale() {
@@ -1087,6 +1087,7 @@
             float scale;
             if (mInitialScale > 0) {
                 scale = mInitialScale;
+                mTextWrapScale = scale;
             } else if (viewState.mViewScale > 0) {
                 mTextWrapScale = viewState.mTextWrapScale;
                 scale = viewState.mViewScale;
@@ -1105,7 +1106,7 @@
             }
             boolean reflowText = false;
             if (!viewState.mIsRestored) {
-                if (settings.getUseFixedViewport()) {
+                if (settings.getUseFixedViewport() && mInitialScale == 0) {
                     // Override the scale only in case of fixed viewport.
                     scale = Math.max(scale, overviewScale);
                     mTextWrapScale = Math.max(mTextWrapScale, overviewScale);
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 772e8e9..1e63e26 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -16,6 +16,11 @@
 
 package android.widget;
 
+import com.android.internal.util.FastMath;
+import com.android.internal.widget.EditableInputConnection;
+
+import org.xmlpull.v1.XmlPullParserException;
+
 import android.R;
 import android.content.ClipData;
 import android.content.ClipData.Item;
@@ -62,6 +67,7 @@
 import android.text.TextPaint;
 import android.text.TextUtils;
 import android.text.TextWatcher;
+import android.text.method.AllCapsTransformationMethod;
 import android.text.method.ArrowKeyMovementMethod;
 import android.text.method.DateKeyListener;
 import android.text.method.DateTimeKeyListener;
@@ -76,6 +82,7 @@
 import android.text.method.TextKeyListener;
 import android.text.method.TimeKeyListener;
 import android.text.method.TransformationMethod;
+import android.text.method.TransformationMethod2;
 import android.text.method.WordIterator;
 import android.text.style.ClickableSpan;
 import android.text.style.ParagraphStyle;
@@ -125,11 +132,6 @@
 import android.view.inputmethod.InputMethodManager;
 import android.widget.RemoteViews.RemoteView;
 
-import com.android.internal.util.FastMath;
-import com.android.internal.widget.EditableInputConnection;
-
-import org.xmlpull.v1.XmlPullParserException;
-
 import java.io.IOException;
 import java.lang.ref.WeakReference;
 import java.text.BreakIterator;
@@ -424,6 +426,7 @@
         int textSize = 15;
         int typefaceIndex = -1;
         int styleIndex = -1;
+        boolean allCaps = false;
 
         /*
          * Look the appearance up without checking first if it exists because
@@ -471,6 +474,10 @@
                 case com.android.internal.R.styleable.TextAppearance_textStyle:
                     styleIndex = appearance.getInt(attr, -1);
                     break;
+
+                case com.android.internal.R.styleable.TextAppearance_textAllCaps:
+                    allCaps = appearance.getBoolean(attr, false);
+                    break;
                 }
             }
 
@@ -822,6 +829,10 @@
             case com.android.internal.R.styleable.TextView_suggestionsEnabled:
                 mSuggestionsEnabled = a.getBoolean(attr, true);
                 break;
+
+            case com.android.internal.R.styleable.TextView_textAllCaps:
+                allCaps = a.getBoolean(attr, false);
+                break;
             }
         }
         a.recycle();
@@ -1004,6 +1015,10 @@
         }
         setRawTextSize(textSize);
 
+        if (allCaps) {
+            setTransformationMethod(new AllCapsTransformationMethod(getContext()));
+        }
+
         if (password || passwordInputType || webPasswordInputType || numberPasswordInputType) {
             setTransformationMethod(PasswordTransformationMethod.getInstance());
             typefaceIndex = MONOSPACE;
@@ -1331,6 +1346,14 @@
 
         mTransformation = method;
 
+        if (method instanceof TransformationMethod2) {
+            TransformationMethod2 method2 = (TransformationMethod2) method;
+            mAllowTransformationLengthChange = !mTextIsSelectable && !(mText instanceof Editable);
+            method2.setLengthChangesAllowed(mAllowTransformationLengthChange);
+        } else {
+            mAllowTransformationLengthChange = false;
+        }
+
         setText(mText);
     }
 
@@ -1775,6 +1798,11 @@
 
         setTypefaceByIndex(typefaceIndex, styleIndex);
         
+        if (appearance.getBoolean(com.android.internal.R.styleable.TextAppearance_textAllCaps,
+                false)) {
+            setTransformationMethod(new AllCapsTransformationMethod(getContext()));
+        }
+
         appearance.recycle();
     }
 
@@ -2823,14 +2851,15 @@
         mBufferType = type;
         mText = text;
 
-        if (mTransformation == null)
+        if (mTransformation == null) {
             mTransformed = text;
-        else
+        } else {
             mTransformed = mTransformation.getTransformation(text, this);
+        }
 
         final int textLength = text.length();
 
-        if (text instanceof Spannable) {
+        if (text instanceof Spannable && !mAllowTransformationLengthChange) {
             Spannable sp = (Spannable) text;
 
             // Remove any ChangeWatchers that might have come
@@ -2852,7 +2881,6 @@
 
             if (mTransformation != null) {
                 sp.setSpan(mTransformation, 0, textLength, Spanned.SPAN_INCLUSIVE_INCLUSIVE);
-
             }
 
             if (mMovement != null) {
@@ -6570,6 +6598,26 @@
     }
 
     /**
+     * Sets the properties of this field to transform input to ALL CAPS
+     * display. This may use a "small caps" formatting if available.
+     * This setting will be ignored if this field is editable or selectable.
+     *
+     * This call replaces the current transformation method. Disabling this
+     * will not necessarily restore the previous behavior from before this
+     * was enabled.
+     *
+     * @see #setTransformationMethod(TransformationMethod)
+     * @attr ref android.R.styleable#TextView_textAllCaps
+     */
+    public void setAllCaps(boolean allCaps) {
+        if (allCaps) {
+            setTransformationMethod(new AllCapsTransformationMethod(getContext()));
+        } else {
+            setTransformationMethod(null);
+        }
+    }
+
+    /**
      * If true, sets the properties of this field (number of lines, horizontally scrolling,
      * transformation method) to be for a single-line input; if false, restores these to the default
      * conditions.
@@ -10254,6 +10302,7 @@
 
     private MovementMethod          mMovement;
     private TransformationMethod    mTransformation;
+    private boolean                 mAllowTransformationLengthChange;
     private ChangeWatcher           mChangeWatcher;
 
     private ArrayList<TextWatcher>  mListeners = null;
diff --git a/core/java/com/android/internal/util/Protocol.java b/core/java/com/android/internal/util/Protocol.java
index 2e7ec58..b754d94 100644
--- a/core/java/com/android/internal/util/Protocol.java
+++ b/core/java/com/android/internal/util/Protocol.java
@@ -26,6 +26,9 @@
  * codes with Message.what starting at Protocol.WIFI + 1 and less than or equal to Protocol.WIFI +
  * Protocol.MAX_MESSAGE
  *
+ * NOTE: After a value is created and source released a value shouldn't be changed to
+ * maintain backwards compatibility.
+ *
  * {@hide}
  */
 public class Protocol {
@@ -40,7 +43,7 @@
     public static final int BASE_DHCP                                               = 0x00030000;
     public static final int BASE_DATA_CONNECTION                                    = 0x00040000;
     public static final int BASE_DATA_CONNECTION_AC                                 = 0x00041000;
-    public static final int BASE_DATA_CONNECTION_TRACKER                            = 0x00050000;
+    public static final int BASE_DATA_CONNECTION_TRACKER                            = 0x00042000;
 
     //TODO: define all used protocols
 }
diff --git a/core/java/com/android/internal/view/menu/ActionMenuItemView.java b/core/java/com/android/internal/view/menu/ActionMenuItemView.java
index 3b497e4..09bebae 100644
--- a/core/java/com/android/internal/view/menu/ActionMenuItemView.java
+++ b/core/java/com/android/internal/view/menu/ActionMenuItemView.java
@@ -154,12 +154,7 @@
         // populate accessibility description with title
         setContentDescription(title);
 
-        if (mShowTextAllCaps && title != null) {
-            mTextButton.setText(title.toString().toUpperCase(
-                    getContext().getResources().getConfiguration().locale));
-        } else {
-            mTextButton.setText(mTitle);
-        }
+        mTextButton.setText(mTitle);
 
         updateTextButtonVisibility();
     }
diff --git a/core/java/com/android/internal/widget/ScrollingTabContainerView.java b/core/java/com/android/internal/widget/ScrollingTabContainerView.java
index 2f7adf0..40e5e8a 100644
--- a/core/java/com/android/internal/widget/ScrollingTabContainerView.java
+++ b/core/java/com/android/internal/widget/ScrollingTabContainerView.java
@@ -260,7 +260,6 @@
                     if (mTextView == null) {
                         TextView textView = new TextView(getContext(), null,
                                 com.android.internal.R.attr.actionBarTabTextStyle);
-                        textView.setSingleLine();
                         textView.setEllipsize(TruncateAt.END);
                         LayoutParams lp = new LayoutParams(LayoutParams.WRAP_CONTENT,
                                 LayoutParams.WRAP_CONTENT);
diff --git a/core/jni/android_net_NetUtils.cpp b/core/jni/android_net_NetUtils.cpp
index ddae505..d9bd50ea 100644
--- a/core/jni/android_net_NetUtils.cpp
+++ b/core/jni/android_net_NetUtils.cpp
@@ -26,7 +26,7 @@
 extern "C" {
 int ifc_enable(const char *ifname);
 int ifc_disable(const char *ifname);
-int ifc_reset_connections(const char *ifname);
+int ifc_reset_connections(const char *ifname, int reset_mask);
 
 int dhcp_do_request(const char *ifname,
                     const char *ipaddr,
@@ -90,12 +90,17 @@
     return (jint)result;
 }
 
-static jint android_net_utils_resetConnections(JNIEnv* env, jobject clazz, jstring ifname)
+static jint android_net_utils_resetConnections(JNIEnv* env, jobject clazz,
+      jstring ifname, jint mask)
 {
     int result;
 
     const char *nameStr = env->GetStringUTFChars(ifname, NULL);
-    result = ::ifc_reset_connections(nameStr);
+
+    LOGD("android_net_utils_resetConnections in env=%p clazz=%p iface=%s mask=0x%x\n",
+          env, clazz, nameStr, mask);
+
+    result = ::ifc_reset_connections(nameStr, mask);
     env->ReleaseStringUTFChars(ifname, nameStr);
     return (jint)result;
 }
@@ -206,7 +211,7 @@
 
     { "enableInterface", "(Ljava/lang/String;)I",  (void *)android_net_utils_enableInterface },
     { "disableInterface", "(Ljava/lang/String;)I",  (void *)android_net_utils_disableInterface },
-    { "resetConnections", "(Ljava/lang/String;)I",  (void *)android_net_utils_resetConnections },
+    { "resetConnections", "(Ljava/lang/String;I)I",  (void *)android_net_utils_resetConnections },
     { "runDhcp", "(Ljava/lang/String;Landroid/net/DhcpInfoInternal;)Z",  (void *)android_net_utils_runDhcp },
     { "runDhcpRenew", "(Ljava/lang/String;Landroid/net/DhcpInfoInternal;)Z",  (void *)android_net_utils_runDhcpRenew },
     { "stopDhcp", "(Ljava/lang/String;)Z",  (void *)android_net_utils_stopDhcp },
diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp
index 2106eb4..681f43f 100644
--- a/core/jni/android_view_GLES20Canvas.cpp
+++ b/core/jni/android_view_GLES20Canvas.cpp
@@ -115,6 +115,18 @@
     return error == EGL_SUCCESS && value == EGL_BUFFER_PRESERVED;
 }
 
+static void android_view_GLES20Canvas_disableVsync(JNIEnv* env, jobject clazz) {
+    EGLDisplay display = eglGetCurrentDisplay();
+
+    eglGetError();
+    eglSwapInterval(display, 0);
+
+    EGLint error = eglGetError();
+    if (error != EGL_SUCCESS) {
+        RENDERER_LOGD("Could not disable v-sync (%x)", error);
+    }
+}
+
 // ----------------------------------------------------------------------------
 // Constructors
 // ----------------------------------------------------------------------------
@@ -621,7 +633,7 @@
 
     if (layer) {
         jint* storage = env->GetIntArrayElements(layerInfo, NULL);
-        storage[0] = layer->texture;
+        storage[0] = layer->getTexture();
         env->ReleaseIntArrayElements(layerInfo, storage, 0);
     }
 
@@ -634,8 +646,8 @@
 
     if (layer) {
         jint* storage = env->GetIntArrayElements(layerInfo, NULL);
-        storage[0] = layer->width;
-        storage[1] = layer->height;
+        storage[0] = layer->getWidth();
+        storage[1] = layer->getHeight();
         env->ReleaseIntArrayElements(layerInfo, storage, 0);
     }
 
@@ -647,8 +659,8 @@
     LayerRenderer::resizeLayer(layer, width, height);
 
     jint* storage = env->GetIntArrayElements(layerInfo, NULL);
-    storage[0] = layer->width;
-    storage[1] = layer->height;
+    storage[0] = layer->getWidth();
+    storage[1] = layer->getHeight();
     env->ReleaseIntArrayElements(layerInfo, storage, 0);
 }
 
@@ -722,6 +734,7 @@
 #ifdef USE_OPENGL_RENDERER
     { "nIsBackBufferPreserved", "()Z",         (void*) android_view_GLES20Canvas_isBackBufferPreserved },
     { "nPreserveBackBuffer",    "()Z",         (void*) android_view_GLES20Canvas_preserveBackBuffer },
+    { "nDisableVsync",          "()V",         (void*) android_view_GLES20Canvas_disableVsync },
 
     { "nCreateRenderer",    "()I",             (void*) android_view_GLES20Canvas_createRenderer },
     { "nDestroyRenderer",   "(I)V",            (void*) android_view_GLES20Canvas_destroyRenderer },
diff --git a/core/res/res/layout-xlarge/activity_list.xml b/core/res/res/layout-xlarge/activity_list.xml
index ad485c1..5093a5e 100644
--- a/core/res/res/layout-xlarge/activity_list.xml
+++ b/core/res/res/layout-xlarge/activity_list.xml
@@ -54,21 +54,15 @@
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content" />
         </LinearLayout>
-        <ImageView android:id="@+id/titleDivider"
+        <View android:id="@+id/titleDivider"
             android:layout_width="match_parent"
-            android:layout_height="4dip"
-            android:layout_marginLeft="16dip"
-            android:layout_marginRight="16dip"
-            android:scaleType="fitXY"
-            android:gravity="fill_horizontal"
-            android:src="@android:drawable/divider_strong_holo" />
+            android:layout_height="2dip"
+            android:background="@android:color/holo_blue_light" />
         <!-- If the client uses a customTitle, it will be added here. -->
     </LinearLayout>
 
     <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
         android:layout_width="match_parent"
-        android:layout_marginLeft="32dip"
-        android:layout_marginRight="32dip"
         android:layout_height="0dip"
         android:layout_weight="1">
 
@@ -95,15 +89,12 @@
         android:minHeight="54dip"
         android:orientation="vertical"
         android:divider="?android:attr/dividerHorizontal"
-        android:showDividers="beginning"
-        android:dividerPadding="16dip">
+        android:showDividers="beginning">
         <LinearLayout
             style="?android:attr/buttonBarStyle"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:orientation="horizontal"
-            android:paddingLeft="2dip"
-            android:paddingRight="2dip"
             android:measureWithLargestChild="true">
             <LinearLayout android:id="@+id/leftSpacer"
                 android:layout_weight="0.25"
diff --git a/core/res/res/layout/activity_chooser_list_footer.xml b/core/res/res/layout/activity_chooser_list_footer.xml
index 7603a31..c05ba1a 100644
--- a/core/res/res/layout/activity_chooser_list_footer.xml
+++ b/core/res/res/layout/activity_chooser_list_footer.xml
@@ -23,13 +23,11 @@
     android:gravity="center"
     android:orientation="vertical">
 
-    <ImageView
+    <View
         android:id="@+id/divider"
         android:layout_width="match_parent"
         android:layout_height="2dip"
-        android:scaleType="fitXY"
-        android:gravity="fill_horizontal"
-        android:src="@drawable/divider_strong_holo" />
+        android:background="@android:color/holo_blue_light" />
 
     <TextView
         android:id="@+id/title"
diff --git a/core/res/res/layout/activity_chooser_list_header.xml b/core/res/res/layout/activity_chooser_list_header.xml
index 867014b9..0fb256f 100644
--- a/core/res/res/layout/activity_chooser_list_header.xml
+++ b/core/res/res/layout/activity_chooser_list_header.xml
@@ -32,12 +32,10 @@
         android:duplicateParentState="true"
         android:singleLine="true" />
 
-    <ImageView
+    <View
         android:id="@+id/divider"
         android:layout_width="match_parent"
         android:layout_height="2dip"
-        android:scaleType="fitXY"
-        android:gravity="fill_horizontal"
         android:src="@drawable/divider_strong_holo" />
 
 </LinearLayout>
diff --git a/core/res/res/layout/alert_dialog_holo.xml b/core/res/res/layout/alert_dialog_holo.xml
index 2185467..2b686bd 100644
--- a/core/res/res/layout/alert_dialog_holo.xml
+++ b/core/res/res/layout/alert_dialog_holo.xml
@@ -30,13 +30,11 @@
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:orientation="vertical">
-        <ImageView android:id="@+id/titleDividerTop"
+        <View android:id="@+id/titleDividerTop"
             android:layout_width="match_parent"
-            android:layout_height="1dip"
+            android:layout_height="2dip"
             android:visibility="gone"
-            android:scaleType="fitXY"
-            android:gravity="fill_horizontal"
-            android:src="@android:drawable/divider_strong_holo" />
+            android:background="@android:color/holo_blue_light" />
         <LinearLayout android:id="@+id/title_template"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
@@ -51,20 +49,17 @@
                 android:paddingRight="8dip"
                 android:src="@null" />
             <com.android.internal.widget.DialogTitle android:id="@+id/alertTitle"
-                style="?android:attr/textAppearanceLarge"
-                android:textColor="@android:color/holo_blue"
+                style="?android:attr/windowTitleStyle"
                 android:singleLine="true"
                 android:ellipsize="end"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content" />
         </LinearLayout>
-        <ImageView android:id="@+id/titleDivider"
+        <View android:id="@+id/titleDivider"
             android:layout_width="match_parent"
-            android:layout_height="1dip"
+            android:layout_height="2dip"
             android:visibility="gone"
-            android:scaleType="fitXY"
-            android:gravity="fill_horizontal"
-            android:src="@android:drawable/divider_strong_holo" />
+            android:background="@android:color/holo_blue_light" />
         <!-- If the client uses a customTitle, it will be added here. -->
     </LinearLayout>
 
diff --git a/core/res/res/layout/dialog_custom_title_holo.xml b/core/res/res/layout/dialog_custom_title_holo.xml
index 5261553..e2335a7 100644
--- a/core/res/res/layout/dialog_custom_title_holo.xml
+++ b/core/res/res/layout/dialog_custom_title_holo.xml
@@ -28,12 +28,10 @@
         android:gravity="center_vertical|left"
         style="?android:attr/windowTitleBackgroundStyle">
     </FrameLayout>
-    <ImageView android:id="@+id/titleDivider"
+    <View android:id="@+id/titleDivider"
             android:layout_width="match_parent"
-            android:layout_height="1dip"
-            android:scaleType="fitXY"
-            android:gravity="fill_horizontal"
-            android:src="@android:drawable/divider_strong_holo" />
+            android:layout_height="2dip"
+            android:background="@android:color/holo_blue_light" />
     <FrameLayout
         android:layout_width="match_parent" android:layout_height="wrap_content"
         android:layout_weight="1"
diff --git a/core/res/res/layout/dialog_title_holo.xml b/core/res/res/layout/dialog_title_holo.xml
index 400ef60..50bb0ba 100644
--- a/core/res/res/layout/dialog_title_holo.xml
+++ b/core/res/res/layout/dialog_title_holo.xml
@@ -30,12 +30,10 @@
         android:paddingLeft="16dip"
         android:paddingRight="16dip"
         android:gravity="center_vertical|left" />
-    <ImageView android:id="@+id/titleDivider"
+    <View android:id="@+id/titleDivider"
             android:layout_width="match_parent"
-            android:layout_height="1dip"
-            android:scaleType="fitXY"
-            android:gravity="fill_horizontal"
-            android:src="@android:drawable/divider_strong_holo" />
+            android:layout_height="2dip"
+            android:background="@android:color/holo_blue_light" />
     <FrameLayout
         android:layout_width="match_parent" android:layout_height="wrap_content"
         android:layout_weight="1"
diff --git a/core/res/res/layout/dialog_title_icons_holo.xml b/core/res/res/layout/dialog_title_icons_holo.xml
index f780ab0..7d7959f 100644
--- a/core/res/res/layout/dialog_title_icons_holo.xml
+++ b/core/res/res/layout/dialog_title_icons_holo.xml
@@ -48,12 +48,10 @@
             android:layout_marginLeft="8dip" />
     </LinearLayout>
 
-    <ImageView android:id="@+id/titleDivider"
+    <View android:id="@+id/titleDivider"
             android:layout_width="match_parent"
             android:layout_height="1dip"
-            android:scaleType="fitXY"
-            android:gravity="fill_horizontal"
-            android:src="@android:drawable/divider_strong_holo" />
+            android:background="@android:color/holo_blue_light" />
 
     <FrameLayout
         android:layout_width="match_parent" android:layout_height="wrap_content"
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 2cc8171..4bc59e4 100755
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -40,6 +40,21 @@
              to use accelerated drawing (thus setting state_accelerated), the
              cache hint is ignored and always assumed to be transparent. -->
         <attr name="colorBackgroundCacheHint" format="color" />
+
+        <!-- Default highlight color for items that are pressed. -->
+        <attr name="colorPressedHighlight" format="color" />
+        <!-- Default highlight color for items that are long-pressed. -->
+        <attr name="colorLongPressedHighlight" format="color" />
+        <!-- Default highlight color for items that are
+             focused. (Focused meaning cursor-based selection.) -->
+        <attr name="colorFocusedHighlight" format="color" />
+        <!-- Default highlight color for items that are
+             activated. (Activated meaning persistent selection.) -->
+        <attr name="colorActivatedHighlight" format="color" />
+        <!-- Default highlight color for items in multiple selection
+             mode. -->
+        <attr name="colorMultiSelectHighlight" format="color" />
+
         <!-- Default disabled alpha for widgets that set enabled/disabled alpha programmatically. -->
         <attr name="disabledAlpha" format="float" />
         <!-- Default background dim amount when a menu, dialog, or something similar pops up. -->
@@ -2810,6 +2825,8 @@
         <attr name="textColorHint" />
         <!-- Color of the links. -->
         <attr name="textColorLink" />
+        <!-- Present the text in ALL CAPS. This may use a small-caps form when available. -->
+        <attr name="textAllCaps" format="boolean" />
     </declare-styleable>
     <declare-styleable name="TextSwitcher">
     </declare-styleable>
@@ -3074,6 +3091,8 @@
         <attr name="textIsSelectable" />
         <!-- Suggestions will be displayed when the user double taps on editable text. -->
         <attr name="suggestionsEnabled" />
+        <!-- Present the text in ALL CAPS. This may use a small-caps form when available. -->
+        <attr name="textAllCaps" />
     </declare-styleable>
     <!-- An <code>input-extras</code> is a container for extra data to supply to
          an input method.  Contains
diff --git a/core/res/res/values/colors.xml b/core/res/res/values/colors.xml
index 2a1ebfc..631d8c6 100644
--- a/core/res/res/values/colors.xml
+++ b/core/res/res/values/colors.xml
@@ -143,19 +143,42 @@
     <color name="link_text_holo_light">#0000ee</color>
 
     <!-- Group buttons -->
+    <eat-comment />
     <color name="group_button_dialog_pressed_holo_dark">#46c5c1ff</color>
     <color name="group_button_dialog_focused_holo_dark">#2699cc00</color>
 
     <color name="group_button_dialog_pressed_holo_light">#ffffffff</color>
     <color name="group_button_dialog_focused_holo_light">#4699cc00</color>
 
+    <!-- Highlight colors for the legacy themes -->
+    <eat-comment />
+    <color name="legacy_pressed_highlight">#fffeaa0c</color>
+    <color name="legacy_selected_highlight">#fff17a0a</color>
+    <color name="legacy_long_pressed_highlight">#ffffffff</color>
+
     <!-- General purpose colors for Holo-themed elements -->
     <eat-comment />
 
-    <!-- A Holo shade of blue -->
-    <color name="holo_blue">#ff6699ff</color>
-    <!-- A Holo shade of green -->
-    <color name="holo_green">#ff99cc00</color>
+    <!-- A light Holo shade of blue -->
+    <color name="holo_blue_light">#ff33b5e5</color>
+    <!-- A light Holo shade of green -->
+    <color name="holo_green_light">#ff99cc00</color>
+    <!-- A light Holo shade of red -->
+    <color name="holo_red_light">#ffff4444</color>
+    <!-- A dark Holo shade of blue -->
+    <color name="holo_blue_dark">#ff0099cc</color>
+    <!-- A dark Holo shade of green -->
+    <color name="holo_green_dark">#ff669900</color>
+    <!-- A dark Holo shade of red -->
+    <color name="holo_red_dark">#ffcc0000</color>
+    <!-- A Holo shade of purple -->
+    <color name="holo_purple">#ffaa66cc</color>
+    <!-- A light Holo shade of orange -->
+    <color name="holo_orange_light">#ffffbb33</color>
+    <!-- A dark Holo shade of orange -->
+    <color name="holo_orange_dark">#ffff8800</color>
+    <!-- A really bright Holo shade of blue -->
+    <color name="holo_blue_bright">#ff00ddff</color>
 
 </resources>
 
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 2de9cd3..f7701f2 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -1779,6 +1779,14 @@
   <public type="attr" name="backgroundStacked" />
   <public type="attr" name="backgroundSplit" />
 
+  <public type="attr" name="textAllCaps" />
+
+  <public type="attr" name="colorPressedHighlight" />
+  <public type="attr" name="colorLongPressedHighlight" />
+  <public type="attr" name="colorFocusedHighlight" />
+  <public type="attr" name="colorActivatedHighlight" />
+  <public type="attr" name="colorMultiSelectHighlight" />
+
   <public type="style" name="TextAppearance.SuggestionHighlight" />
   <public type="style" name="Theme.Holo.SplitActionBarWhenNarrow" />
   <public type="style" name="Theme.Holo.Light.SplitActionBarWhenNarrow" />
@@ -1807,4 +1815,15 @@
   <public type="integer" name="status_bar_notification_info_maxnum" />
   <public type="string" name="status_bar_notification_info_overflow" />
 
+  <public type="color" name="holo_blue_light" />
+  <public type="color" name="holo_blue_dark" />
+  <public type="color" name="holo_green_light" />
+  <public type="color" name="holo_green_dark" />
+  <public type="color" name="holo_red_light" />
+  <public type="color" name="holo_red_dark" />
+  <public type="color" name="holo_orange_light" />
+  <public type="color" name="holo_orange_dark" />
+  <public type="color" name="holo_purple" />
+  <public type="color" name="holo_blue_bright" />
+
 </resources>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 50f8df7..97a8c0b 100755
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -2085,6 +2085,10 @@
     <!-- Do not translate. Regex used by AutoFill. -->
     <string name="autofill_phone_suffix_separator_re">^-$</string>
 
+    <!-- Do not translate. Regex used by AutoFill. -->
+    <!-- Ex: ************1234 -->
+    <string name="credit_card_number_preview_format">$1</string>
+
     <!-- Title of an application permission, listed so the user can choose whether
         they want to allow the application to do this. -->
     <string name="permlab_readHistoryBookmarks">read Browser\'s history and bookmarks</string>
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index 11016f4..a5cd6e3 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -1319,6 +1319,7 @@
         <item name="android:textSize">12sp</item>
         <item name="android:textStyle">bold</item>
         <item name="android:textColor">?android:attr/actionMenuTextColor</item>
+        <item name="android:textAllCaps">true</item>
     </style>
 
     <style name="TextAppearance.Holo.Widget.ActionMode">
@@ -1355,7 +1356,7 @@
 
     <style name="TextAppearance.Holo.DialogWindowTitle">
         <item name="android:textSize">22sp</item>
-        <item name="android:textColor">@android:color/holo_blue</item>
+        <item name="android:textColor">@android:color/holo_blue_light</item>
     </style>
 
     <style name="TextAppearance.Holo.CalendarViewWeekDayView" parent="TextAppearance.Small.CalendarViewWeekDayView">
@@ -1454,7 +1455,7 @@
 
     <style name="TextAppearance.Holo.Light.DialogWindowTitle">
         <item name="android:textSize">22sp</item>
-        <item name="android:textColor">@android:color/holo_blue</item>
+        <item name="android:textColor">@android:color/holo_blue_light</item>
     </style>
 
     <style name="TextAppearance.Holo.Light.CalendarViewWeekDayView" parent="TextAppearance.Small.CalendarViewWeekDayView">
@@ -1857,6 +1858,7 @@
         <item name="android:textColor">?android:attr/textColorPrimary</item>
         <item name="android:textSize">12sp</item>
         <item name="android:textStyle">bold</item>
+        <item name="android:textAllCaps">true</item>
     </style>
 
     <style name="Widget.Holo.ActionMode" parent="Widget.ActionMode">
diff --git a/core/res/res/values/themes.xml b/core/res/res/values/themes.xml
index 9a52cff..90f3602 100644
--- a/core/res/res/values/themes.xml
+++ b/core/res/res/values/themes.xml
@@ -31,6 +31,13 @@
         <item name="colorForegroundInverse">@android:color/bright_foreground_dark_inverse</item>
         <item name="colorBackground">@android:color/background_dark</item>
         <item name="colorBackgroundCacheHint">?android:attr/colorBackground</item>
+
+        <item name="colorPressedHighlight">@color/legacy_pressed_highlight</item>
+        <item name="colorLongPressedHighlight">@color/legacy_long_pressed_highlight</item>
+        <item name="colorFocusedHighlight">@color/legacy_selected_highlight</item>
+        <item name="colorMultiSelectHighlight">@color/legacy_selected_highlight</item>
+        <item name="colorActivatedHighlight">@color/legacy_selected_highlight</item>
+
         <item name="disabledAlpha">0.5</item>
         <item name="backgroundDimAmount">0.6</item>
 
@@ -799,6 +806,12 @@
         <item name="disabledAlpha">0.5</item>
         <item name="backgroundDimAmount">0.6</item>
 
+        <item name="colorPressedHighlight">@color/holo_blue_light</item>
+        <item name="colorLongPressedHighlight">@color/holo_blue_bright</item>
+        <item name="colorFocusedHighlight">@color/holo_blue_dark</item>
+        <item name="colorMultiSelectHighlight">@color/holo_green_light</item>
+        <item name="colorActivatedHighlight">@color/holo_blue_dark</item>
+
         <!-- Text styles -->
         <item name="textAppearance">@android:style/TextAppearance.Holo</item>
         <item name="textAppearanceInverse">@android:style/TextAppearance.Holo.Inverse</item>
@@ -1090,6 +1103,11 @@
         <item name="disabledAlpha">0.5</item>
         <item name="backgroundDimAmount">0.6</item>
 
+        <item name="colorPressedHighlight">@color/holo_blue_light</item>
+        <item name="colorLongPressedHighlight">@color/holo_blue_bright</item>
+        <item name="colorFocusedHighlight">@color/holo_blue_dark</item>
+        <item name="colorMultiSelectHighlight">@color/holo_green_light</item>
+        <item name="colorActivatedHighlight">@color/holo_blue_dark</item>
 
         <!-- Text styles -->
         <item name="textAppearance">@android:style/TextAppearance.Holo.Light</item>
diff --git a/docs/html/index.jd b/docs/html/index.jd
index eeeedd0..dce46f9 100644
--- a/docs/html/index.jd
+++ b/docs/html/index.jd
@@ -148,19 +148,18 @@
 
     'tv': {
       'layout':"imgLeft",
-      'icon':"tv_s.png",
+      'icon':"GTV_icon_small.png",
       'name':"Google TV",
-      'img':"tv_l.png",
-      'title':"Announcing Google TV!",
-      'desc': "<p><a href='http://www.google.com/tv/'>Google TV</a> is a new platform "
-               + "for television built on Android. Google "
-               + "has partnered with Sony and Logitech to integrate "
-               + "this platform into TVs, blu-ray players, and companion "
-               + "boxes. </p>"
-               + "<p><a href='http://www.google.com/tv/'>Learn more about "
-               + "Google TV &raquo;</a></p>"
+      'img':"GTV_icon_large.png",
+      'title':"Google TV!",
+      'desc': "<p>Build something big. By big, we mean <em>worthy-of-the-living-room</em> big.</p>"
+	        +  " <p>Use <a href='http://code.google.com/tv'>Google TV</a> to bring the power of Android" 
+	        +  " and Google Chrome to television."
+			+  " The average American watches five hours of TV per day. Give them the web and apps"
+			+  " to update their status, listen to music, watch web videos, and much more...</p>"
     },
 
+
     'devphone': {
       'layout':"imgLeft",
       'icon':"devphone-small.png",
diff --git a/docs/html/sdk/eclipse-adt.jd b/docs/html/sdk/eclipse-adt.jd
index b4f1b27..18f47a6 100644
--- a/docs/html/sdk/eclipse-adt.jd
+++ b/docs/html/sdk/eclipse-adt.jd
@@ -99,7 +99,7 @@
   <a href="#" onclick="return toggleDiv(this)">
         <img src="{@docRoot}assets/images/triangle-opened.png" class="toggle-img" height="9px"
 width="9px" />
-ADT 12.0.0</a> <em>(June 2011)</em>
+ADT 12.0.0</a> <em>(July 2011)</em>
   <div class="toggleme">
 <dl>
 
diff --git a/docs/html/sdk/tools-notes.jd b/docs/html/sdk/tools-notes.jd
index d4ebf8a..8c4d037 100644
--- a/docs/html/sdk/tools-notes.jd
+++ b/docs/html/sdk/tools-notes.jd
@@ -66,7 +66,7 @@
 <div class="toggleable opened">
   <a href="#" onclick="return toggleDiv(this)">
         <img src="{@docRoot}assets/images/triangle-opened.png" class="toggle-img" height="9px" width="9px" />
-SDK Tools, Revision 12</a> <em>(June 2011)</em>
+SDK Tools, Revision 12</a> <em>(July 2011)</em>
   <div class="toggleme">
   <dl>
 <dt>Dependencies:</dt>
diff --git a/graphics/java/android/graphics/Path.java b/graphics/java/android/graphics/Path.java
index 1324431..c5d7500 100644
--- a/graphics/java/android/graphics/Path.java
+++ b/graphics/java/android/graphics/Path.java
@@ -40,6 +40,7 @@
      */
     public Region rects;
     private boolean mDetectSimplePaths;
+    private Direction mLastDirection = null;
 
     /**
      * Create an empty path
@@ -70,6 +71,7 @@
     public void reset() {
         isSimplePath = true;
         if (mDetectSimplePaths) {
+            mLastDirection = null;
             if (rects != null) rects.setEmpty();
         }
         native_reset(mNativePath);
@@ -82,6 +84,7 @@
     public void rewind() {
         isSimplePath = true;
         if (mDetectSimplePaths) {
+            mLastDirection = null;
             if (rects != null) rects.setEmpty();
         }
         native_rewind(mNativePath);
@@ -378,6 +381,20 @@
         final int nativeInt;
     }
     
+    private void detectSimplePath(float left, float top, float right, float bottom, Direction dir) {
+        if (mDetectSimplePaths) {
+            if (mLastDirection == null) {
+                mLastDirection = dir;
+            }
+            if (mLastDirection != dir) {
+                isSimplePath = false;
+            } else {
+                if (rects == null) rects = new Region();
+                rects.op((int) left, (int) top, (int) right, (int) bottom, Region.Op.UNION);
+            }
+        }
+    }
+
     /**
      * Add a closed rectangle contour to the path
      *
@@ -388,11 +405,7 @@
         if (rect == null) {
             throw new NullPointerException("need rect parameter");
         }
-        if (mDetectSimplePaths) {
-            if (rects == null) rects = new Region();
-            rects.op((int) rect.left, (int) rect.top, (int) rect.right, (int) rect.bottom,
-                    Region.Op.UNION);
-        }
+        detectSimplePath(rect.left, rect.top, rect.right, rect.bottom, dir);
         native_addRect(mNativePath, rect, dir.nativeInt);
     }
 
@@ -406,10 +419,7 @@
      * @param dir    The direction to wind the rectangle's contour
      */
     public void addRect(float left, float top, float right, float bottom, Direction dir) {
-        if (mDetectSimplePaths) {
-            if (rects == null) rects = new Region();
-            rects.op((int) left, (int) top, (int) right, (int) bottom, Region.Op.UNION);
-        }
+        detectSimplePath(left, top, right, bottom, dir);
         native_addRect(mNativePath, left, top, right, bottom, dir.nativeInt);
     }
 
diff --git a/libs/hwui/Layer.h b/libs/hwui/Layer.h
index 0310bc3..3c2d80d 100644
--- a/libs/hwui/Layer.h
+++ b/libs/hwui/Layer.h
@@ -27,6 +27,7 @@
 
 #include "Rect.h"
 #include "SkiaColorFilter.h"
+#include "Texture.h"
 #include "Vertex.h"
 
 namespace android {
@@ -40,14 +41,18 @@
  * A layer has dimensions and is backed by an OpenGL texture or FBO.
  */
 struct Layer {
-    Layer(const uint32_t layerWidth, const uint32_t layerHeight):
-            width(layerWidth), height(layerHeight) {
+    Layer(const uint32_t layerWidth, const uint32_t layerHeight) {
         mesh = NULL;
         meshIndices = NULL;
         meshElementCount = 0;
-        isCacheable = true;
-        isTextureLayer = false;
+        cacheable = true;
+        textureLayer = false;
         renderTarget = GL_TEXTURE_2D;
+        texture.width = layerWidth;
+        texture.height = layerHeight;
+        colorFilter = NULL;
+        firstFilter = true;
+        firstWrap = true;
     }
 
     ~Layer() {
@@ -64,12 +69,152 @@
         regionRect.set(bounds.leftTop().x, bounds.leftTop().y,
                bounds.rightBottom().x, bounds.rightBottom().y);
 
-        const float texX = 1.0f / float(width);
-        const float texY = 1.0f / float(height);
+        const float texX = 1.0f / float(texture.width);
+        const float texY = 1.0f / float(texture.height);
         const float height = layer.getHeight();
         texCoords.set(
                regionRect.left * texX, (height - regionRect.top) * texY,
                regionRect.right * texX, (height - regionRect.bottom) * texY);
+
+        regionRect.translate(layer.left, layer.top);
+    }
+
+    inline uint32_t getWidth() {
+        return texture.width;
+    }
+
+    inline uint32_t getHeight() {
+        return texture.height;
+    }
+
+    void setSize(uint32_t width, uint32_t height) {
+        texture.width = width;
+        texture.height = height;
+    }
+
+    inline void setBlend(bool blend) {
+        texture.blend = blend;
+    }
+
+    inline bool isBlend() {
+        return texture.blend;
+    }
+
+    inline void setAlpha(int alpha) {
+        this->alpha = alpha;
+    }
+
+    inline void setAlpha(int alpha, SkXfermode::Mode mode) {
+        this->alpha = alpha;
+        this->mode = mode;
+    }
+
+    inline int getAlpha() {
+        return alpha;
+    }
+
+    inline SkXfermode::Mode getMode() {
+        return mode;
+    }
+
+    inline void setEmpty(bool empty) {
+        this->empty = empty;
+    }
+
+    inline bool isEmpty() {
+        return empty;
+    }
+
+    inline void setFbo(GLuint fbo) {
+        this->fbo = fbo;
+    }
+
+    inline GLuint getFbo() {
+        return fbo;
+    }
+
+    inline GLuint* getTexturePointer() {
+        return &texture.id;
+    }
+
+    inline GLuint getTexture() {
+        return texture.id;
+    }
+
+    inline GLenum getRenderTarget() {
+        return renderTarget;
+    }
+
+    inline void setRenderTarget(GLenum renderTarget) {
+        this->renderTarget = renderTarget;
+    }
+
+    void setWrap(GLenum wrapS, GLenum wrapT, bool bindTexture = false, bool force = false) {
+        if (firstWrap || force || wrapS != texture.wrapS || wrapT != texture.wrapT) {
+            firstWrap = true;
+            texture.setWrap(wrapS, wrapT);
+            if (bindTexture) {
+                glBindTexture(renderTarget, texture.id);
+            }
+            glTexParameteri(renderTarget, GL_TEXTURE_WRAP_S, wrapS);
+            glTexParameteri(renderTarget, GL_TEXTURE_WRAP_T, wrapT);
+        }
+    }
+
+    void setFilter(GLenum min, GLenum mag, bool bindTexture = false, bool force = false) {
+        if (firstFilter || force || min != texture.minFilter || mag != texture.magFilter) {
+            firstFilter = false;
+            texture.setFilter(min, mag);
+            if (bindTexture) {
+                glBindTexture(renderTarget, texture.id);
+            }
+            glTexParameteri(renderTarget, GL_TEXTURE_MIN_FILTER, min);
+            glTexParameteri(renderTarget, GL_TEXTURE_MAG_FILTER, mag);
+        }
+    }
+
+    inline bool isCacheable() {
+        return cacheable;
+    }
+
+    inline void setCacheable(bool cacheable) {
+        this->cacheable = cacheable;
+    }
+
+    inline bool isTextureLayer() {
+        return textureLayer;
+    }
+
+    inline void setTextureLayer(bool textureLayer) {
+        this->textureLayer = textureLayer;
+    }
+
+    inline SkiaColorFilter* getColorFilter() {
+        return colorFilter;
+    }
+
+    inline void setColorFilter(SkiaColorFilter* filter) {
+        colorFilter = filter;
+    }
+
+    inline void bindTexture() {
+        glBindTexture(renderTarget, texture.id);
+    }
+
+    inline void generateTexture() {
+        glGenTextures(1, &texture.id);
+    }
+
+    inline void deleteTexture() {
+        if (texture.id) glDeleteTextures(1, &texture.id);
+    }
+
+    inline void allocateTexture(GLenum format, GLenum storage) {
+        glTexImage2D(renderTarget, 0, format, getWidth(), getHeight(), 0, format, storage, NULL);
+    }
+
+    inline mat4& getTexTransform() {
+        return texTransform;
     }
 
     /**
@@ -82,43 +227,6 @@
     Rect texCoords;
 
     /**
-     * Name of the FBO used to render the layer. If the name is 0
-     * this layer is not backed by an FBO, but a simple texture.
-     */
-    GLuint fbo;
-
-    /**
-     * Opacity of the layer.
-     */
-    int alpha;
-    /**
-     * Blending mode of the layer.
-     */
-    SkXfermode::Mode mode;
-    /**
-     * Indicates whether this layer should be blended.
-     */
-    bool blend;
-
-    /**
-     * Indicates whether this layer has been used already.
-     */
-    bool empty;
-
-    /**
-     * Name of the texture used to render the layer.
-     */
-    GLuint texture;
-    /**
-     * Width of the layer texture.
-     */
-    uint32_t width;
-    /**
-     * Height of the layer texture.
-     */
-    uint32_t height;
-
-    /**
      * Dirty region indicating what parts of the layer
      * have been drawn.
      */
@@ -130,37 +238,66 @@
     Rect regionRect;
 
     /**
-     * Color filter used to draw this layer. Optional.
-     */
-    SkiaColorFilter* colorFilter;
-
-    /**
      * If the layer can be rendered as a mesh, this is non-null.
      */
     TextureVertex* mesh;
     uint16_t* meshIndices;
     GLsizei meshElementCount;
 
+private:
+    /**
+     * Name of the FBO used to render the layer. If the name is 0
+     * this layer is not backed by an FBO, but a simple texture.
+     */
+    GLuint fbo;
+
+    /**
+     * Indicates whether this layer has been used already.
+     */
+    bool empty;
+
+    /**
+     * The texture backing this layer.
+     */
+    Texture texture;
+
     /**
      * If set to true (by default), the layer can be reused.
      */
-    bool isCacheable;
+    bool cacheable;
 
     /**
      * When set to true, this layer must be treated as a texture
      * layer.
      */
-    bool isTextureLayer;
+    bool textureLayer;
+
+    /**
+     * Indicates the render target.
+     */
+    GLenum renderTarget;
+
+    /**
+     * Color filter used to draw this layer. Optional.
+     */
+    SkiaColorFilter* colorFilter;
+
+    /**
+     * Opacity of the layer.
+     */
+    int alpha;
+    /**
+     * Blending mode of the layer.
+     */
+    SkXfermode::Mode mode;
 
     /**
      * Optional texture coordinates transform.
      */
     mat4 texTransform;
 
-    /**
-     * Indicates the render target.
-     */
-    GLenum renderTarget;
+    bool firstFilter;
+    bool firstWrap;
 }; // struct Layer
 
 }; // namespace uirenderer
diff --git a/libs/hwui/LayerCache.cpp b/libs/hwui/LayerCache.cpp
index b2d795f..1a15e87 100644
--- a/libs/hwui/LayerCache.cpp
+++ b/libs/hwui/LayerCache.cpp
@@ -68,8 +68,8 @@
 
 void LayerCache::deleteLayer(Layer* layer) {
     if (layer) {
-        mSize -= layer->width * layer->height * 4;
-        glDeleteTextures(1, &layer->texture);
+        mSize -= layer->getWidth() * layer->getHeight() * 4;
+        layer->deleteTexture();
         delete layer;
     }
 }
@@ -93,29 +93,23 @@
         mCache.removeAt(index);
 
         layer = entry.mLayer;
-        mSize -= layer->width * layer->height * 4;
+        mSize -= layer->getWidth() * layer->getHeight() * 4;
 
-        LAYER_LOGD("Reusing layer %dx%d", layer->width, layer->height);
+        LAYER_LOGD("Reusing layer %dx%d", layer->getWidth(), layer->getHeight());
     } else {
         LAYER_LOGD("Creating new layer %dx%d", entry.mWidth, entry.mHeight);
 
         layer = new Layer(entry.mWidth, entry.mHeight);
-        layer->blend = true;
-        layer->empty = true;
-        layer->fbo = 0;
-        layer->colorFilter = NULL;
+        layer->setBlend(true);
+        layer->setEmpty(true);
+        layer->setFbo(0);
 
-        glGenTextures(1, &layer->texture);
-        glBindTexture(GL_TEXTURE_2D, layer->texture);
-
+        layer->generateTexture();
+        layer->bindTexture();
+        layer->setFilter(GL_NEAREST, GL_NEAREST);
+        layer->setWrap(GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE);
         glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
 
-        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-
-        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
-        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-
 #if DEBUG_LAYERS
         size_t size = mCache.size();
         for (size_t i = 0; i < size; i++) {
@@ -133,30 +127,30 @@
     //       size already in the cache, and reuse it instead of creating a new one
 
     LayerEntry entry(width, height);
-    if (entry.mWidth <= layer->width && entry.mHeight <= layer->height) {
+    if (entry.mWidth <= layer->getWidth() && entry.mHeight <= layer->getHeight()) {
         return true;
     }
 
-    glActiveTexture(GL_TEXTURE0);
-    glBindTexture(GL_TEXTURE_2D, layer->texture);
+    uint32_t oldWidth = layer->getWidth();
+    uint32_t oldHeight = layer->getHeight();
 
-    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, entry.mWidth, entry.mHeight, 0,
-            GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+    glActiveTexture(GL_TEXTURE0);
+    layer->bindTexture();
+    layer->setSize(entry.mWidth, entry.mHeight);
+    layer->allocateTexture(GL_RGBA, GL_UNSIGNED_BYTE);
 
     if (glGetError() != GL_NO_ERROR) {
+        layer->setSize(oldWidth, oldHeight);
         return false;
     }
 
-    layer->width = entry.mWidth;
-    layer->height = entry.mHeight;
-
     return true;
 }
 
 bool LayerCache::put(Layer* layer) {
-    if (!layer->isCacheable) return false;
+    if (!layer->isCacheable()) return false;
 
-    const uint32_t size = layer->width * layer->height * 4;
+    const uint32_t size = layer->getWidth() * layer->getHeight() * 4;
     // Don't even try to cache a layer that's bigger than the cache
     if (size < mMaxSize) {
         // TODO: Use an LRU
diff --git a/libs/hwui/LayerCache.h b/libs/hwui/LayerCache.h
index d2d5f39..81b8bf3 100644
--- a/libs/hwui/LayerCache.h
+++ b/libs/hwui/LayerCache.h
@@ -119,7 +119,7 @@
         }
 
         LayerEntry(Layer* layer):
-            mLayer(layer), mWidth(layer->width), mHeight(layer->height) {
+            mLayer(layer), mWidth(layer->getWidth()), mHeight(layer->getHeight()) {
         }
 
         bool operator<(const LayerEntry& rhs) const {
diff --git a/libs/hwui/LayerRenderer.cpp b/libs/hwui/LayerRenderer.cpp
index e034a868..1fa343b 100644
--- a/libs/hwui/LayerRenderer.cpp
+++ b/libs/hwui/LayerRenderer.cpp
@@ -32,9 +32,9 @@
 ///////////////////////////////////////////////////////////////////////////////
 
 void LayerRenderer::prepareDirty(float left, float top, float right, float bottom, bool opaque) {
-    LAYER_RENDERER_LOGD("Rendering into layer, fbo = %d", mLayer->fbo);
+    LAYER_RENDERER_LOGD("Rendering into layer, fbo = %d", mLayer->getFbo());
 
-    glBindFramebuffer(GL_FRAMEBUFFER, mLayer->fbo);
+    glBindFramebuffer(GL_FRAMEBUFFER, mLayer->getFbo());
 
     const float width = mLayer->layer.getWidth();
     const float height = mLayer->layer.getHeight();
@@ -62,14 +62,14 @@
 
     generateMesh();
 
-    LAYER_RENDERER_LOGD("Finished rendering into layer, fbo = %d", mLayer->fbo);
+    LAYER_RENDERER_LOGD("Finished rendering into layer, fbo = %d", mLayer->getFbo());
 
     // No need to unbind our FBO, this will be taken care of by the caller
     // who will invoke OpenGLRenderer::resume()
 }
 
 GLint LayerRenderer::getTargetFbo() {
-    return mLayer->fbo;
+    return mLayer->getFbo();
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -128,8 +128,8 @@
     }
     mLayer->meshElementCount = elementCount;
 
-    const float texX = 1.0f / float(mLayer->width);
-    const float texY = 1.0f / float(mLayer->height);
+    const float texX = 1.0f / float(mLayer->getWidth());
+    const float texY = 1.0f / float(mLayer->getHeight());
     const float height = mLayer->layer.getHeight();
 
     TextureVertex* mesh = mLayer->mesh;
@@ -182,40 +182,41 @@
         return NULL;
     }
 
-    layer->fbo = fbo;
+    layer->setFbo(fbo);
     layer->layer.set(0.0f, 0.0f, width, height);
-    layer->texCoords.set(0.0f, height / float(layer->height),
-            width / float(layer->width), 0.0f);
-    layer->alpha = 255;
-    layer->mode = SkXfermode::kSrcOver_Mode;
-    layer->blend = !isOpaque;
-    layer->colorFilter = NULL;
+    layer->texCoords.set(0.0f, height / float(layer->getHeight()),
+            width / float(layer->getWidth()), 0.0f);
+    layer->setAlpha(255, SkXfermode::kSrcOver_Mode);
+    layer->setBlend(!isOpaque);
+    layer->setColorFilter(NULL);
     layer->region.clear();
 
     GLuint previousFbo;
     glGetIntegerv(GL_FRAMEBUFFER_BINDING, (GLint*) &previousFbo);
 
-    glBindFramebuffer(GL_FRAMEBUFFER, layer->fbo);
-    glBindTexture(GL_TEXTURE_2D, layer->texture);
+    glBindFramebuffer(GL_FRAMEBUFFER, layer->getFbo());
+    layer->bindTexture();
 
     // Initialize the texture if needed
-    if (layer->empty) {
-        layer->empty = false;
-        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, layer->width, layer->height, 0,
-                GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+    if (layer->isEmpty()) {
+        layer->setEmpty(false);
+        layer->allocateTexture(GL_RGBA, GL_UNSIGNED_BYTE);
 
         if (glGetError() != GL_NO_ERROR) {
             LOGD("Could not allocate texture");
+
             glBindFramebuffer(GL_FRAMEBUFFER, previousFbo);
-            glDeleteTextures(1, &layer->texture);
             Caches::getInstance().fboCache.put(fbo);
+
+            layer->deleteTexture();
             delete layer;
+
             return NULL;
         }
     }
 
     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
-            layer->texture, 0);
+            layer->getTexture(), 0);
 
     glDisable(GL_SCISSOR_TEST);
     glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
@@ -229,14 +230,14 @@
 
 bool LayerRenderer::resizeLayer(Layer* layer, uint32_t width, uint32_t height) {
     if (layer) {
-        LAYER_RENDERER_LOGD("Resizing layer fbo = %d to %dx%d", layer->fbo, width, height);
+        LAYER_RENDERER_LOGD("Resizing layer fbo = %d to %dx%d", layer->getFbo(), width, height);
 
         if (Caches::getInstance().layerCache.resize(layer, width, height)) {
             layer->layer.set(0.0f, 0.0f, width, height);
-            layer->texCoords.set(0.0f, height / float(layer->height),
-                    width / float(layer->width), 0.0f);
+            layer->texCoords.set(0.0f, height / float(layer->getHeight()),
+                    width / float(layer->getWidth()), 0.0f);
         } else {
-            if (layer->texture) glDeleteTextures(1, &layer->texture);
+            layer->deleteTexture();
             delete layer;
             return false;
         }
@@ -245,37 +246,23 @@
     return true;
 }
 
-static void setTextureParameters(Layer* layer) {
-    glBindTexture(layer->renderTarget, layer->texture);
-
-    glTexParameteri(layer->renderTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-    glTexParameteri(layer->renderTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-
-    glTexParameteri(layer->renderTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
-    glTexParameteri(layer->renderTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-}
-
 Layer* LayerRenderer::createTextureLayer(bool isOpaque) {
     LAYER_RENDERER_LOGD("Creating new texture layer");
 
     Layer* layer = new Layer(0, 0);
-    layer->isCacheable = false;
-    layer->isTextureLayer = true;
-    layer->blend = !isOpaque;
-    layer->empty = true;
-    layer->fbo = 0;
-    layer->colorFilter = NULL;
-    layer->fbo = 0;
+    layer->setCacheable(false);
+    layer->setTextureLayer(true);
+    layer->setBlend(!isOpaque);
+    layer->setEmpty(true);
+    layer->setFbo(0);
+    layer->setAlpha(255, SkXfermode::kSrcOver_Mode);
     layer->layer.set(0.0f, 0.0f, 0.0f, 0.0f);
     layer->texCoords.set(0.0f, 1.0f, 0.0f, 1.0f);
-    layer->alpha = 255;
-    layer->mode = SkXfermode::kSrcOver_Mode;
-    layer->colorFilter = NULL;
     layer->region.clear();
-    layer->renderTarget = GL_NONE; // see ::updateTextureLayer()
+    layer->setRenderTarget(GL_NONE); // see ::updateTextureLayer()
 
     glActiveTexture(GL_TEXTURE0);
-    glGenTextures(1, &layer->texture);
+    layer->generateTexture();
 
     return layer;
 }
@@ -283,31 +270,32 @@
 void LayerRenderer::updateTextureLayer(Layer* layer, uint32_t width, uint32_t height,
         bool isOpaque, GLenum renderTarget, float* transform) {
     if (layer) {
-        layer->blend = !isOpaque;
-        layer->width = width;
-        layer->height = height;
+        layer->setBlend(!isOpaque);
+        layer->setSize(width, height);
         layer->layer.set(0.0f, 0.0f, width, height);
         layer->region.set(width, height);
         layer->regionRect.set(0.0f, 0.0f, width, height);
-        layer->texTransform.load(transform);
+        layer->getTexTransform().load(transform);
 
-        if (renderTarget != layer->renderTarget) {
-            layer->renderTarget = renderTarget;
-            setTextureParameters(layer);
+        if (renderTarget != layer->getRenderTarget()) {
+            layer->setRenderTarget(renderTarget);
+            layer->bindTexture();
+            layer->setFilter(GL_NEAREST, GL_NEAREST, false, true);
+            layer->setWrap(GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, false, true);
         }
     }
 }
 
 void LayerRenderer::destroyLayer(Layer* layer) {
     if (layer) {
-        LAYER_RENDERER_LOGD("Destroying layer, fbo = %d", layer->fbo);
+        LAYER_RENDERER_LOGD("Destroying layer, fbo = %d", layer->getFbo());
 
-        if (layer->fbo) {
-            Caches::getInstance().fboCache.put(layer->fbo);
+        if (layer->getFbo()) {
+            Caches::getInstance().fboCache.put(layer->getFbo());
         }
 
         if (!Caches::getInstance().layerCache.put(layer)) {
-            if (layer->texture) glDeleteTextures(1, &layer->texture);
+            layer->deleteTexture();
             delete layer;
         } else {
             layer->region.clear();
@@ -317,7 +305,7 @@
 
 void LayerRenderer::destroyLayerDeferred(Layer* layer) {
     if (layer) {
-        LAYER_RENDERER_LOGD("Deferring layer destruction, fbo = %d", layer->fbo);
+        LAYER_RENDERER_LOGD("Deferring layer destruction, fbo = %d", layer->getFbo());
 
         Caches::getInstance().deleteLayerDeferred(layer);
     }
@@ -325,7 +313,7 @@
 
 bool LayerRenderer::copyLayer(Layer* layer, SkBitmap* bitmap) {
     Caches& caches = Caches::getInstance();
-    if (layer && layer->isTextureLayer && bitmap->width() <= caches.maxTextureSize &&
+    if (layer && layer->isTextureLayer() && bitmap->width() <= caches.maxTextureSize &&
             bitmap->height() <= caches.maxTextureSize) {
 
         GLuint fbo = caches.fboCache.get();
@@ -365,12 +353,11 @@
                 break;
         }
 
-        float alpha = layer->alpha;
-        SkXfermode::Mode mode = layer->mode;
+        float alpha = layer->getAlpha();
+        SkXfermode::Mode mode = layer->getMode();
 
-        layer->mode = SkXfermode::kSrc_Mode;
-        layer->alpha = 255;
-        layer->fbo = fbo;
+        layer->setAlpha(255, SkXfermode::kSrc_Mode);
+        layer->setFbo(fbo);
 
         glGetIntegerv(GL_FRAMEBUFFER_BINDING, (GLint*) &previousFbo);
         glBindFramebuffer(GL_FRAMEBUFFER, fbo);
@@ -381,8 +368,8 @@
         glActiveTexture(GL_TEXTURE0);
         glBindTexture(GL_TEXTURE_2D, texture);
 
-        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
 
         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
@@ -399,7 +386,7 @@
             LayerRenderer renderer(layer);
             renderer.setViewport(bitmap->width(), bitmap->height());
             renderer.OpenGLRenderer::prepareDirty(0.0f, 0.0f,
-                    bitmap->width(), bitmap->height(), !layer->blend);
+                    bitmap->width(), bitmap->height(), !layer->isBlend());
             if ((error = glGetError()) != GL_NO_ERROR) goto error;
 
             {
@@ -424,9 +411,8 @@
 #endif
 
         glBindFramebuffer(GL_FRAMEBUFFER, previousFbo);
-        layer->mode = mode;
-        layer->alpha = alpha;
-        layer->fbo = 0;
+        layer->setAlpha(alpha, mode);
+        layer->setFbo(0);
         glDeleteTextures(1, &texture);
         caches.fboCache.put(fbo);
 
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 1c06a0b..a349121 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -449,12 +449,11 @@
         return false;
     }
 
-    layer->mode = mode;
-    layer->alpha = alpha;
+    layer->setAlpha(alpha, mode);
     layer->layer.set(bounds);
-    layer->texCoords.set(0.0f, bounds.getHeight() / float(layer->height),
-            bounds.getWidth() / float(layer->width), 0.0f);
-    layer->colorFilter = mColorFilter;
+    layer->texCoords.set(0.0f, bounds.getHeight() / float(layer->getHeight()),
+            bounds.getWidth() / float(layer->getWidth()), 0.0f);
+    layer->setColorFilter(mColorFilter);
 
     // Save the layer in the snapshot
     snapshot->flags |= Snapshot::kFlagIsLayer;
@@ -464,12 +463,13 @@
         return createFboLayer(layer, bounds, snapshot, previousFbo);
     } else {
         // Copy the framebuffer into the layer
-        glBindTexture(GL_TEXTURE_2D, layer->texture);
+        layer->bindTexture();
         if (!bounds.isEmpty()) {
-            if (layer->empty) {
-                glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, bounds.left,
-                        snapshot->height - bounds.bottom, layer->width, layer->height, 0);
-                layer->empty = false;
+            if (layer->isEmpty()) {
+                glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
+                        bounds.left, snapshot->height - bounds.bottom,
+                        layer->getWidth(), layer->getHeight(), 0);
+                layer->setEmpty(false);
             } else {
                 glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, bounds.left,
                         snapshot->height - bounds.bottom, bounds.getWidth(), bounds.getHeight());
@@ -485,7 +485,7 @@
 
 bool OpenGLRenderer::createFboLayer(Layer* layer, Rect& bounds, sp<Snapshot> snapshot,
         GLuint previousFbo) {
-    layer->fbo = mCaches.fboCache.get();
+    layer->setFbo(mCaches.fboCache.get());
 
 #if RENDER_LAYERS_AS_REGIONS
     snapshot->region = &snapshot->layer->region;
@@ -507,7 +507,7 @@
     clip.translate(-bounds.left, -bounds.top);
 
     snapshot->flags |= Snapshot::kFlagIsFboLayer;
-    snapshot->fbo = layer->fbo;
+    snapshot->fbo = layer->getFbo();
     snapshot->resetTransform(-bounds.left, -bounds.top, 0.0f);
     snapshot->resetClip(clip.left, clip.top, clip.right, clip.bottom);
     snapshot->viewport.set(0.0f, 0.0f, bounds.getWidth(), bounds.getHeight());
@@ -516,18 +516,17 @@
     snapshot->orthoMatrix.load(mOrthoMatrix);
 
     // Bind texture to FBO
-    glBindFramebuffer(GL_FRAMEBUFFER, layer->fbo);
-    glBindTexture(GL_TEXTURE_2D, layer->texture);
+    glBindFramebuffer(GL_FRAMEBUFFER, layer->getFbo());
+    layer->bindTexture();
 
     // Initialize the texture if needed
-    if (layer->empty) {
-        layer->empty = false;
-        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, layer->width, layer->height, 0,
-                GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+    if (layer->isEmpty()) {
+        layer->allocateTexture(GL_RGBA, GL_UNSIGNED_BYTE);
+        layer->setEmpty(false);
     }
 
     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
-            layer->texture, 0);
+            layer->getTexture(), 0);
 
 #if DEBUG_LAYERS_AS_REGIONS
     GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
@@ -535,8 +534,8 @@
         LOGE("Framebuffer incomplete (GL error code 0x%x)", status);
 
         glBindFramebuffer(GL_FRAMEBUFFER, previousFbo);
-        glDeleteTextures(1, &layer->texture);
-        mCaches.fboCache.put(layer->fbo);
+        layer->deleteTexture();
+        mCaches.fboCache.put(layer->getFbo());
 
         delete layer;
 
@@ -578,11 +577,11 @@
     Layer* layer = current->layer;
     const Rect& rect = layer->layer;
 
-    if (!fboLayer && layer->alpha < 255) {
+    if (!fboLayer && layer->getAlpha() < 255) {
         drawColorRect(rect.left, rect.top, rect.right, rect.bottom,
-                layer->alpha << 24, SkXfermode::kDstIn_Mode, true);
+                layer->getAlpha() << 24, SkXfermode::kDstIn_Mode, true);
         // Required below, composeLayerRect() will divide by 255
-        layer->alpha = 255;
+        layer->setAlpha(255);
     }
 
     mCaches.unbindMeshBuffer();
@@ -593,18 +592,16 @@
     // drawing only the dirty region
     if (fboLayer) {
         dirtyLayer(rect.left, rect.top, rect.right, rect.bottom, *previous->transform);
-        if (layer->colorFilter) {
-            setupColorFilter(layer->colorFilter);
+        if (layer->getColorFilter()) {
+            setupColorFilter(layer->getColorFilter());
         }
         composeLayerRegion(layer, rect);
-        if (layer->colorFilter) {
+        if (layer->getColorFilter()) {
             resetColorFilter();
         }
-    } else {
-        if (!rect.isEmpty()) {
-            dirtyLayer(rect.left, rect.top, rect.right, rect.bottom);
-            composeLayerRect(layer, rect, true);
-        }
+    } else if (!rect.isEmpty()) {
+        dirtyLayer(rect.left, rect.top, rect.right, rect.bottom);
+        composeLayerRect(layer, rect, true);
     }
 
     if (fboLayer) {
@@ -622,16 +619,16 @@
     // Failing to add the layer to the cache should happen only if the layer is too large
     if (!mCaches.layerCache.put(layer)) {
         LAYER_LOGD("Deleting layer");
-        glDeleteTextures(1, &layer->texture);
+        layer->deleteTexture();
         delete layer;
     }
 }
 
 void OpenGLRenderer::drawTextureLayer(Layer* layer, const Rect& rect) {
-    float alpha = layer->alpha / 255.0f;
+    float alpha = layer->getAlpha() / 255.0f;
 
     setupDraw();
-    if (layer->renderTarget == GL_TEXTURE_2D) {
+    if (layer->getRenderTarget() == GL_TEXTURE_2D) {
         setupDrawWithTexture();
     } else {
         setupDrawWithExternalTexture();
@@ -639,17 +636,28 @@
     setupDrawTextureTransform();
     setupDrawColor(alpha, alpha, alpha, alpha);
     setupDrawColorFilter();
-    setupDrawBlending(layer->blend || layer->alpha < 255, layer->mode);
+    setupDrawBlending(layer->isBlend() || alpha < 1.0f, layer->getMode());
     setupDrawProgram();
-    setupDrawModelView(rect.left, rect.top, rect.right, rect.bottom);
     setupDrawPureColorUniforms();
     setupDrawColorFilterUniforms();
-    if (layer->renderTarget == GL_TEXTURE_2D) {
-        setupDrawTexture(layer->texture);
+    if (layer->getRenderTarget() == GL_TEXTURE_2D) {
+        setupDrawTexture(layer->getTexture());
     } else {
-        setupDrawExternalTexture(layer->texture);
+        setupDrawExternalTexture(layer->getTexture());
     }
-    setupDrawTextureTransformUniforms(layer->texTransform);
+    if (mSnapshot->transform->isPureTranslate() &&
+            layer->getWidth() == (uint32_t) rect.getWidth() &&
+            layer->getHeight() == (uint32_t) rect.getHeight()) {
+        const float x = (int) floorf(rect.left + mSnapshot->transform->getTranslateX() + 0.5f);
+        const float y = (int) floorf(rect.top + mSnapshot->transform->getTranslateY() + 0.5f);
+
+        layer->setFilter(GL_NEAREST, GL_NEAREST);
+        setupDrawModelView(x, y, x + rect.getWidth(), y + rect.getHeight(), true);
+    } else {
+        layer->setFilter(GL_LINEAR, GL_LINEAR);
+        setupDrawModelView(rect.left, rect.top, rect.right, rect.bottom);
+    }
+    setupDrawTextureTransformUniforms(layer->getTexTransform());
     setupDrawMesh(&mMeshVertices[0].position[0], &mMeshVertices[0].texture[0]);
 
     glDrawArrays(GL_TRIANGLE_STRIP, 0, gMeshCount);
@@ -658,14 +666,34 @@
 }
 
 void OpenGLRenderer::composeLayerRect(Layer* layer, const Rect& rect, bool swap) {
-    if (!layer->isTextureLayer) {
+    if (!layer->isTextureLayer()) {
         const Rect& texCoords = layer->texCoords;
         resetDrawTextureTexCoords(texCoords.left, texCoords.top,
                 texCoords.right, texCoords.bottom);
 
-        drawTextureMesh(rect.left, rect.top, rect.right, rect.bottom, layer->texture,
-                layer->alpha / 255.0f, layer->mode, layer->blend, &mMeshVertices[0].position[0],
-                &mMeshVertices[0].texture[0], GL_TRIANGLE_STRIP, gMeshCount, swap, swap);
+        float x = rect.left;
+        float y = rect.top;
+        bool simpleTransform = mSnapshot->transform->isPureTranslate() &&
+                layer->getWidth() == (uint32_t) rect.getWidth() &&
+                layer->getHeight() == (uint32_t) rect.getHeight();
+
+        if (simpleTransform) {
+            // When we're swapping, the layer is already in screen coordinates
+            if (!swap) {
+                x = (int) floorf(rect.left + mSnapshot->transform->getTranslateX() + 0.5f);
+                y = (int) floorf(rect.top + mSnapshot->transform->getTranslateY() + 0.5f);
+            }
+
+            layer->setFilter(GL_NEAREST, GL_NEAREST, true);
+        } else {
+            layer->setFilter(GL_LINEAR, GL_LINEAR, true);
+        }
+
+        drawTextureMesh(x, y, x + rect.getWidth(), y + rect.getHeight(),
+                layer->getTexture(), layer->getAlpha() / 255.0f,
+                layer->getMode(), layer->isBlend(),
+                &mMeshVertices[0].position[0], &mMeshVertices[0].texture[0],
+                GL_TRIANGLE_STRIP, gMeshCount, swap, swap || simpleTransform);
 
         resetDrawTextureTexCoords(0.0f, 0.0f, 1.0f, 1.0f);
     } else {
@@ -690,9 +718,9 @@
         size_t count;
         const android::Rect* rects = layer->region.getArray(&count);
 
-        const float alpha = layer->alpha / 255.0f;
-        const float texX = 1.0f / float(layer->width);
-        const float texY = 1.0f / float(layer->height);
+        const float alpha = layer->getAlpha() / 255.0f;
+        const float texX = 1.0f / float(layer->getWidth());
+        const float texY = 1.0f / float(layer->getHeight());
         const float height = rect.getHeight();
 
         TextureVertex* mesh = mCaches.getRegionMesh();
@@ -702,13 +730,22 @@
         setupDrawWithTexture();
         setupDrawColor(alpha, alpha, alpha, alpha);
         setupDrawColorFilter();
-        setupDrawBlending(layer->blend || layer->alpha < 255, layer->mode, false);
+        setupDrawBlending(layer->isBlend() || alpha < 1.0f, layer->getMode(), false);
         setupDrawProgram();
         setupDrawDirtyRegionsDisabled();
         setupDrawPureColorUniforms();
         setupDrawColorFilterUniforms();
-        setupDrawTexture(layer->texture);
-        setupDrawModelViewTranslate(rect.left, rect.top, rect.right, rect.bottom);
+        setupDrawTexture(layer->getTexture());
+        if (mSnapshot->transform->isPureTranslate()) {
+            const float x = (int) floorf(rect.left + mSnapshot->transform->getTranslateX() + 0.5f);
+            const float y = (int) floorf(rect.top + mSnapshot->transform->getTranslateY() + 0.5f);
+
+            layer->setFilter(GL_NEAREST, GL_NEAREST);
+            setupDrawModelViewTranslate(x, y, x + rect.getWidth(), y + rect.getHeight(), true);
+        } else {
+            layer->setFilter(GL_LINEAR, GL_LINEAR);
+            setupDrawModelViewTranslate(rect.left, rect.top, rect.right, rect.bottom);
+        }
         setupDrawMesh(&mesh[0].position[0], &mesh[0].texture[0]);
 
         for (size_t i = 0; i < count; i++) {
@@ -2154,8 +2191,7 @@
     SkXfermode::Mode mode;
     getAlphaAndMode(paint, &alpha, &mode);
 
-    layer->alpha = alpha;
-    layer->mode = mode;
+    layer->setAlpha(alpha, mode);
 
 #if RENDER_LAYERS_AS_REGIONS
     if (!layer->region.isEmpty()) {
@@ -2169,13 +2205,23 @@
             setupDrawWithTexture();
             setupDrawColor(a, a, a, a);
             setupDrawColorFilter();
-            setupDrawBlending(layer->blend || layer->alpha < 255, layer->mode, false);
+            setupDrawBlending(layer->isBlend() || a < 1.0f, layer->getMode(), false);
             setupDrawProgram();
-            setupDrawModelViewTranslate(x, y,
-                    x + layer->layer.getWidth(), y + layer->layer.getHeight());
             setupDrawPureColorUniforms();
             setupDrawColorFilterUniforms();
-            setupDrawTexture(layer->texture);
+            setupDrawTexture(layer->getTexture());
+            if (mSnapshot->transform->isPureTranslate()) {
+                x = (int) floorf(x + mSnapshot->transform->getTranslateX() + 0.5f);
+                y = (int) floorf(y + mSnapshot->transform->getTranslateY() + 0.5f);
+
+                layer->setFilter(GL_NEAREST, GL_NEAREST);
+                setupDrawModelViewTranslate(x, y,
+                        x + layer->layer.getWidth(), y + layer->layer.getHeight(), true);
+            } else {
+                layer->setFilter(GL_LINEAR, GL_LINEAR);
+                setupDrawModelViewTranslate(x, y,
+                        x + layer->layer.getWidth(), y + layer->layer.getHeight());
+            }
             setupDrawMesh(&layer->mesh[0].position[0], &layer->mesh[0].texture[0]);
 
             glDrawElements(GL_TRIANGLES, layer->meshElementCount,
diff --git a/libs/hwui/ShapeCache.h b/libs/hwui/ShapeCache.h
index b048469..f4d9686 100644
--- a/libs/hwui/ShapeCache.h
+++ b/libs/hwui/ShapeCache.h
@@ -537,7 +537,7 @@
     const float pathWidth = fmax(bounds.width(), 1.0f);
     const float pathHeight = fmax(bounds.height(), 1.0f);
 
-    const float offset = fmax(paint->getStrokeWidth(), 1.0f) * 1.5f;
+    const float offset = (int) floorf(fmax(paint->getStrokeWidth(), 1.0f) * 1.5f + 0.5f);
 
     const uint32_t width = uint32_t(pathWidth + offset * 2.0 + 0.5);
     const uint32_t height = uint32_t(pathHeight + offset * 2.0 + 0.5);
diff --git a/libs/hwui/Texture.h b/libs/hwui/Texture.h
index 4922bb3..c6ae326 100644
--- a/libs/hwui/Texture.h
+++ b/libs/hwui/Texture.h
@@ -29,8 +29,22 @@
     Texture() {
         cleanup = false;
         bitmapSize = 0;
+
         wrapS = GL_CLAMP_TO_EDGE;
         wrapT = GL_CLAMP_TO_EDGE;
+
+        minFilter = GL_NEAREST;
+        magFilter = GL_NEAREST;
+    }
+
+    void setWrap(GLenum wrapS, GLenum wrapT) {
+        this->wrapS = wrapS;
+        this->wrapT = wrapT;
+    }
+
+    void setFilter(GLenum min, GLenum mag) {
+        minFilter = min;
+        magFilter = mag;
     }
 
     /**
@@ -67,6 +81,12 @@
      */
     GLenum wrapS;
     GLenum wrapT;
+
+    /**
+     * Last filters set on this texture. Defaults to GL_NEAREST.
+     */
+    GLenum minFilter;
+    GLenum magFilter;
 }; // struct Texture
 
 class AutoTexture {
diff --git a/libs/rs/driver/rsdGL.cpp b/libs/rs/driver/rsdGL.cpp
index 1f7bb0f..04446ad 100644
--- a/libs/rs/driver/rsdGL.cpp
+++ b/libs/rs/driver/rsdGL.cpp
@@ -99,9 +99,8 @@
 
     for (size_t j = 0; j < sizeof(names) / sizeof(names[0]); j++) {
         EGLint value = -1;
-        EGLint returnVal = eglGetConfigAttrib(dpy, config, names[j].attribute, &value);
-        EGLint error = eglGetError();
-        if (returnVal && error == EGL_SUCCESS) {
+        EGLBoolean returnVal = eglGetConfigAttrib(dpy, config, names[j].attribute, &value);
+        if (returnVal) {
             LOGV(" %s: %d (0x%x)", names[j].name, value, value);
         }
     }
@@ -169,6 +168,24 @@
     configAttribsPtr[1] = EGL_OPENGL_ES2_BIT;
     configAttribsPtr += 2;
 
+    configAttribsPtr[0] = EGL_RED_SIZE;
+    configAttribsPtr[1] = 8;
+    configAttribsPtr += 2;
+
+    configAttribsPtr[0] = EGL_GREEN_SIZE;
+    configAttribsPtr[1] = 8;
+    configAttribsPtr += 2;
+
+    configAttribsPtr[0] = EGL_BLUE_SIZE;
+    configAttribsPtr[1] = 8;
+    configAttribsPtr += 2;
+
+    if (rsc->mUserSurfaceConfig.alphaMin > 0) {
+        configAttribsPtr[0] = EGL_ALPHA_SIZE;
+        configAttribsPtr[1] = rsc->mUserSurfaceConfig.alphaMin;
+        configAttribsPtr += 2;
+    }
+
     if (rsc->mUserSurfaceConfig.depthMin > 0) {
         configAttribsPtr[0] = EGL_DEPTH_SIZE;
         configAttribsPtr[1] = rsc->mUserSurfaceConfig.depthMin;
@@ -191,16 +208,53 @@
     eglInitialize(dc->gl.egl.display, &dc->gl.egl.majorVersion, &dc->gl.egl.minorVersion);
     checkEglError("eglInitialize");
 
-    PixelFormat pf = PIXEL_FORMAT_RGBA_8888;
-    if (rsc->mUserSurfaceConfig.alphaMin == 0) {
-        pf = PIXEL_FORMAT_RGBX_8888;
+    EGLBoolean ret;
+
+    EGLint numConfigs = -1, n = 0;
+    ret = eglChooseConfig(dc->gl.egl.display, configAttribs, 0, 0, &numConfigs);
+    checkEglError("eglGetConfigs", ret);
+
+    if (numConfigs) {
+        EGLConfig* const configs = new EGLConfig[numConfigs];
+
+        ret = eglChooseConfig(dc->gl.egl.display,
+                configAttribs, configs, numConfigs, &n);
+        if (!ret || !n) {
+            checkEglError("eglChooseConfig", ret);
+            LOGE("%p, couldn't find an EGLConfig matching the screen format\n", rsc);
+        }
+
+        // The first config is guaranteed to over-satisfy the constraints
+        dc->gl.egl.config = configs[0];
+
+        // go through the list and skip configs that over-satisfy our needs
+        for (int i=0 ; i<n ; i++) {
+            if (rsc->mUserSurfaceConfig.alphaMin <= 0) {
+                EGLint alphaSize;
+                eglGetConfigAttrib(dc->gl.egl.display,
+                        configs[i], EGL_ALPHA_SIZE, &alphaSize);
+                if (alphaSize > 0) {
+                    continue;
+                }
+            }
+
+            if (rsc->mUserSurfaceConfig.depthMin <= 0) {
+                EGLint depthSize;
+                eglGetConfigAttrib(dc->gl.egl.display,
+                        configs[i], EGL_DEPTH_SIZE, &depthSize);
+                if (depthSize > 0) {
+                    continue;
+                }
+            }
+
+            // Found one!
+            dc->gl.egl.config = configs[i];
+            break;
+        }
+
+        delete [] configs;
     }
 
-    status_t err = EGLUtils::selectConfigForPixelFormat(dc->gl.egl.display, configAttribs,
-                                                        pf, &dc->gl.egl.config);
-    if (err) {
-       LOGE("%p, couldn't find an EGLConfig matching the screen format\n", rsc);
-    }
     //if (props.mLogVisual) {
     if (0) {
         printEGLConfiguration(dc->gl.egl.display, dc->gl.egl.config);
@@ -227,8 +281,8 @@
         return false;
     }
 
-    EGLBoolean ret = eglMakeCurrent(dc->gl.egl.display, dc->gl.egl.surfaceDefault,
-                                    dc->gl.egl.surfaceDefault, dc->gl.egl.context);
+    ret = eglMakeCurrent(dc->gl.egl.display, dc->gl.egl.surfaceDefault,
+                         dc->gl.egl.surfaceDefault, dc->gl.egl.context);
     if (ret == EGL_FALSE) {
         LOGE("eglMakeCurrent returned EGL_FALSE");
         checkEglError("eglMakeCurrent", ret);
diff --git a/libs/ui/EGLUtils.cpp b/libs/ui/EGLUtils.cpp
index f24a71d..020646b 100644
--- a/libs/ui/EGLUtils.cpp
+++ b/libs/ui/EGLUtils.cpp
@@ -24,6 +24,8 @@
 
 #include <EGL/egl.h>
 
+#include <system/graphics.h>
+
 #include <private/ui/android_natives_priv.h>
 
 // ----------------------------------------------------------------------------
@@ -67,31 +69,49 @@
         return BAD_VALUE;
     
     // Get all the "potential match" configs...
-    if (eglGetConfigs(dpy, NULL, 0, &numConfigs) == EGL_FALSE)
+    if (eglChooseConfig(dpy, attrs, 0, 0, &numConfigs) == EGL_FALSE)
         return BAD_VALUE;
 
-    EGLConfig* const configs = (EGLConfig*)malloc(sizeof(EGLConfig)*numConfigs);
-    if (eglChooseConfig(dpy, attrs, configs, numConfigs, &n) == EGL_FALSE) {
-        free(configs);
-        return BAD_VALUE;
-    }
-    
-    int i;
-    EGLConfig config = NULL;
-    for (i=0 ; i<n ; i++) {
-        EGLint nativeVisualId = 0;
-        eglGetConfigAttrib(dpy, configs[i], EGL_NATIVE_VISUAL_ID, &nativeVisualId);
-        if (nativeVisualId>0 && format == nativeVisualId) {
+    if (numConfigs) {
+        EGLConfig* const configs = new EGLConfig[numConfigs];
+        if (eglChooseConfig(dpy, attrs, configs, numConfigs, &n) == EGL_FALSE) {
+            delete [] configs;
+            return BAD_VALUE;
+        }
+
+        bool hasAlpha = false;
+        switch (format) {
+            case HAL_PIXEL_FORMAT_RGBA_8888:
+            case HAL_PIXEL_FORMAT_BGRA_8888:
+            case HAL_PIXEL_FORMAT_RGBA_5551:
+            case HAL_PIXEL_FORMAT_RGBA_4444:
+                hasAlpha = true;
+                break;
+        }
+
+        // The first config is guaranteed to over-satisfy the constraints
+        EGLConfig config = configs[0];
+
+        // go through the list and skip configs that over-satisfy our needs
+        int i;
+        for (i=0 ; i<n ; i++) {
+            if (!hasAlpha) {
+                EGLint alphaSize;
+                eglGetConfigAttrib(dpy, configs[i], EGL_ALPHA_SIZE, &alphaSize);
+                if (alphaSize > 0) {
+                    continue;
+                }
+            }
             config = configs[i];
             break;
         }
-    }
 
-    free(configs);
-    
-    if (i<n) {
-        *outConfig = config;
-        return NO_ERROR;
+        delete [] configs;
+
+        if (i<n) {
+            *outConfig = config;
+            return NO_ERROR;
+        }
     }
 
     return NAME_NOT_FOUND;
diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp
index b003476..223e0be 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.cpp
+++ b/media/libmediaplayerservice/StagefrightRecorder.cpp
@@ -1136,10 +1136,69 @@
         clipVideoFrameRate();
         clipVideoFrameWidth();
         clipVideoFrameHeight();
+        setDefaultProfileIfNecessary();
     }
     return OK;
 }
 
+// Set to use AVC baseline profile if the encoding parameters matches
+// CAMCORDER_QUALITY_LOW profile; this is for the sake of MMS service.
+void StagefrightRecorder::setDefaultProfileIfNecessary() {
+    LOGV("setDefaultProfileIfNecessary");
+
+    camcorder_quality quality = CAMCORDER_QUALITY_LOW;
+
+    int64_t durationUs   = mEncoderProfiles->getCamcorderProfileParamByName(
+                                "duration", mCameraId, quality) * 1000000LL;
+
+    int fileFormat       = mEncoderProfiles->getCamcorderProfileParamByName(
+                                "file.format", mCameraId, quality);
+
+    int videoCodec       = mEncoderProfiles->getCamcorderProfileParamByName(
+                                "vid.codec", mCameraId, quality);
+
+    int videoBitRate     = mEncoderProfiles->getCamcorderProfileParamByName(
+                                "vid.bps", mCameraId, quality);
+
+    int videoFrameRate   = mEncoderProfiles->getCamcorderProfileParamByName(
+                                "vid.fps", mCameraId, quality);
+
+    int videoFrameWidth  = mEncoderProfiles->getCamcorderProfileParamByName(
+                                "vid.width", mCameraId, quality);
+
+    int videoFrameHeight = mEncoderProfiles->getCamcorderProfileParamByName(
+                                "vid.height", mCameraId, quality);
+
+    int audioCodec       = mEncoderProfiles->getCamcorderProfileParamByName(
+                                "aud.codec", mCameraId, quality);
+
+    int audioBitRate     = mEncoderProfiles->getCamcorderProfileParamByName(
+                                "aud.bps", mCameraId, quality);
+
+    int audioSampleRate  = mEncoderProfiles->getCamcorderProfileParamByName(
+                                "aud.hz", mCameraId, quality);
+
+    int audioChannels    = mEncoderProfiles->getCamcorderProfileParamByName(
+                                "aud.ch", mCameraId, quality);
+
+    if (durationUs == mMaxFileDurationUs &&
+        fileFormat == mOutputFormat &&
+        videoCodec == mVideoEncoder &&
+        videoBitRate == mVideoBitRate &&
+        videoFrameRate == mFrameRate &&
+        videoFrameWidth == mVideoWidth &&
+        videoFrameHeight == mVideoHeight &&
+        audioCodec == mAudioEncoder &&
+        audioBitRate == mAudioBitRate &&
+        audioSampleRate == mSampleRate &&
+        audioChannels == mAudioChannels) {
+        if (videoCodec == VIDEO_ENCODER_H264) {
+            LOGI("Force to use AVC baseline profile");
+            setParamVideoEncoderProfile(OMX_VIDEO_AVCProfileBaseline);
+        }
+    }
+}
+
 status_t StagefrightRecorder::checkAudioEncoderCapabilities() {
     clipAudioBitRate();
     clipAudioSampleRate();
diff --git a/media/libmediaplayerservice/StagefrightRecorder.h b/media/libmediaplayerservice/StagefrightRecorder.h
index cb9c406..034b373 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.h
+++ b/media/libmediaplayerservice/StagefrightRecorder.h
@@ -174,6 +174,7 @@
     void clipAudioBitRate();
     void clipAudioSampleRate();
     void clipNumberOfAudioChannels();
+    void setDefaultProfileIfNecessary();
 
     StagefrightRecorder(const StagefrightRecorder &);
     StagefrightRecorder &operator=(const StagefrightRecorder &);
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index 1ac2c1f..06363ee 100644
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -1295,13 +1295,6 @@
     h264type.nAllowedPictureTypes =
         OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
 
-    h264type.nSliceHeaderSpacing = 0;
-    h264type.nBFrames = 0;   // No B frames support yet
-    h264type.nPFrames = setPFramesSpacing(iFramesInterval, frameRate);
-    if (h264type.nPFrames == 0) {
-        h264type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI;
-    }
-
     // Check profile and level parameters
     CodecProfileLevel defaultProfileLevel, profileLevel;
     defaultProfileLevel.mProfile = h264type.eProfile;
@@ -1312,8 +1305,14 @@
     h264type.eLevel = static_cast<OMX_VIDEO_AVCLEVELTYPE>(profileLevel.mLevel);
 
     if (h264type.eProfile == OMX_VIDEO_AVCProfileBaseline) {
+        h264type.nSliceHeaderSpacing = 0;
         h264type.bUseHadamard = OMX_TRUE;
         h264type.nRefFrames = 1;
+        h264type.nBFrames = 0;
+        h264type.nPFrames = setPFramesSpacing(iFramesInterval, frameRate);
+        if (h264type.nPFrames == 0) {
+            h264type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI;
+        }
         h264type.nRefIdx10ActiveMinus1 = 0;
         h264type.nRefIdx11ActiveMinus1 = 0;
         h264type.bEntropyCodingCABAC = OMX_FALSE;
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/VideoEditorAPITest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/VideoEditorAPITest.java
index 5120694..afe2001 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/VideoEditorAPITest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/VideoEditorAPITest.java
@@ -1335,16 +1335,19 @@
     @LargeTest
     public void testEffectKenBurn() throws Exception {
         // Test ken burn effect using a JPEG file.
-        testEffectKenBurn(INPUT_FILE_PATH + "IMG_640x480.jpg");
+        testEffectKenBurn(INPUT_FILE_PATH + "IMG_640x480.jpg",
+         "mediaImageItem1");
 
         // Test ken burn effect using a PNG file
-        testEffectKenBurn(INPUT_FILE_PATH + "IMG_640x480.png");
+        testEffectKenBurn(INPUT_FILE_PATH + "IMG_640x480.png",
+         "mediaImageItem2");
     }
 
-    private void testEffectKenBurn(final String imageItemFileName) throws Exception {
+    private void testEffectKenBurn(final String imageItemFileName,
+     final String MediaId) throws Exception {
         final int imageItemRenderingMode =MediaItem.RENDERING_MODE_BLACK_BORDER;
         final MediaImageItem mediaImageItem =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "mediaImageItem1",
+            mVideoEditorHelper.createMediaItem(mVideoEditor, MediaId,
             imageItemFileName, 5000, imageItemRenderingMode);
         mVideoEditor.addMediaItem(mediaImageItem);
 
diff --git a/opengl/tests/EGLTest/Android.mk b/opengl/tests/EGLTest/Android.mk
new file mode 100644
index 0000000..ab5f4bd
--- /dev/null
+++ b/opengl/tests/EGLTest/Android.mk
@@ -0,0 +1,41 @@
+# Build the unit tests.
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+ifneq ($(TARGET_SIMULATOR),true)
+
+LOCAL_MODULE := EGL_test
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_SRC_FILES := \
+    EGL_test.cpp \
+
+LOCAL_SHARED_LIBRARIES := \
+	libEGL \
+	libcutils \
+	libstlport \
+	libutils \
+
+LOCAL_STATIC_LIBRARIES := \
+	libgtest \
+	libgtest_main \
+
+LOCAL_C_INCLUDES := \
+    bionic \
+    bionic/libstdc++/include \
+    external/gtest/include \
+    external/stlport/stlport \
+
+include $(BUILD_EXECUTABLE)
+
+endif
+
+# Include subdirectory makefiles
+# ============================================================
+
+# If we're building with ONE_SHOT_MAKEFILE (mm, mmm), then what the framework
+# team really wants is to build the stuff defined by this makefile.
+ifeq (,$(ONE_SHOT_MAKEFILE))
+include $(call first-makefiles-under,$(LOCAL_PATH))
+endif
diff --git a/opengl/tests/EGLTest/EGL_test.cpp b/opengl/tests/EGLTest/EGL_test.cpp
new file mode 100644
index 0000000..337ad33
--- /dev/null
+++ b/opengl/tests/EGLTest/EGL_test.cpp
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+
+#include <utils/String8.h>
+
+#include <EGL/egl.h>
+
+namespace android {
+
+class EGLTest : public ::testing::Test {
+protected:
+    EGLDisplay mEglDisplay;
+
+protected:
+    EGLTest() :
+            mEglDisplay(EGL_NO_DISPLAY) {
+    }
+
+    virtual void SetUp() {
+        mEglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+        ASSERT_NE(EGL_NO_DISPLAY, mEglDisplay);
+        ASSERT_EQ(EGL_SUCCESS, eglGetError());
+
+        EGLint majorVersion;
+        EGLint minorVersion;
+        EXPECT_TRUE(eglInitialize(mEglDisplay, &majorVersion, &minorVersion));
+        ASSERT_EQ(EGL_SUCCESS, eglGetError());
+        RecordProperty("EglVersionMajor", majorVersion);
+        RecordProperty("EglVersionMajor", minorVersion);
+    }
+
+    virtual void TearDown() {
+        EGLBoolean success = eglTerminate(mEglDisplay);
+        ASSERT_EQ(EGL_TRUE, success);
+        ASSERT_EQ(EGL_SUCCESS, eglGetError());
+    }
+};
+
+TEST_F(EGLTest, DISABLED_EGLConfigEightBitFirst) {
+
+    EGLint numConfigs;
+    EGLConfig config;
+    EGLBoolean success;
+    EGLint attrs[] = {
+            EGL_SURFACE_TYPE,       EGL_WINDOW_BIT,
+            EGL_RENDERABLE_TYPE,    EGL_OPENGL_ES2_BIT,
+            EGL_NONE
+    };
+
+    success = eglChooseConfig(mEglDisplay, attrs, &config, 1, &numConfigs);
+    ASSERT_EQ(EGL_TRUE, success);
+    ASSERT_EQ(EGL_SUCCESS, eglGetError());
+    ASSERT_GE(numConfigs, 1);
+
+    EGLint components[3];
+
+    success = eglGetConfigAttrib(mEglDisplay, config, EGL_RED_SIZE, &components[0]);
+    ASSERT_EQ(EGL_TRUE, success);
+    ASSERT_EQ(EGL_SUCCESS, eglGetError());
+    success = eglGetConfigAttrib(mEglDisplay, config, EGL_GREEN_SIZE, &components[1]);
+    ASSERT_EQ(EGL_TRUE, success);
+    ASSERT_EQ(EGL_SUCCESS, eglGetError());
+    success = eglGetConfigAttrib(mEglDisplay, config, EGL_BLUE_SIZE, &components[2]);
+    ASSERT_EQ(EGL_TRUE, success);
+    ASSERT_EQ(EGL_SUCCESS, eglGetError());
+
+    EXPECT_GE(components[0], 8);
+    EXPECT_GE(components[1], 8);
+    EXPECT_GE(components[2], 8);
+}
+
+TEST_F(EGLTest, EGLConfigRGBA8888First) {
+
+    EGLint numConfigs;
+    EGLConfig config;
+    EGLBoolean success;
+    EGLint attrs[] = {
+            EGL_SURFACE_TYPE,       EGL_WINDOW_BIT,
+            EGL_RENDERABLE_TYPE,    EGL_OPENGL_ES2_BIT,
+            EGL_RED_SIZE,           8,
+            EGL_GREEN_SIZE,         8,
+            EGL_BLUE_SIZE,          8,
+            EGL_ALPHA_SIZE,         8,
+            EGL_NONE
+    };
+
+    success = eglChooseConfig(mEglDisplay, attrs, &config, 1, &numConfigs);
+    ASSERT_EQ(EGL_TRUE, success);
+    ASSERT_EQ(EGL_SUCCESS, eglGetError());
+    ASSERT_GE(numConfigs, 1);
+
+    EGLint components[4];
+
+    success = eglGetConfigAttrib(mEglDisplay, config, EGL_RED_SIZE, &components[0]);
+    ASSERT_EQ(EGL_TRUE, success);
+    ASSERT_EQ(EGL_SUCCESS, eglGetError());
+    success = eglGetConfigAttrib(mEglDisplay, config, EGL_GREEN_SIZE, &components[1]);
+    ASSERT_EQ(EGL_TRUE, success);
+    ASSERT_EQ(EGL_SUCCESS, eglGetError());
+    success = eglGetConfigAttrib(mEglDisplay, config, EGL_BLUE_SIZE, &components[2]);
+    ASSERT_EQ(EGL_TRUE, success);
+    ASSERT_EQ(EGL_SUCCESS, eglGetError());
+    success = eglGetConfigAttrib(mEglDisplay, config, EGL_ALPHA_SIZE, &components[3]);
+    ASSERT_EQ(EGL_TRUE, success);
+    ASSERT_EQ(EGL_SUCCESS, eglGetError());
+
+    EXPECT_GE(components[0], 8);
+    EXPECT_GE(components[1], 8);
+    EXPECT_GE(components[2], 8);
+    EXPECT_GE(components[3], 8);
+}
+
+
+}
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
index 47ab150..afe4246 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
@@ -16,17 +16,6 @@
 
 package com.android.providers.settings;
 
-import com.android.internal.content.PackageHelper;
-import com.android.internal.telephony.BaseCommands;
-import com.android.internal.telephony.Phone;
-import com.android.internal.telephony.RILConstants;
-import com.android.internal.util.XmlUtils;
-import com.android.internal.widget.LockPatternUtils;
-import com.android.internal.widget.LockPatternView;
-
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
 import android.content.ComponentName;
 import android.content.ContentValues;
 import android.content.Context;
@@ -47,6 +36,17 @@
 import android.text.TextUtils;
 import android.util.Log;
 
+import com.android.internal.content.PackageHelper;
+import com.android.internal.telephony.BaseCommands;
+import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.RILConstants;
+import com.android.internal.util.XmlUtils;
+import com.android.internal.widget.LockPatternUtils;
+import com.android.internal.widget.LockPatternView;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
 import java.io.IOException;
 import java.util.HashSet;
 import java.util.List;
@@ -63,7 +63,7 @@
     // database gets upgraded properly. At a minimum, please confirm that 'upgradeVersion'
     // is properly propagated through your change.  Not doing so will result in a loss of user
     // settings.
-    private static final int DATABASE_VERSION = 65;
+    private static final int DATABASE_VERSION = 66;
 
     private Context mContext;
 
@@ -839,6 +839,28 @@
             upgradeVersion = 65;
         }
 
+        if (upgradeVersion == 65) {
+            /*
+             * Animations are removed from Settings. Turned on by default
+             */
+            db.beginTransaction();
+            SQLiteStatement stmt = null;
+            try {
+                db.execSQL("DELETE FROM system WHERE name='"
+                        + Settings.System.WINDOW_ANIMATION_SCALE + "'");
+                db.execSQL("DELETE FROM system WHERE name='"
+                        + Settings.System.TRANSITION_ANIMATION_SCALE + "'");
+                stmt = db.compileStatement("INSERT INTO system(name,value)"
+                        + " VALUES(?,?);");
+                loadDefaultAnimationSettings(stmt);
+                db.setTransactionSuccessful();
+            } finally {
+                db.endTransaction();
+                if (stmt != null) stmt.close();
+            }
+            upgradeVersion = 66;
+        }
+
         // *** Remember to update DATABASE_VERSION above!
 
         if (upgradeVersion != currentVersion) {
diff --git a/packages/SystemUI/src/com/android/systemui/recent/Constants.java b/packages/SystemUI/src/com/android/systemui/recent/Constants.java
new file mode 100644
index 0000000..66f9292
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recent/Constants.java
@@ -0,0 +1,24 @@
+/*
+ * 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.systemui.recent;
+
+public class Constants {
+    static final int MAX_ESCAPE_ANIMATION_DURATION = 500; // in ms
+    static final float FADE_CONSTANT = 0.5f; // unitless
+    static final int SNAP_BACK_DURATION = 250; // in ms
+    static final int ESCAPE_VELOCITY = 100; // speed of item required to "curate" it in dp/s
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsHorizontalScrollView.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsHorizontalScrollView.java
index 3dbcc59..fb7a0a7 100644
--- a/packages/SystemUI/src/com/android/systemui/recent/RecentsHorizontalScrollView.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsHorizontalScrollView.java
@@ -25,6 +25,7 @@
 import android.animation.ValueAnimator;
 import android.animation.ValueAnimator.AnimatorUpdateListener;
 import android.content.Context;
+import android.content.res.Configuration;
 import android.database.DataSetObserver;
 import android.graphics.RectF;
 import android.util.AttributeSet;
@@ -33,6 +34,7 @@
 import android.view.MotionEvent;
 import android.view.VelocityTracker;
 import android.view.View;
+import android.view.ViewConfiguration;
 import android.view.animation.DecelerateInterpolator;
 import android.view.animation.LinearInterpolator;
 import android.widget.HorizontalScrollView;
@@ -42,12 +44,9 @@
 
 public class RecentsHorizontalScrollView extends HorizontalScrollView
         implements View.OnClickListener, View.OnTouchListener {
-    private static final float FADE_CONSTANT = 0.5f;
-    private static final int SNAP_BACK_DURATION = 250;
-    private static final int ESCAPE_VELOCITY = 100; // speed of item required to "curate" it
-    private static final String TAG = RecentsPanelView.TAG;
-    private static final float THRESHHOLD = 50;
     private static final boolean DEBUG_INVALIDATE = false;
+    private static final String TAG = RecentsPanelView.TAG;
+    private static final boolean DEBUG = RecentsPanelView.DEBUG;
     private LinearLayout mLinearLayout;
     private ActivityDescriptionAdapter mAdapter;
     private RecentsCallback mCallback;
@@ -56,6 +55,8 @@
     private float mLastY;
     private boolean mDragging;
     private VelocityTracker mVelocityTracker;
+    private float mDensityScale;
+    private float mPagingTouchSlop;
 
     public RecentsHorizontalScrollView(Context context) {
         this(context, null);
@@ -63,6 +64,8 @@
 
     public RecentsHorizontalScrollView(Context context, AttributeSet attrs) {
         super(context, attrs, 0);
+        mDensityScale = getResources().getDisplayMetrics().density;
+        mPagingTouchSlop = ViewConfiguration.get(mContext).getScaledPagingTouchSlop();
     }
 
     private int scrollPositionOfMostRecent() {
@@ -101,7 +104,8 @@
 
             case MotionEvent.ACTION_MOVE:
                 float delta = ev.getY() - mLastY;
-                if (Math.abs(delta) > THRESHHOLD) {
+                if (DEBUG) Log.v(TAG, "ACTION_MOVE : " + delta);
+                if (Math.abs(delta) > mPagingTouchSlop) {
                     mDragging = true;
                 }
                 break;
@@ -114,13 +118,14 @@
     }
 
     private float getAlphaForOffset(View view, float thumbHeight) {
-        final float fadeHeight = FADE_CONSTANT * thumbHeight;
+        final float fadeHeight = Constants.FADE_CONSTANT * thumbHeight;
         float result = 1.0f;
         if (view.getY() >= thumbHeight) {
             result = 1.0f - (view.getY() - thumbHeight) / fadeHeight;
         } else if (view.getY() < 0.0f) {
             result = 1.0f + (thumbHeight + view.getY()) / fadeHeight;
         }
+        if (DEBUG) Log.v(TAG, "FADE AMOUNT: " + result);
         return result;
     }
 
@@ -155,12 +160,13 @@
                     final float velocityY = velocityTracker.getYVelocity();
                     final float curY = animView.getY();
                     final float newY = (velocityY >= 0.0f ? 1 : -1) * animView.getHeight();
-
+                    final float maxVelocity = Constants.ESCAPE_VELOCITY * mDensityScale;
                     if (Math.abs(velocityY) > Math.abs(velocityX)
-                            && Math.abs(velocityY) > ESCAPE_VELOCITY
+                            && Math.abs(velocityY) > maxVelocity
                             && (velocityY >= 0.0f) == (animView.getY() >= 0)) {
-                        final long duration =
+                        long duration =
                             (long) (Math.abs(newY - curY) * 1000.0f / Math.abs(velocityY));
+                        duration = Math.min(duration, Constants.MAX_ESCAPE_ANIMATION_DURATION);
                         anim = ObjectAnimator.ofFloat(animView, "y", curY, newY);
                         anim.setInterpolator(new LinearInterpolator());
                         final int swipeDirection = animView.getY() >= 0.0f ?
@@ -181,9 +187,10 @@
                         });
                         anim.setDuration(duration);
                     } else { // Animate back to position
-                        final long duration = Math.abs(velocityY) > 0.0f ?
+                        long duration = Math.abs(velocityY) > 0.0f ?
                                 (long) (Math.abs(newY - curY) * 1000.0f / Math.abs(velocityY))
-                                : SNAP_BACK_DURATION;
+                                : Constants.SNAP_BACK_DURATION;
+                        duration = Math.min(duration, Constants.SNAP_BACK_DURATION);
                         anim = ObjectAnimator.ofFloat(animView, "y", animView.getY(), 0.0f);
                         anim.setInterpolator(new DecelerateInterpolator(2.0f));
                         anim.setDuration(duration);
@@ -241,8 +248,15 @@
         setOverScrollEffectPadding(leftPadding, 0);
     }
 
+    @Override
+    protected void onConfigurationChanged(Configuration newConfig) {
+        super.onConfigurationChanged(newConfig);
+        mDensityScale = getResources().getDisplayMetrics().density;
+        mPagingTouchSlop = ViewConfiguration.get(mContext).getScaledPagingTouchSlop();
+    }
+
     private void setOverScrollEffectPadding(int leftPadding, int i) {
-        // TODO Add to RecentsHorizontalScrollView
+        // TODO Add to (Vertical)ScrollView
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java
index 6190c9b..a55fe9c 100644
--- a/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsPanelView.java
@@ -417,11 +417,11 @@
         mActivityDescriptions = getRecentTasks();
         mListAdapter.notifyDataSetInvalidated();
         if (mActivityDescriptions.size() > 0) {
-            Log.v(TAG, "Showing " + mActivityDescriptions.size() + " apps");
+            if (DEBUG) Log.v(TAG, "Showing " + mActivityDescriptions.size() + " apps");
             updateUiElements(getResources().getConfiguration());
         } else {
             // Immediately hide this panel
-            Log.v(TAG, "Nothing to show");
+            if (DEBUG) Log.v(TAG, "Nothing to show");
             hide(false);
         }
     }
@@ -436,7 +436,7 @@
             paint.setAlpha(255);
             final int srcWidth = thumbnail.getWidth();
             final int srcHeight = thumbnail.getHeight();
-            Log.v(TAG, "Source thumb: " + srcWidth + "x" + srcHeight);
+            if (DEBUG) Log.v(TAG, "Source thumb: " + srcWidth + "x" + srcHeight);
             canvas.drawBitmap(thumbnail,
                     new Rect(0, 0, srcWidth-1, srcHeight-1),
                     new RectF(mGlowBitmapPaddingLeftPx, mGlowBitmapPaddingTopPx,
@@ -486,7 +486,7 @@
 
     public void handleSwipe(View view, int direction) {
         ActivityDescription ad = ((ViewHolder) view.getTag()).activityDescription;
-        Log.v(TAG, "Jettison " + ad.label);
+        if (DEBUG) Log.v(TAG, "Jettison " + ad.label);
         mActivityDescriptions.remove(ad);
 
         // Handled by widget containers to enable LayoutTransitions properly
diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentsVerticalScrollView.java b/packages/SystemUI/src/com/android/systemui/recent/RecentsVerticalScrollView.java
index 6a962cb..711ffa3 100644
--- a/packages/SystemUI/src/com/android/systemui/recent/RecentsVerticalScrollView.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/RecentsVerticalScrollView.java
@@ -25,6 +25,7 @@
 import android.animation.ValueAnimator;
 import android.animation.ValueAnimator.AnimatorUpdateListener;
 import android.content.Context;
+import android.content.res.Configuration;
 import android.database.DataSetObserver;
 import android.graphics.RectF;
 import android.util.AttributeSet;
@@ -33,6 +34,7 @@
 import android.view.MotionEvent;
 import android.view.VelocityTracker;
 import android.view.View;
+import android.view.ViewConfiguration;
 import android.view.animation.DecelerateInterpolator;
 import android.view.animation.LinearInterpolator;
 import android.widget.LinearLayout;
@@ -42,12 +44,9 @@
 
 public class RecentsVerticalScrollView extends ScrollView
         implements View.OnClickListener, View.OnTouchListener {
-    private static final float FADE_CONSTANT = 0.5f;
-    private static final int SNAP_BACK_DURATION = 250;
-    private static final int ESCAPE_VELOCITY = 100; // speed of item required to "curate" it
     private static final String TAG = RecentsPanelView.TAG;
-    private static final float THRESHHOLD = 50;
     private static final boolean DEBUG_INVALIDATE = false;
+    private static final boolean DEBUG = RecentsPanelView.DEBUG;
     private LinearLayout mLinearLayout;
     private ActivityDescriptionAdapter mAdapter;
     private RecentsCallback mCallback;
@@ -56,6 +55,8 @@
     private float mLastX;
     private boolean mDragging;
     private VelocityTracker mVelocityTracker;
+    private float mDensityScale;
+    private float mPagingTouchSlop;
 
     public RecentsVerticalScrollView(Context context) {
         this(context, null);
@@ -63,6 +64,8 @@
 
     public RecentsVerticalScrollView(Context context, AttributeSet attrs) {
         super(context, attrs, 0);
+        mDensityScale = getResources().getDisplayMetrics().density;
+        mPagingTouchSlop = ViewConfiguration.get(mContext).getScaledPagingTouchSlop();
     }
 
     private int scrollPositionOfMostRecent() {
@@ -101,8 +104,8 @@
 
             case MotionEvent.ACTION_MOVE:
                 float delta = ev.getX() - mLastX;
-                Log.v(TAG, "ACTION_MOVE : " + delta);
-                if (Math.abs(delta) > THRESHHOLD) {
+                if (DEBUG) Log.v(TAG, "ACTION_MOVE : " + delta);
+                if (Math.abs(delta) > mPagingTouchSlop) {
                     mDragging = true;
                 }
                 break;
@@ -115,14 +118,14 @@
     }
 
     private float getAlphaForOffset(View view, float thumbWidth) {
-        final float fadeWidth = FADE_CONSTANT * thumbWidth;
+        final float fadeWidth = Constants.FADE_CONSTANT * thumbWidth;
         float result = 1.0f;
         if (view.getX() >= thumbWidth) {
             result = 1.0f - (view.getX() - thumbWidth) / fadeWidth;
         } else if (view.getX() < 0.0f) {
             result = 1.0f + (thumbWidth + view.getX()) / fadeWidth;
         }
-        Log.v(TAG, "FADE AMOUNT: " + result);
+        if (DEBUG) Log.v(TAG, "FADE AMOUNT: " + result);
         return result;
     }
 
@@ -157,12 +160,13 @@
                     final float velocityY = velocityTracker.getYVelocity();
                     final float curX = animView.getX();
                     final float newX = (velocityX >= 0.0f ? 1 : -1) * animView.getWidth();
-
+                    final float maxVelocity = Constants.ESCAPE_VELOCITY * mDensityScale;
                     if (Math.abs(velocityX) > Math.abs(velocityY)
-                            && Math.abs(velocityX) > ESCAPE_VELOCITY
+                            && Math.abs(velocityX) > maxVelocity
                             && (velocityX > 0.0f) == (animView.getX() >= 0)) {
-                        final long duration =
+                        long duration =
                             (long) (Math.abs(newX-curX) * 1000.0f / Math.abs(velocityX));
+                        duration = Math.min(duration, Constants.MAX_ESCAPE_ANIMATION_DURATION);
                         anim = ObjectAnimator.ofFloat(animView, "x", curX, newX);
                         anim.setInterpolator(new LinearInterpolator());
                         final int swipeDirection = animView.getX() >= 0.0f ?
@@ -183,9 +187,10 @@
                         });
                         anim.setDuration(duration);
                     } else { // Animate back to position
-                        final long duration = Math.abs(velocityX) > 0.0f ?
+                        long duration = Math.abs(velocityX) > 0.0f ?
                                 (long) (Math.abs(newX-curX) * 1000.0f / Math.abs(velocityX))
-                                : SNAP_BACK_DURATION;
+                                : Constants.SNAP_BACK_DURATION;
+                        duration = Math.min(duration, Constants.SNAP_BACK_DURATION);
                         anim = ObjectAnimator.ofFloat(animView, "x", animView.getX(), 0.0f);
                         anim.setInterpolator(new DecelerateInterpolator(4.0f));
                         anim.setDuration(duration);
@@ -243,6 +248,13 @@
         setOverScrollEffectPadding(leftPadding, 0);
     }
 
+    @Override
+    protected void onConfigurationChanged(Configuration newConfig) {
+        super.onConfigurationChanged(newConfig);
+        mDensityScale = getResources().getDisplayMetrics().density;
+        mPagingTouchSlop = ViewConfiguration.get(mContext).getScaledPagingTouchSlop();
+    }
+
     private void setOverScrollEffectPadding(int leftPadding, int i) {
         // TODO Add to (Vertical)ScrollView
     }
diff --git a/services/audioflinger/AudioResamplerCubic.cpp b/services/audioflinger/AudioResamplerCubic.cpp
index 1d247bd..4d721f6 100644
--- a/services/audioflinger/AudioResamplerCubic.cpp
+++ b/services/audioflinger/AudioResamplerCubic.cpp
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+#define LOG_TAG "AudioSRC"
+
 #include <stdint.h>
 #include <string.h>
 #include <sys/types.h>
@@ -22,8 +24,6 @@
 #include "AudioResampler.h"
 #include "AudioResamplerCubic.h"
 
-#define LOG_TAG "AudioSRC"
-
 namespace android {
 // ----------------------------------------------------------------------------
 
diff --git a/services/java/com/android/server/BackupManagerService.java b/services/java/com/android/server/BackupManagerService.java
index 6afccec..786f2fa 100644
--- a/services/java/com/android/server/BackupManagerService.java
+++ b/services/java/com/android/server/BackupManagerService.java
@@ -224,6 +224,7 @@
         public PackageInfo pkgInfo;
         public int pmToken; // in post-install restore, the PM's token for this transaction
         public boolean needFullBackup;
+        public String[] filterSet;
 
         RestoreParams(IBackupTransport _transport, IRestoreObserver _obs,
                 long _token, PackageInfo _pkg, int _pmToken, boolean _needFullBackup) {
@@ -233,6 +234,7 @@
             pkgInfo = _pkg;
             pmToken = _pmToken;
             needFullBackup = _needFullBackup;
+            filterSet = null;
         }
 
         RestoreParams(IBackupTransport _transport, IRestoreObserver _obs, long _token,
@@ -243,6 +245,18 @@
             pkgInfo = null;
             pmToken = 0;
             needFullBackup = _needFullBackup;
+            filterSet = null;
+        }
+
+        RestoreParams(IBackupTransport _transport, IRestoreObserver _obs, long _token,
+                String[] _filterSet, boolean _needFullBackup) {
+            transport = _transport;
+            observer = _obs;
+            token = _token;
+            pkgInfo = null;
+            pmToken = 0;
+            needFullBackup = _needFullBackup;
+            filterSet = _filterSet;
         }
     }
 
@@ -404,7 +418,7 @@
                 Slog.d(TAG, "MSG_RUN_RESTORE observer=" + params.observer);
                 (new PerformRestoreTask(params.transport, params.observer,
                         params.token, params.pkgInfo, params.pmToken,
-                        params.needFullBackup)).run();
+                        params.needFullBackup, params.filterSet)).run();
                 break;
             }
 
@@ -3020,6 +3034,7 @@
         private File mStateDir;
         private int mPmToken;
         private boolean mNeedFullBackup;
+        private HashSet<String> mFilterSet;
 
         class RestoreRequest {
             public PackageInfo app;
@@ -3033,7 +3048,7 @@
 
         PerformRestoreTask(IBackupTransport transport, IRestoreObserver observer,
                 long restoreSetToken, PackageInfo targetPackage, int pmToken,
-                boolean needFullBackup) {
+                boolean needFullBackup, String[] filterSet) {
             mTransport = transport;
             mObserver = observer;
             mToken = restoreSetToken;
@@ -3041,6 +3056,15 @@
             mPmToken = pmToken;
             mNeedFullBackup = needFullBackup;
 
+            if (filterSet != null) {
+                mFilterSet = new HashSet<String>();
+                for (String pkg : filterSet) {
+                    mFilterSet.add(pkg);
+                }
+            } else {
+                mFilterSet = null;
+            }
+
             try {
                 mStateDir = new File(mBaseStateDir, transport.transportDirName());
             } catch (RemoteException e) {
@@ -3052,7 +3076,8 @@
             long startRealtime = SystemClock.elapsedRealtime();
             if (DEBUG) Slog.v(TAG, "Beginning restore process mTransport=" + mTransport
                     + " mObserver=" + mObserver + " mToken=" + Long.toHexString(mToken)
-                    + " mTargetPackage=" + mTargetPackage + " mPmToken=" + mPmToken);
+                    + " mTargetPackage=" + mTargetPackage + " mFilterSet=" + mFilterSet
+                    + " mPmToken=" + mPmToken);
 
             PackageManagerBackupAgent pmAgent = null;
             int error = -1; // assume error
@@ -3071,6 +3096,22 @@
 
                 List<PackageInfo> agentPackages = allAgentPackages();
                 if (mTargetPackage == null) {
+                    // if there's a filter set, strip out anything that isn't
+                    // present before proceeding
+                    if (mFilterSet != null) {
+                        for (int i = agentPackages.size() - 1; i >= 0; i--) {
+                            final PackageInfo pkg = agentPackages.get(i);
+                            if (! mFilterSet.contains(pkg.packageName)) {
+                                agentPackages.remove(i);
+                            }
+                        }
+                        if (DEBUG) {
+                            Slog.i(TAG, "Post-filter package set for restore:");
+                            for (PackageInfo p : agentPackages) {
+                                Slog.i(TAG, "    " + p);
+                            }
+                        }
+                    }
                     restorePackages.addAll(agentPackages);
                 } else {
                     // Just one package to attempt restore of
@@ -4266,6 +4307,67 @@
             return -1;
         }
 
+        public synchronized int restoreSome(long token, IRestoreObserver observer,
+                String[] packages) {
+            mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP,
+                    "performRestore");
+
+            if (DEBUG) {
+                StringBuilder b = new StringBuilder(128);
+                b.append("restoreSome token=");
+                b.append(Long.toHexString(token));
+                b.append(" observer=");
+                b.append(observer.toString());
+                b.append(" packages=");
+                if (packages == null) {
+                    b.append("null");
+                } else {
+                    b.append('{');
+                    boolean first = true;
+                    for (String s : packages) {
+                        if (!first) {
+                            b.append(", ");
+                        } else first = false;
+                        b.append(s);
+                    }
+                    b.append('}');
+                }
+                Slog.d(TAG, b.toString());
+            }
+
+            if (mEnded) {
+                throw new IllegalStateException("Restore session already ended");
+            }
+
+            if (mRestoreTransport == null || mRestoreSets == null) {
+                Slog.e(TAG, "Ignoring restoreAll() with no restore set");
+                return -1;
+            }
+
+            if (mPackageName != null) {
+                Slog.e(TAG, "Ignoring restoreAll() on single-package session");
+                return -1;
+            }
+
+            synchronized (mQueueLock) {
+                for (int i = 0; i < mRestoreSets.length; i++) {
+                    if (token == mRestoreSets[i].token) {
+                        long oldId = Binder.clearCallingIdentity();
+                        mWakelock.acquire();
+                        Message msg = mBackupHandler.obtainMessage(MSG_RUN_RESTORE);
+                        msg.obj = new RestoreParams(mRestoreTransport, observer, token,
+                                packages, true);
+                        mBackupHandler.sendMessage(msg);
+                        Binder.restoreCallingIdentity(oldId);
+                        return 0;
+                    }
+                }
+            }
+
+            Slog.w(TAG, "Restore token " + Long.toHexString(token) + " not found");
+            return -1;
+        }
+
         public synchronized int restorePackage(String packageName, IRestoreObserver observer) {
             if (DEBUG) Slog.v(TAG, "restorePackage pkg=" + packageName + " obs=" + observer);
 
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java
index b98d2a2..41450d2 100644
--- a/services/java/com/android/server/ConnectivityService.java
+++ b/services/java/com/android/server/ConnectivityService.java
@@ -1602,8 +1602,10 @@
             if (linkProperties != null) {
                 String iface = linkProperties.getInterfaceName();
                 if (TextUtils.isEmpty(iface) == false) {
-                    if (DBG) log("resetConnections(" + iface + ")");
-                    NetworkUtils.resetConnections(iface);
+                    if (DBG) {
+                        log("resetConnections(" + iface + ", NetworkUtils.RESET_ALL_ADDRESSES)");
+                    }
+                    NetworkUtils.resetConnections(iface, NetworkUtils.RESET_ALL_ADDRESSES);
                 }
             }
         }
diff --git a/services/surfaceflinger/DisplayHardware/DisplayHardware.cpp b/services/surfaceflinger/DisplayHardware/DisplayHardware.cpp
index 33125c4..7bf3e0a 100644
--- a/services/surfaceflinger/DisplayHardware/DisplayHardware.cpp
+++ b/services/surfaceflinger/DisplayHardware/DisplayHardware.cpp
@@ -99,6 +99,31 @@
             mMaxViewportDims[0] : mMaxViewportDims[1];
 }
 
+static status_t selectConfigForPixelFormat(
+        EGLDisplay dpy,
+        EGLint const* attrs,
+        PixelFormat format,
+        EGLConfig* outConfig)
+{
+    EGLConfig config = NULL;
+    EGLint numConfigs = -1, n=0;
+    eglGetConfigs(dpy, NULL, 0, &numConfigs);
+    EGLConfig* const configs = new EGLConfig[numConfigs];
+    eglChooseConfig(dpy, attrs, configs, numConfigs, &n);
+    for (int i=0 ; i<n ; i++) {
+        EGLint nativeVisualId = 0;
+        eglGetConfigAttrib(dpy, configs[i], EGL_NATIVE_VISUAL_ID, &nativeVisualId);
+        if (nativeVisualId>0 && format == nativeVisualId) {
+            *outConfig = configs[i];
+            delete [] configs;
+            return NO_ERROR;
+        }
+    }
+    delete [] configs;
+    return NAME_NOT_FOUND;
+}
+
+
 void DisplayHardware::init(uint32_t dpy)
 {
     mNativeWindow = new FramebufferNativeWindow();
@@ -108,6 +133,9 @@
         exit(0);
     }
 
+    int format;
+    ANativeWindow const * const window = mNativeWindow.get();
+    window->query(window, NATIVE_WINDOW_FORMAT, &format);
     mDpiX = mNativeWindow->xdpi;
     mDpiY = mNativeWindow->ydpi;
     mRefreshRate = fbDev->fps;
@@ -116,11 +144,13 @@
     EGLint numConfigs=0;
     EGLSurface surface;
     EGLContext context;
+    EGLBoolean result;
+    status_t err;
 
     // initialize EGL
     EGLint attribs[] = {
-            EGL_SURFACE_TYPE,   EGL_WINDOW_BIT,
-            EGL_NONE,           0,
+            EGL_SURFACE_TYPE,       EGL_WINDOW_BIT,
+            EGL_NONE,               0,
             EGL_NONE
     };
 
@@ -141,9 +171,8 @@
     eglInitialize(display, NULL, NULL);
     eglGetConfigs(display, NULL, 0, &numConfigs);
 
-    EGLConfig config;
-    status_t err = EGLUtils::selectConfigForNativeWindow(
-            display, attribs, mNativeWindow.get(), &config);
+    EGLConfig config = NULL;
+    err = selectConfigForPixelFormat(display, attribs, format, &config);
     LOGE_IF(err, "couldn't find an EGLConfig matching the screen format");
     
     EGLint r,g,b,a;
@@ -224,7 +253,11 @@
      * Gather OpenGL ES extensions
      */
 
-    eglMakeCurrent(display, surface, surface, context);
+    result = eglMakeCurrent(display, surface, surface, context);
+    if (!result) {
+        LOGE("Couldn't create a working GLES context. check logs. exiting...");
+        exit(0);
+    }
 
     GLExtensions& extensions(GLExtensions::getInstance());
     extensions.initWithGLStrings(
diff --git a/services/surfaceflinger/LayerBase.cpp b/services/surfaceflinger/LayerBase.cpp
index bcd8c83..c86c659 100644
--- a/services/surfaceflinger/LayerBase.cpp
+++ b/services/surfaceflinger/LayerBase.cpp
@@ -228,13 +228,18 @@
     const Layer::State& s(drawingState());
     const Transform tr(planeTransform * s.transform);
     const bool transformed = tr.transformed();
-   
+    const DisplayHardware& hw(graphicPlane(0).displayHardware());
+    const uint32_t hw_h = hw.getHeight();
+
     uint32_t w = s.w;
     uint32_t h = s.h;    
     tr.transform(mVertices[0], 0, 0);
     tr.transform(mVertices[1], 0, h);
     tr.transform(mVertices[2], w, h);
     tr.transform(mVertices[3], w, 0);
+    for (size_t i=0 ; i<4 ; i++)
+        mVertices[i][1] = hw_h - mVertices[i][1];
+
     if (UNLIKELY(transformed)) {
         // NOTE: here we could also punt if we have too many rectangles
         // in the transparent region
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index cccab4a..b0881a4 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -276,7 +276,8 @@
     glViewport(0, 0, w, h);
     glMatrixMode(GL_PROJECTION);
     glLoadIdentity();
-    glOrthof(0, w, h, 0, 0, 1);
+    // put the origin in the left-bottom corner
+    glOrthof(0, w, 0, h, 0, 1); // l=0, r=w ; b=0, t=h
 
     mReadyToRunBarrier.open();
 
@@ -1791,7 +1792,7 @@
     }
 
     GLfloat vtx[8];
-    const GLfloat texCoords[4][2] = { {0,v}, {0,0}, {u,0}, {u,v} };
+    const GLfloat texCoords[4][2] = { {0,1}, {0,1-v}, {u,1-v}, {u,1} };
     glBindTexture(GL_TEXTURE_2D, tname);
     glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
     glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
@@ -1800,6 +1801,22 @@
     glEnableClientState(GL_TEXTURE_COORD_ARRAY);
     glVertexPointer(2, GL_FLOAT, 0, vtx);
 
+    /*
+     * Texture coordinate mapping
+     *
+     *                 u
+     *    1 +----------+---+
+     *      |     |    |   |  image is inverted
+     *      |     V    |   |  w.r.t. the texture
+     *  1-v +----------+   |  coordinates
+     *      |              |
+     *      |              |
+     *      |              |
+     *    0 +--------------+
+     *      0              1
+     *
+     */
+
     class s_curve_interpolator {
         const float nbFrames, s, v;
     public:
@@ -1824,10 +1841,10 @@
             const GLfloat h = hw_h - (hw_h * v);
             const GLfloat x = (hw_w - w) * 0.5f;
             const GLfloat y = (hw_h - h) * 0.5f;
-            vtx[0] = x;         vtx[1] = y + h;
-            vtx[2] = x;         vtx[3] = y;
-            vtx[4] = x + w;     vtx[5] = y;
-            vtx[6] = x + w;     vtx[7] = y + h;
+            vtx[0] = x;         vtx[1] = y;
+            vtx[2] = x;         vtx[3] = y + h;
+            vtx[4] = x + w;     vtx[5] = y + h;
+            vtx[6] = x + w;     vtx[7] = y;
         }
     };
 
@@ -1842,15 +1859,20 @@
             const GLfloat h = 1.0f;
             const GLfloat x = (hw_w - w) * 0.5f;
             const GLfloat y = (hw_h - h) * 0.5f;
-            vtx[0] = x;         vtx[1] = y + h;
-            vtx[2] = x;         vtx[3] = y;
-            vtx[4] = x + w;     vtx[5] = y;
-            vtx[6] = x + w;     vtx[7] = y + h;
+            vtx[0] = x;         vtx[1] = y;
+            vtx[2] = x;         vtx[3] = y + h;
+            vtx[4] = x + w;     vtx[5] = y + h;
+            vtx[6] = x + w;     vtx[7] = y;
         }
     };
 
     // the full animation is 24 frames
-    const int nbFrames = 12;
+    char value[PROPERTY_VALUE_MAX];
+    property_get("debug.sf.electron_frames", value, "24");
+    int nbFrames = (atoi(value) + 1) >> 1;
+    if (nbFrames <= 0) // just in case
+        nbFrames = 24;
+
     s_curve_interpolator itr(nbFrames, 7.5f);
     s_curve_interpolator itg(nbFrames, 8.0f);
     s_curve_interpolator itb(nbFrames, 8.5f);
@@ -2225,10 +2247,11 @@
         // invert everything, b/c glReadPixel() below will invert the FB
         glViewport(0, 0, sw, sh);
         glScissor(0, 0, sw, sh);
+        glEnable(GL_SCISSOR_TEST);
         glMatrixMode(GL_PROJECTION);
         glPushMatrix();
         glLoadIdentity();
-        glOrthof(0, hw_w, 0, hw_h, 0, 1);
+        glOrthof(0, hw_w, hw_h, 0, 0, 1);
         glMatrixMode(GL_MODELVIEW);
 
         // redraw the screen entirely...
@@ -2244,6 +2267,7 @@
         }
 
         // XXX: this is needed on tegra
+        glEnable(GL_SCISSOR_TEST);
         glScissor(0, 0, sw, sh);
 
         // check for errors and return screen capture
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnection.java b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnection.java
index 9695344..1f24b58 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnection.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnection.java
@@ -76,8 +76,6 @@
                 + "' APN: '" + mApn.apn
                 + "' proxy: '" + mApn.proxy + "' port: '" + mApn.port);
 
-        setHttpProxy (mApn.proxy, mApn.port);
-
         createTime = -1;
         lastFailTime = -1;
         lastFailCause = FailCause.NONE;
@@ -152,38 +150,6 @@
         Log.d(LOG_TAG, "[" + getName() + "] " + s);
     }
 
-    private void setHttpProxy(String httpProxy, String httpPort) {
-
-        if (DBG) log("set http proxy for"
-                + "' APN: '" + mActiveApnType
-                + "' proxy: '" + mApn.proxy + "' port: '" + mApn.port);
-        if(TextUtils.equals(mActiveApnType, Phone.APN_TYPE_DEFAULT)) {
-            if (httpProxy == null || httpProxy.length() == 0) {
-                phone.setSystemProperty("net.gprs.http-proxy", null);
-                return;
-            }
-
-            if (httpPort == null || httpPort.length() == 0) {
-                httpPort = "8080";     // Default to port 8080
-            }
-
-            phone.setSystemProperty("net.gprs.http-proxy",
-                    "http://" + httpProxy + ":" + httpPort + "/");
-        } else {
-            if (httpProxy == null || httpProxy.length() == 0) {
-                phone.setSystemProperty("net.gprs.http-proxy." + mActiveApnType, null);
-                return;
-            }
-
-            if (httpPort == null || httpPort.length() == 0) {
-                httpPort = "8080";  // Default to port 8080
-            }
-
-            phone.setSystemProperty("net.gprs.http-proxy." + mActiveApnType,
-                    "http://" + httpProxy + ":" + httpPort + "/");
-        }
-    }
-
     private boolean isIpAddress(String address) {
         if (address == null) return false;
 
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
index fe57d0d..df5898b 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
@@ -1055,10 +1055,16 @@
                     }
                 }
                 if (!found) {
-                    // ApnContext does not have dcan reorted in data call list.
+                    // ApnContext does not have dcac reported in data call list.
+                    // Fetch all the ApnContexts that map to this dcac which are in
+                    // INITING state too.
                     if (DBG) log("onDataStateChanged(ar): Connected apn not found in the list (" +
                                  apnContext.toString() + ")");
-                    list.add(apnContext);
+                    if (apnContext.getDataConnectionAc() != null) {
+                        list.addAll(apnContext.getDataConnectionAc().getApnListSync());
+                    } else {
+                        list.add(apnContext);
+                    }
                 }
             }
         }
@@ -1110,10 +1116,12 @@
 
             Collection<ApnContext> apns = dcac.getApnListSync();
 
-            // filter out ApnContext with "Connected" state.
+            // filter out ApnContext with "Connected/Connecting" state.
             ArrayList<ApnContext> connectedApns = new ArrayList<ApnContext>();
             for (ApnContext apnContext : apns) {
-                if (apnContext.getState() == State.CONNECTED) {
+                if (apnContext.getState() == State.CONNECTED ||
+                       apnContext.getState() == State.CONNECTING ||
+                       apnContext.getState() == State.INITING) {
                     connectedApns.add(apnContext);
                 }
             }
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/GLTextureViewActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/GLTextureViewActivity.java
index e1ca756..949589f 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/GLTextureViewActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/GLTextureViewActivity.java
@@ -39,7 +39,10 @@
 import javax.microedition.khronos.egl.EGLDisplay;
 import javax.microedition.khronos.egl.EGLSurface;
 import javax.microedition.khronos.opengles.GL;
-
+import java.io.BufferedOutputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
 import java.nio.ByteBuffer;
 import java.nio.ByteOrder;
 import java.nio.FloatBuffer;
@@ -57,6 +60,25 @@
 
         mTextureView = new TextureView(this);
         mTextureView.setSurfaceTextureListener(this);
+        mTextureView.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                Bitmap b = mTextureView.getBitmap(800, 800);
+                BufferedOutputStream out = null;
+                try {
+                    out = new BufferedOutputStream(new FileOutputStream("/sdcard/out.png"));
+                    b.compress(Bitmap.CompressFormat.PNG, 100, out);
+                } catch (FileNotFoundException e) {
+                    e.printStackTrace();
+                } finally {
+                    if (out != null) try {
+                        out.close();
+                    } catch (IOException e) {
+                        e.printStackTrace();
+                    }
+                }
+            }
+        });
 
         setContentView(mTextureView, new FrameLayout.LayoutParams(
                 ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT,
@@ -77,7 +99,7 @@
         animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
             @Override
             public void onAnimationUpdate(ValueAnimator animation) {
-                ((View) mTextureView.getParent()).invalidate();
+                mTextureView.invalidate();
             }
         });
         animator.start();
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/TextureViewActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/TextureViewActivity.java
index c857ded..634e7e3a 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/TextureViewActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/TextureViewActivity.java
@@ -16,7 +16,6 @@
 
 package com.android.test.hwui;
 
-import android.animation.AnimatorSet;
 import android.app.Activity;
 import android.graphics.SurfaceTexture;
 import android.hardware.Camera;
@@ -34,7 +33,6 @@
     private Camera mCamera;
     private TextureView mTextureView;
     private FrameLayout mContent;
-    private AnimatorSet mAnimatorSet;
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
@@ -53,7 +51,6 @@
             @Override
             public void onClick(View v) {
                 if (mAdded) {
-                    if (mAnimatorSet != null) mAnimatorSet.cancel();
                     mContent.removeView(mTextureView);
                 } else {
                     mContent.addView(mTextureView);
@@ -62,7 +59,9 @@
             }
         });
 
-        mContent.addView(mTextureView, new FrameLayout.LayoutParams(500, 400, Gravity.CENTER));
+        mContent.addView(mTextureView, new FrameLayout.LayoutParams(
+                FrameLayout.LayoutParams.WRAP_CONTENT, FrameLayout.LayoutParams.WRAP_CONTENT,
+                Gravity.CENTER));
         mContent.addView(button, new FrameLayout.LayoutParams(
                 FrameLayout.LayoutParams.WRAP_CONTENT, FrameLayout.LayoutParams.WRAP_CONTENT,
                 Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM));
@@ -72,6 +71,9 @@
     @Override
     public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
         mCamera = Camera.open();
+        Camera.Size previewSize = mCamera.getParameters().getPreviewSize();
+        mTextureView.setLayoutParams(new FrameLayout.LayoutParams(
+                previewSize.width, previewSize.height, Gravity.CENTER));
 
         try {
             mCamera.setPreviewTexture(surface);
@@ -82,20 +84,6 @@
         mCamera.startPreview();
 
         mTextureView.setCameraDistance(5000);
-
-//        ObjectAnimator rotationY = ObjectAnimator.ofFloat(mTextureView, "rotationY", 0.0f, 360.0f);
-//        rotationY.setRepeatMode(ObjectAnimator.REVERSE);
-//        rotationY.setRepeatCount(ObjectAnimator.INFINITE);
-//        rotationY.setDuration(4000);
-
-//        ObjectAnimator alpha = ObjectAnimator.ofFloat(mTextureView, "alpha", 1.0f, 0.0f);
-//        alpha.setRepeatMode(ObjectAnimator.REVERSE);
-//        alpha.setRepeatCount(ObjectAnimator.INFINITE);
-//        alpha.setDuration(4000);
-
-//        mAnimatorSet = new AnimatorSet();
-//        mAnimatorSet.play(alpha).with(rotationY);
-//        mAnimatorSet.start();
     }
 
     @Override